From 8a682877febb2598a4586449ae232856ae97f105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Ko=C5=82odziejczyk?= Date: Tue, 23 Apr 2024 10:13:24 +0000 Subject: [PATCH 001/875] le_audio: Add missing object for Audio Profile Preferences This CL adds missing object parameter for jni native method parameters list. Tag: #bug Bug: 337196203 Flags: Exempt, trivial fix Test: mmm packages/modules/Bluetooth Change-Id: I33dd9495e13c8eb90c89ddca0996e31cd44a03fb --- android/app/jni/com_android_bluetooth_le_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/jni/com_android_bluetooth_le_audio.cpp b/android/app/jni/com_android_bluetooth_le_audio.cpp index f1d1136b3ed..802bb5d2e1f 100644 --- a/android/app/jni/com_android_bluetooth_le_audio.cpp +++ b/android/app/jni/com_android_bluetooth_le_audio.cpp @@ -688,7 +688,7 @@ static void setUnicastMonitorModeNative(JNIEnv* /* env */, jobject /* object */, sLeAudioClientInterface->SetUnicastMonitorMode(direction, enable); } -static void sendAudioProfilePreferencesNative(JNIEnv* /* env */, jint groupId, +static void sendAudioProfilePreferencesNative(JNIEnv* /* env */, jobject /* object */, jint groupId, jboolean isOutputPreferenceLeAudio, jboolean isDuplexPreferenceLeAudio) { std::shared_lock lock(interface_mutex); -- GitLab From f413dbe5b83f98939a0b173c87cd5edd0c1a5748 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Wed, 31 Jul 2024 17:33:15 +0800 Subject: [PATCH 002/875] hh: Don't transmit the whole UHID struct UHID struct is more than 4KB, but usually we only need a handful of bytes for each event. Bug: 356790330 Test: m -j Flag: EXEMPT refactorization Change-Id: I0ea5070d1fbe4fb74c77e6bbdd1269ffc9a10d37 --- system/bta/include/bta_hh_co.h | 2 +- system/btif/co/bta_hh_co.cc | 95 +++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 30 deletions(-) diff --git a/system/bta/include/bta_hh_co.h b/system/bta/include/bta_hh_co.h index 6ab199717a0..b291459f710 100644 --- a/system/bta/include/bta_hh_co.h +++ b/system/bta/include/bta_hh_co.h @@ -53,7 +53,7 @@ typedef struct { union { uhid_event uhid; }; -} tBTA_HH_TO_UHID_EVT; +} __attribute__((__packed__)) tBTA_HH_TO_UHID_EVT; /******************************************************************************* * diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index 0b0141c04ef..e7c723a0aed 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -64,7 +64,7 @@ static const bthh_report_type_t map_rtype_uhid_hh[] = {BTHH_FEATURE_REPORT, BTHH BTHH_INPUT_REPORT}; static void* btif_hh_poll_event_thread(void* arg); -static bool to_uhid_thread(int fd, const tBTA_HH_TO_UHID_EVT* ev); +static bool to_uhid_thread(int fd, const tBTA_HH_TO_UHID_EVT* ev, size_t data_len); void uhid_set_non_blocking(int fd) { int opts = fcntl(fd, F_GETFL); @@ -133,17 +133,51 @@ static bool uhid_set_report_req_handler(btif_hh_uhid_t* p_uhid, struct uhid_set_ } #endif // ENABLE_UHID_SET_REPORT +/* Calculate the minimum length required to send message to UHID */ +static size_t uhid_calc_msg_len(const struct uhid_event* ev, size_t var_len) { + switch (ev->type) { + // these messages don't have data following them, so just 4 bytes of type. + case UHID_DESTROY: + case UHID_STOP: + case UHID_OPEN: + case UHID_CLOSE: + return sizeof(ev->type); + // these messages has static length of data. + case UHID_START: + return sizeof(ev->type) + sizeof(ev->u.start); + case UHID_OUTPUT: + return sizeof(ev->type) + sizeof(ev->u.output); + case UHID_GET_REPORT: + return sizeof(ev->type) + sizeof(ev->u.get_report); + case UHID_SET_REPORT_REPLY: + return sizeof(ev->type) + sizeof(ev->u.set_report_reply); + // these messages has variable amount of data. We only need to write the + // necessary length. + case UHID_CREATE2: + return sizeof(ev->type) + sizeof(ev->u.create2) - HID_MAX_DESCRIPTOR_SIZE + var_len; + case UHID_INPUT2: + return sizeof(ev->type) + sizeof(ev->u.input2) - UHID_DATA_MAX + var_len; + case UHID_GET_REPORT_REPLY: + return sizeof(ev->type) + sizeof(ev->u.get_report_reply) - UHID_DATA_MAX + var_len; + case UHID_SET_REPORT: + return sizeof(ev->type) + sizeof(ev->u.set_report) - UHID_DATA_MAX + var_len; + default: + log::error("unknown uhid event type {}", ev->type); + return 0; + } +} + /*Internal function to perform UHID write and error checking*/ -static int uhid_write(int fd, const struct uhid_event* ev) { +static int uhid_write(int fd, const struct uhid_event* ev, size_t len) { ssize_t ret; - OSI_NO_INTR(ret = write(fd, ev, sizeof(*ev))); + OSI_NO_INTR(ret = write(fd, ev, len)); if (ret < 0) { int rtn = -errno; log::error("Cannot write to uhid:{}", strerror(errno)); return rtn; - } else if (ret != (ssize_t)sizeof(*ev)) { - log::error("Wrong size written to uhid: {} != {}", ret, sizeof(*ev)); + } else if (ret != (ssize_t)len) { + log::error("Wrong size written to uhid: {} != {}", ret, len); return -EFAULT; } @@ -157,7 +191,7 @@ static void uhid_flush_input_queue(btif_hh_uhid_t* p_uhid) { if (p_ev == nullptr) { break; } - uhid_write(p_uhid->fd, p_ev); + uhid_write(p_uhid->fd, p_ev, uhid_calc_msg_len(p_ev, p_ev->u.input2.size)); osi_free(p_ev); } } @@ -178,7 +212,7 @@ static void uhid_open_timeout(void* data) { // Notify the UHID thread that the timer has expired. log::verbose("UHID Open timeout evt"); ev.type = BTA_HH_UHID_INBOUND_OPEN_TIMEOUT_EVT; - to_uhid_thread(send_fd, &ev); + to_uhid_thread(send_fd, &ev, 0); } static void uhid_on_open(btif_hh_uhid_t* p_uhid) { @@ -199,13 +233,13 @@ static void uhid_on_open(btif_hh_uhid_t* p_uhid) { INT_TO_PTR(p_uhid->internal_send_fd)); } -static void uhid_queue_input(btif_hh_uhid_t* p_uhid, struct uhid_event* ev) { - struct uhid_event* p_ev = (struct uhid_event*)osi_malloc(sizeof(*ev)); +static void uhid_queue_input(btif_hh_uhid_t* p_uhid, struct uhid_event* ev, size_t len) { + struct uhid_event* p_ev = (struct uhid_event*)osi_malloc(len); if (!p_ev) { log::error("allocate uhid_event failed"); return; } - memcpy(p_ev, ev, sizeof(*p_ev)); + memcpy(p_ev, ev, len); if (!fixed_queue_try_enqueue(p_uhid->input_queue, (void*)p_ev)) { osi_free(p_ev); @@ -338,9 +372,9 @@ static int uhid_read_inbound_event(btif_hh_uhid_t* p_uhid) { switch (ev.type) { case BTA_HH_UHID_INBOUND_INPUT_EVT: if (p_uhid->ready_for_data) { - res = uhid_write(p_uhid->fd, &ev.uhid); + res = uhid_write(p_uhid->fd, &ev.uhid, ret - 1); } else { - uhid_queue_input(p_uhid, &ev.uhid); + uhid_queue_input(p_uhid, &ev.uhid, ret - 1); } break; case BTA_HH_UHID_INBOUND_OPEN_TIMEOUT_EVT: @@ -350,7 +384,7 @@ static int uhid_read_inbound_event(btif_hh_uhid_t* p_uhid) { res = 1; // any positive value indicates a normal close event break; case BTA_HH_UHID_INBOUND_DSCP_EVT: - res = uhid_write(p_uhid->fd, &ev.uhid); + res = uhid_write(p_uhid->fd, &ev.uhid, ret - 1); break; case BTA_HH_UHID_INBOUND_GET_REPORT_EVT: context = (uint32_t*)fixed_queue_try_dequeue(p_uhid->get_rpt_id_queue); @@ -359,7 +393,7 @@ static int uhid_read_inbound_event(btif_hh_uhid_t* p_uhid) { break; } ev.uhid.u.get_report_reply.id = *context; - res = uhid_write(p_uhid->fd, &ev.uhid); + res = uhid_write(p_uhid->fd, &ev.uhid, ret - 1); osi_free(context); break; #if ENABLE_UHID_SET_REPORT @@ -370,7 +404,7 @@ static int uhid_read_inbound_event(btif_hh_uhid_t* p_uhid) { break; } ev.uhid.u.set_report_reply.id = *context; - res = uhid_write(p_uhid->fd, &ev.uhid); + res = uhid_write(p_uhid->fd, &ev.uhid, ret - 1); osi_free(context); break; #endif // ENABLE_UHID_SET_REPORT @@ -410,7 +444,7 @@ static void uhid_fd_close(btif_hh_uhid_t* p_uhid) { if (p_uhid->fd >= 0) { struct uhid_event ev = {}; ev.type = UHID_DESTROY; - uhid_write(p_uhid->fd, &ev); + uhid_write(p_uhid->fd, &ev, uhid_calc_msg_len(&ev, 0)); log::debug("Closing fd={}, addr:{}", p_uhid->fd, p_uhid->link_spec); close(p_uhid->fd); p_uhid->fd = -1; @@ -649,20 +683,21 @@ static void* btif_hh_poll_event_thread(void* arg) { } /* Pass messages to be handled by uhid_read_inbound_event in the UHID thread */ -static bool to_uhid_thread(int fd, const tBTA_HH_TO_UHID_EVT* ev) { +static bool to_uhid_thread(int fd, const tBTA_HH_TO_UHID_EVT* ev, size_t data_len) { if (fd < 0) { log::error("Cannot write to uhid thread: invalid fd"); return false; } + size_t len = data_len + sizeof(ev->type); ssize_t ret; - OSI_NO_INTR(ret = write(fd, ev, sizeof(*ev))); + OSI_NO_INTR(ret = write(fd, ev, len)); if (ret < 0) { log::error("Cannot write to uhid thread: {}", strerror(errno)); return false; - } else if (ret != (ssize_t)sizeof(*ev)) { - log::error("Wrong size written to uhid thread: {} != {}", ret, sizeof(*ev)); + } else if (ret != (ssize_t)len) { + log::error("Wrong size written to uhid thread: {} != {}", ret, len); return false; } @@ -682,12 +717,13 @@ int bta_hh_co_write(int fd, uint8_t* rpt, uint16_t len) { } memcpy(ev.u.input2.data, rpt, len); + size_t mlen = uhid_calc_msg_len(&ev, len); if (!com::android::bluetooth::flags::hid_report_queuing()) { - return uhid_write(fd, &ev); + return uhid_write(fd, &ev, mlen); } to_uhid.type = BTA_HH_UHID_INBOUND_INPUT_EVT; - return to_uhid_thread(fd, &to_uhid) ? 0 : -1; + return to_uhid_thread(fd, &to_uhid, mlen) ? 0 : -1; } /******************************************************************************* @@ -811,7 +847,7 @@ void bta_hh_co_close(btif_hh_device_t* p_dev) { if (p_dev->internal_send_fd >= 0) { tBTA_HH_TO_UHID_EVT to_uhid = {}; to_uhid.type = BTA_HH_UHID_INBOUND_CLOSE_EVT; - to_uhid_thread(p_dev->internal_send_fd, &to_uhid); + to_uhid_thread(p_dev->internal_send_fd, &to_uhid, 0); pthread_join(p_dev->hh_poll_thread_id, NULL); p_dev->hh_poll_thread_id = -1; @@ -927,8 +963,9 @@ void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name, uint ev.u.create2.version = version; ev.u.create2.country = ctry_code; + size_t mlen = uhid_calc_msg_len(&ev, dscp_len); if (!com::android::bluetooth::flags::hid_report_queuing()) { - result = uhid_write(p_dev->uhid.fd, &ev); + result = uhid_write(p_dev->uhid.fd, &ev, mlen); log::warn("wrote descriptor to fd = {}, dscp_len = {}, result = {}", p_dev->uhid.fd, dscp_len, result); @@ -945,7 +982,7 @@ void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name, uint } to_uhid.type = BTA_HH_UHID_INBOUND_DSCP_EVT; - if (!to_uhid_thread(p_dev->internal_send_fd, &to_uhid)) { + if (!to_uhid_thread(p_dev->internal_send_fd, &to_uhid, mlen)) { log::warn("Error: failed to send DSCP"); if (p_dev->internal_send_fd >= 0) { // Detach the uhid thread. It will exit by itself upon receiving hangup. @@ -985,7 +1022,7 @@ void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) { to_uhid.uhid.type = UHID_SET_REPORT_REPLY; to_uhid.uhid.u.set_report_reply.err = status; - to_uhid_thread(p_dev->internal_send_fd, &to_uhid); + to_uhid_thread(p_dev->internal_send_fd, &to_uhid, uhid_calc_msg_len(&to_uhid.uhid, 0)); return; } @@ -1018,7 +1055,7 @@ void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) { }, }, }; - uhid_write(p_dev->uhid.fd, &ev); + uhid_write(p_dev->uhid.fd, &ev, uhid_calc_msg_len(&ev, 0)); osi_free(context); #else @@ -1060,7 +1097,7 @@ void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, const uint8_t* p_ to_uhid.uhid.u.get_report_reply.size = len; memcpy(to_uhid.uhid.u.get_report_reply.data, p_rpt, len); - to_uhid_thread(p_dev->internal_send_fd, &to_uhid); + to_uhid_thread(p_dev->internal_send_fd, &to_uhid, uhid_calc_msg_len(&to_uhid.uhid, len)); return; } @@ -1096,7 +1133,7 @@ void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, const uint8_t* p_ }; memcpy(ev.u.get_report_reply.data, p_rpt, len); - uhid_write(p_dev->uhid.fd, &ev); + uhid_write(p_dev->uhid.fd, &ev, uhid_calc_msg_len(&ev, len)); osi_free(context); } -- GitLab From e7407a3fa5cb435d1335393c69bcf99af709602f Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 8 Aug 2024 10:01:55 +0000 Subject: [PATCH 003/875] Bass: Fix parsing BASE structure Each time we get the field length from the remote, make sure we actually received the proper amount of data. This eliminates the fatal errors when the BASE data is truncated or badly formatted. Bug: 328181940 Test: atest BluetoothInstrumentationTests Flag: EXEMPT; Regression tests added Change-Id: I5ba26f8bda55c94424024b1cd80e8e95dfebc610 --- .../bluetooth/bass_client/BaseData.java | 85 +++++- .../bluetooth/bass_client/BaseDataTest.java | 277 ++++++++++++++++++ 2 files changed, 351 insertions(+), 11 deletions(-) diff --git a/android/app/src/com/android/bluetooth/bass_client/BaseData.java b/android/app/src/com/android/bluetooth/bass_client/BaseData.java index b2c6986a80d..c15277eeddc 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BaseData.java +++ b/android/app/src/com/android/bluetooth/bass_client/BaseData.java @@ -141,26 +141,36 @@ class BaseData { levelOne.print(); log("levelOne subgroups" + levelOne.numSubGroups); for (int i = 0; i < (int) levelOne.numSubGroups; i++) { + if (offset >= serviceData.length) { + Log.e(TAG, "Error: parsing Level 2"); + return null; + } + Pair pair1 = parseLevelTwo(serviceData, i, offset); - BaseInformation node2 = pair1.first; - if (node2 == null) { + if (pair1 == null) { Log.e(TAG, "Error: parsing Level 2"); return null; } + BaseInformation node2 = pair1.first; numOfBISIndices += node2.numSubGroups; levelTwo.add(node2); node2.print(); offset = pair1.second; for (int k = 0; k < node2.numSubGroups; k++) { + if (offset >= serviceData.length) { + Log.e(TAG, "Error: parsing Level 3"); + return null; + } + Pair pair2 = parseLevelThree(serviceData, offset); - BaseInformation node3 = pair2.first; - offset = pair2.second; - if (node3 == null) { + if (pair2 == null) { Log.e(TAG, "Error: parsing Level 3"); return null; } + BaseInformation node3 = pair2.first; levelThree.add(node3); node3.print(); + offset = pair2.second; } } consolidateBaseofLevelTwo(levelTwo, levelThree); @@ -173,17 +183,52 @@ class BaseData { BaseInformation node = new BaseInformation(); node.level = METADATA_LEVEL2; node.subGroupId = groupIndex; + int bufferLengthLeft = (serviceData.length - offset); + + // Min. length expected is: codecID (5) + numBis (1) + codecSpecCfgLen (1) + metadataLen (1) + final int minNodeBufferLen = METADATA_CODEC_LENGTH + 3; + if (bufferLengthLeft < minNodeBufferLen) { + Log.e(TAG, "Error: Invalid Lvl2 buffer length."); + return null; + } + node.numSubGroups = serviceData[offset++]; // NumBis System.arraycopy(serviceData, offset, node.codecId, 0, METADATA_CODEC_LENGTH); offset += METADATA_CODEC_LENGTH; - node.codecConfigLength = serviceData[offset++] & 0xff; - if (node.codecConfigLength != 0) { + + // Declared codec specific data length + int declaredLength = serviceData[offset++] & 0xff; + + bufferLengthLeft = (serviceData.length - offset); + if (declaredLength < 0 || declaredLength > bufferLengthLeft) { + Log.e(TAG, "Error: Invalid codec config length or codec config truncated."); + return null; + } + + if (declaredLength != 0) { + node.codecConfigLength = declaredLength; node.codecConfigInfo = new byte[node.codecConfigLength]; System.arraycopy(serviceData, offset, node.codecConfigInfo, 0, node.codecConfigLength); offset += node.codecConfigLength; } - node.metaDataLength = serviceData[offset++] & 0xff; - if (node.metaDataLength != 0) { + + // Verify the buffer size left + bufferLengthLeft = (serviceData.length - offset); + if (bufferLengthLeft < 1) { + Log.e(TAG, "Error: Invalid Lvl2 buffer length."); + return null; + } + + // Declared metadata length + declaredLength = serviceData[offset++] & 0xff; + --bufferLengthLeft; + if (declaredLength < 0 || declaredLength > bufferLengthLeft) { + Log.e(TAG, "Error: Invalid metadata length or metadata truncated."); + return null; + } + + if (declaredLength != 0) { + node.metaDataLength = declaredLength; node.metaData = new byte[node.metaDataLength]; System.arraycopy(serviceData, offset, node.metaData, 0, node.metaDataLength); offset += node.metaDataLength; @@ -195,9 +240,27 @@ class BaseData { log("Parsing Level 3"); BaseInformation node = new BaseInformation(); node.level = METADATA_LEVEL3; + int bufferLengthLeft = (serviceData.length - offset); + + // Min. length expected is: bisIdx (1) + codecSpecCfgLen (1) + final int minNodeBufferLen = 2; + if (bufferLengthLeft < minNodeBufferLen) { + Log.e(TAG, "Error: Invalid Lvl2 buffer length."); + return null; + } node.index = serviceData[offset++]; - node.codecConfigLength = serviceData[offset++] & 0xff; - if (node.codecConfigLength != 0) { + + // Verify the buffer size left + int declaredLength = serviceData[offset++] & 0xff; + + bufferLengthLeft = (serviceData.length - offset); + if (declaredLength < 0 || declaredLength > bufferLengthLeft) { + Log.e(TAG, "Error: Invalid metadata length or metadata truncated."); + return null; + } + + if (declaredLength != 0) { + node.codecConfigLength = declaredLength; node.codecConfigInfo = new byte[node.codecConfigLength]; System.arraycopy(serviceData, offset, node.codecConfigInfo, 0, node.codecConfigLength); offset += node.codecConfigLength; diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java index 445be0e2b5f..93082e863a8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java @@ -119,6 +119,283 @@ public class BaseDataTest { assertThat(level.codecConfigLength).isEqualTo(3); } + @Test + public void parseBaseDataLvl2TruncatedConfig() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01, // numSubGroups + // LEVEL 2 + (byte) 0x01, // numBIS + (byte) 0x06, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, // Lc3 + (byte) 0x03, // codecConfigLength + (byte) 0x01, + (byte) 'A', // codecConfigInfo + }; + + BaseData data = BaseData.parseBaseData(serviceData); + assertThat(data).isEqualTo(null); + } + + @Test + public void parseBaseDataLvl2TruncatedMetadata() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01, // numSubGroups + // LEVEL 2 + (byte) 0x01, // numBIS + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, // UNKNOWN_CODEC + (byte) 0x02, // codecConfigLength + (byte) 0x01, + (byte) 'A', // codecConfigInfo + (byte) 0x04, // metaDataLength + (byte) 0x06, + (byte) 0x07, + (byte) 0x08, // metaData + }; + + BaseData data = BaseData.parseBaseData(serviceData); + assertThat(data).isEqualTo(null); + } + + @Test + public void parseBaseDataLvl3TruncatedConfig() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01, // numSubGroups + // LEVEL 2 + (byte) 0x01, // numBIS + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, // UNKNOWN_CODEC + (byte) 0x02, // codecConfigLength + (byte) 0x01, + (byte) 'A', // codecConfigInfo + (byte) 0x03, // metaDataLength + (byte) 0x06, + (byte) 0x07, + (byte) 0x08, // metaData + // LEVEL 3 + (byte) 0x04, // index + (byte) 0x04, // codecConfigLength + (byte) 0x02, + (byte) 'B', + (byte) 'C' // codecConfigInfo + }; + + BaseData data = BaseData.parseBaseData(serviceData); + assertThat(data).isEqualTo(null); + } + + @Test + public void parseBaseDataInvalidLtv() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01, // numSubGroups + // LEVEL 2 + (byte) 0x01, // numBIS + (byte) 0x06, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, // LC3 + (byte) 0x02, // codecConfigLength + (byte) 0x04, + (byte) 'A', // codecConfigInfo + (byte) 0x03, // metaDataLength + (byte) 0x06, + (byte) 0x07, + (byte) 0x08, // metaData + // LEVEL 3 + (byte) 0x04, // index + (byte) 0x03, // codecConfigLength + (byte) 0x03, + (byte) 'B', + (byte) 'C' // codecConfigInfo + }; + + BaseData data = BaseData.parseBaseData(serviceData); + BaseData.BaseInformation level = data.getLevelOne(); + assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.numSubGroups).isEqualTo(1); + + assertThat(data.getLevelTwo().size()).isEqualTo(1); + level = data.getLevelTwo().get(0); + + assertThat(level.numSubGroups).isEqualTo(1); + assertThat(level.codecId).isEqualTo(new byte[] {0x06, 0x00, 0x00, 0x00, 0x00}); + assertThat(level.codecConfigLength).isEqualTo(2); + assertThat(level.metaDataLength).isEqualTo(3); + + assertThat(data.getLevelThree().size()).isEqualTo(1); + level = data.getLevelThree().get(0); + assertThat(level.index).isEqualTo(4); + + // Got the whole config, without interpreting it as LTV + assertThat(level.codecConfigLength).isEqualTo(3); + } + + @Test + public void parseBaseVendorCodecBaseData() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01, // numSubGroups + // LEVEL 2 + (byte) 0x01, // numBIS + (byte) 0xFF, // VENDOR_CODEC + (byte) 0x0A, + (byte) 0xAB, + (byte) 0xBC, + (byte) 0xCD, + (byte) 0x04, // codecConfigLength + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, + (byte) 0x04, // opaque vendor data + (byte) 0x03, // metaDataLength + (byte) 0x06, + (byte) 0x07, + (byte) 0x08, // metaData + // LEVEL 3 + (byte) 0x04, // index + (byte) 0x03, // codecConfigLength + (byte) 0x03, + (byte) 0x02, + (byte) 0x01 // opaque vendor data + }; + + BaseData data = BaseData.parseBaseData(serviceData); + BaseData.BaseInformation level = data.getLevelOne(); + assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.numSubGroups).isEqualTo(1); + + assertThat(data.getLevelTwo().size()).isEqualTo(1); + level = data.getLevelTwo().get(0); + + assertThat(level.numSubGroups).isEqualTo(1); + assertThat(level.codecId) + .isEqualTo( + new byte[] { + (byte) 0xFF, (byte) 0x0A, (byte) 0xAB, (byte) 0xBC, (byte) 0xCD + }); + assertThat(level.codecConfigLength).isEqualTo(4); + assertThat(level.metaDataLength).isEqualTo(3); + + assertThat(data.getLevelThree().size()).isEqualTo(1); + level = data.getLevelThree().get(0); + assertThat(level.index).isEqualTo(4); + assertThat(level.codecConfigLength).isEqualTo(3); + } + + @Test + public void parseBaseVendorCodecBaseDataMinimal() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01, // numSubGroups + // LEVEL 2 + (byte) 0x01, // numBIS + (byte) 0xFF, // VENDOR_CODEC + (byte) 0x0A, + (byte) 0xAB, + (byte) 0xBC, + (byte) 0xCD, + (byte) 0x00, // codecConfigLength + (byte) 0x00, // metaDataLength + // LEVEL 3 + (byte) 0x04, // index + (byte) 0x00, // codecConfigLength + }; + + BaseData data = BaseData.parseBaseData(serviceData); + BaseData.BaseInformation level = data.getLevelOne(); + assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.numSubGroups).isEqualTo(1); + + assertThat(data.getLevelTwo().size()).isEqualTo(1); + level = data.getLevelTwo().get(0); + + assertThat(level.numSubGroups).isEqualTo(1); + assertThat(level.codecId) + .isEqualTo( + new byte[] { + (byte) 0xFF, (byte) 0x0A, (byte) 0xAB, (byte) 0xBC, (byte) 0xCD + }); + assertThat(level.codecConfigLength).isEqualTo(0); + assertThat(level.metaDataLength).isEqualTo(0); + + assertThat(data.getLevelThree().size()).isEqualTo(1); + level = data.getLevelThree().get(0); + assertThat(level.index).isEqualTo(4); + assertThat(level.codecConfigLength).isEqualTo(0); + } + + @Test + public void parseBaseVendorCodecBaseDataInvalid() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01, // numSubGroups + // LEVEL 2 + (byte) 0x00, // numBIS invalid value + (byte) 0xFE, // UNKNOWN CODEC + (byte) 0x00, // codecConfigLength + (byte) 0x00, // metaDataLength + }; + + BaseData data = BaseData.parseBaseData(serviceData); + assertThat(data).isEqualTo(null); + } + @Test public void parseBaseData_longMetaData() { assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); -- GitLab From 50d8fce799dd083ac7782242f19ec6cfae015e4c Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Tue, 3 Sep 2024 06:47:39 +0000 Subject: [PATCH 004/875] HidHostTest: fix lint issues * Fix package name to be the same as folder name * Add additional imports * Add annotation to surprise lint warnings on permission Test: atest HidHostTest Flag: TEST_ONLY Bug: 363974008 Change-Id: I2eee5ba308253cac8eb05ede39373e2f1fb50a14 --- .../android/bluetooth/hid/HidHostTest.java | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java index 4e11e4d4af8..7501ab96b21 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java @@ -14,10 +14,20 @@ * limitations under the License. */ -package android.bluetooth; +package android.bluetooth.hid; import static com.google.common.truth.Truth.assertThat; +import android.annotation.SuppressLint; +import android.bluetooth.BluetoothA2dp; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothHidDevice; +import android.bluetooth.BluetoothHidHost; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.PandoraDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -27,8 +37,8 @@ import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.Log; -import androidx.test.core.app.ApplicationProvider; 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; @@ -52,11 +62,10 @@ import java.util.Iterator; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; -/** Test cases for {@link Hid Host}. */ +/** Test cases for {@link BluetoothHidHost}. */ @RunWith(AndroidJUnit4.class) -@Ignore("b/355328584") public class HidHostTest { - private static final String TAG = "HidHostTest"; + private static final String TAG = HidHostTest.class.getSimpleName(); private SettableFuture mFutureConnectionIntent, mFutureAdapterStateIntent, mFutureBondIntent, @@ -69,9 +78,10 @@ public class HidHostTest { private BluetoothHidHost mHidService; private BluetoothHeadset mHfpService; private BluetoothA2dp mA2dpService; - private final Context mContext = ApplicationProvider.getApplicationContext(); - private final BluetoothManager mManager = mContext.getSystemService(BluetoothManager.class); - private final BluetoothAdapter mAdapter = mManager.getAdapter(); + private final Context mContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + private final BluetoothAdapter mAdapter = + mContext.getSystemService(BluetoothManager.class).getAdapter(); private HIDGrpc.HIDBlockingStub mHidBlockingStub; private byte mReportId; private static final int KEYBD_RPT_ID = 1; @@ -92,8 +102,9 @@ public class HidHostTest { @Rule(order = 2) public final PandoraDevice mBumble = new PandoraDevice(); - private BroadcastReceiver mHidStateReceiver = + private final BroadcastReceiver mHidStateReceiver = new BroadcastReceiver() { + @SuppressLint("MissingPermission") @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { @@ -213,6 +224,7 @@ public class HidHostTest { public void onServiceDisconnected(int profile) {} }; + @SuppressLint("MissingPermission") @Before public void setUp() throws Exception { final IntentFilter filter = new IntentFilter(); @@ -259,6 +271,7 @@ public class HidHostTest { assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_CONNECTED); } + @SuppressLint("MissingPermission") @After public void tearDown() throws Exception { @@ -288,6 +301,7 @@ public class HidHostTest { *
  • 4. Bumble Disconnect the HID and Android verifies Connection state intent * */ + @SuppressLint("MissingPermission") @Test public void disconnectHidDeviceTest() throws Exception { @@ -313,6 +327,7 @@ public class HidHostTest { *
  • 10. Bumble connect the HID and Android verifies Connection state intent * */ + @SuppressLint("MissingPermission") @Test @RequiresFlagsEnabled({ Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP, @@ -368,6 +383,7 @@ public class HidHostTest { *
  • 4. Bumble reconnects and Android verifies Connection state intent * */ + @SuppressLint("MissingPermission") @Test @RequiresFlagsEnabled({ Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP, @@ -396,6 +412,7 @@ public class HidHostTest { *
  • 5. Bumble reconnects and Android verifies Connection state intent * */ + @SuppressLint("MissingPermission") @Test @RequiresFlagsEnabled({ Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP, @@ -426,6 +443,7 @@ public class HidHostTest { *
  • 4. Bumble reconnects and Android verifies Connection state intent * */ + @SuppressLint("MissingPermission") @Test @RequiresFlagsEnabled({ Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP, @@ -455,6 +473,7 @@ public class HidHostTest { *
  • 2. Android Virtual Unplug and verifies Bonding * */ + @SuppressLint("MissingPermission") @Test public void hidVirtualUnplugFromHidHostTest() throws Exception { mHidService.virtualUnplug(mDevice); @@ -470,6 +489,7 @@ public class HidHostTest { *
  • 2. Bumble Virtual Unplug and Android verifies Bonding * */ + @SuppressLint("MissingPermission") @Test public void hidVirtualUnplugFromHidDeviceTest() throws Exception { mHidBlockingStub.virtualCableUnplugHost(Empty.getDefaultInstance()); @@ -486,6 +506,7 @@ public class HidHostTest { *
  • 2. Android Gets the Protocol mode and verifies the mode * */ + @SuppressLint("MissingPermission") @Test public void hidGetProtocolModeTest() throws Exception { mHidService.getProtocolMode(mDevice); @@ -502,6 +523,7 @@ public class HidHostTest { *
  • 2. Android Sets the Protocol mode and verifies the mode * */ + @SuppressLint("MissingPermission") @Test @Ignore("b/349351673: sets wrong protocol mode value") public void hidSetProtocolModeTest() throws Exception { @@ -529,6 +551,7 @@ public class HidHostTest { *
  • 2. Android get report and verifies the report * */ + @SuppressLint("MissingPermission") @Test public void hidGetReportTest() throws Exception { // Keyboard report @@ -561,6 +584,7 @@ public class HidHostTest { *
  • 2. Android Set report and verifies the report * */ + @SuppressLint("MissingPermission") @Test public void hidSetReportTest() throws Exception { Iterator mHidReportEventObserver = -- GitLab From 8b8ed167d28175cf8435b77478ccaa3b2c368cf9 Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Tue, 3 Sep 2024 13:53:11 +0000 Subject: [PATCH 005/875] HidHostTest: Use Mockito to wait for events instead of Future * This helps get rid of unncessary broadcast receiver and listener classes * Before this change, there is no gurantee that A2DP, HFP, and HID_HOST service proxy will be connected on time during setUp() function. This change ensures that we always wait for service proxy connections * Before this change, some times the Future is created after calling the method under test, if the future is completed before the Future is completed, then we will wait forever for the future. This change makes sure this race condition won't happen * Added EnableBluetoothRule to toggle Bluetooth at each test, adding about 2 second delay to each test, but it makes the test much more stable Test: atest HidHostTest Flag: TEST_ONLY Bug: 363974008 Change-Id: I9e9a198bdccd1510f963a8bb85df78b5d52f54e7 --- .../android/bluetooth/hid/HidHostTest.java | 624 +++++++++++------- 1 file changed, 401 insertions(+), 223 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java index 7501ab96b21..fde1a292bdf 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java @@ -16,8 +16,26 @@ package android.bluetooth.hid; +import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO; +import static android.bluetooth.BluetoothDevice.TRANSPORT_BREDR; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; + +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 static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + import android.annotation.SuppressLint; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; @@ -28,6 +46,7 @@ import android.bluetooth.BluetoothHidHost; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.PandoraDevice; +import android.bluetooth.cts.EnableBluetoothRule; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -43,21 +62,29 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.bluetooth.flags.Flags; import com.android.compatibility.common.util.AdoptShellPermissionsRule; -import com.google.common.util.concurrent.SettableFuture; import com.google.protobuf.Empty; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; import org.junit.After; import org.junit.Before; import org.junit.Ignore; 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.hamcrest.MockitoHamcrest; +import org.mockito.stubbing.Answer; import pandora.HIDGrpc; import pandora.HidProto.ProtocolModeEvent; import pandora.HidProto.ReportEvent; import java.time.Duration; +import java.util.Arrays; import java.util.Iterator; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -66,14 +93,7 @@ import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) public class HidHostTest { private static final String TAG = HidHostTest.class.getSimpleName(); - private SettableFuture mFutureConnectionIntent, - mFutureAdapterStateIntent, - mFutureBondIntent, - mFutureHandShakeIntent, - mFutureProtocolModeIntent, - mFutureVirtualUnplugIntent, - mFutureReportIntent; - private SettableFuture mAclConnectionIntent; + private static final Duration INTENT_TIMEOUT = Duration.ofSeconds(10); private BluetoothDevice mDevice; private BluetoothHidHost mHidService; private BluetoothHeadset mHfpService; @@ -90,6 +110,7 @@ public class HidHostTest { private static final int MOUSE_RPT_SIZE = 4; private static final int INVALID_RPT_ID = 3; private static final int CONNECTION_TIMEOUT_MS = 2_000; + private static final int BT_ON_DELAY_MS = 3000; private static final Duration PROTO_MODE_TIMEOUT = Duration.ofSeconds(10); @@ -102,173 +123,208 @@ public class HidHostTest { @Rule(order = 2) public final PandoraDevice mBumble = new PandoraDevice(); - private final BroadcastReceiver mHidStateReceiver = - new BroadcastReceiver() { - @SuppressLint("MissingPermission") - @Override - public void onReceive(Context context, Intent intent) { - switch (intent.getAction()) { - case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED: - int state = - intent.getIntExtra( - BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR); - Log.i(TAG, "Connection state change:" + state); - if (state == BluetoothProfile.STATE_CONNECTED - || state == BluetoothProfile.STATE_DISCONNECTED) { - if (mFutureConnectionIntent != null) { - mFutureConnectionIntent.set(state); - } - } - break; - case BluetoothDevice.ACTION_PAIRING_REQUEST: - mBumble.getRemoteDevice().setPairingConfirmation(true); - break; - case BluetoothAdapter.ACTION_STATE_CHANGED: - int adapterState = - intent.getIntExtra( - BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); - Log.i(TAG, "Adapter state change:" + adapterState); - if (adapterState == BluetoothAdapter.STATE_ON - || adapterState == BluetoothAdapter.STATE_OFF) { - if (mFutureAdapterStateIntent != null) { - mFutureAdapterStateIntent.set(adapterState); - } - } - break; - case BluetoothDevice.ACTION_BOND_STATE_CHANGED: - int bondState = - intent.getIntExtra( - BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - Log.i(TAG, "Bond state change:" + bondState); - if (bondState == BluetoothDevice.BOND_BONDED - || bondState == BluetoothDevice.BOND_NONE) { - if (mFutureBondIntent != null) { - mFutureBondIntent.set(bondState); - } - } - break; - case BluetoothHidHost.ACTION_PROTOCOL_MODE_CHANGED: - int protocolMode = - intent.getIntExtra( - BluetoothHidHost.EXTRA_PROTOCOL_MODE, - BluetoothHidHost.PROTOCOL_UNSUPPORTED_MODE); - Log.i(TAG, "Protocol mode:" + protocolMode); - if (mFutureProtocolModeIntent != null) { - mFutureProtocolModeIntent.set(protocolMode); - } - break; - case BluetoothHidHost.ACTION_HANDSHAKE: - int handShake = - intent.getIntExtra( - BluetoothHidHost.EXTRA_STATUS, - BluetoothHidDevice.ERROR_RSP_UNKNOWN); - Log.i(TAG, "Handshake status:" + handShake); - if (mFutureHandShakeIntent != null) { - mFutureHandShakeIntent.set(handShake); - } - break; - case BluetoothHidHost.ACTION_VIRTUAL_UNPLUG_STATUS: - int virtualUnplug = - intent.getIntExtra( - BluetoothHidHost.EXTRA_VIRTUAL_UNPLUG_STATUS, - BluetoothHidHost.VIRTUAL_UNPLUG_STATUS_FAIL); - Log.i(TAG, "Virtual Unplug status:" + virtualUnplug); - if (mFutureVirtualUnplugIntent != null) { - mFutureVirtualUnplugIntent.set(virtualUnplug); - } - break; - case BluetoothHidHost.ACTION_REPORT: - byte[] report = intent.getByteArrayExtra(BluetoothHidHost.EXTRA_REPORT); - int reportSize = - intent.getIntExtra( - BluetoothHidHost.EXTRA_REPORT_BUFFER_SIZE, 0); - mReportId = report[0]; - if (mFutureReportIntent != null) { - mFutureReportIntent.set((reportSize - 1)); - } - break; - case BluetoothDevice.ACTION_ACL_DISCONNECTED: - if (mAclConnectionIntent != null) { - mAclConnectionIntent.set(true); - } - break; - default: - break; - } - } - }; + @Rule(order = 3) + public final EnableBluetoothRule enableBluetoothRule = new EnableBluetoothRule(false, true); - // These callbacks run on the main thread. - private final BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = - new BluetoothProfile.ServiceListener() { - - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - switch (profile) { - case BluetoothProfile.HEADSET: - mHfpService = (BluetoothHeadset) proxy; - break; - case BluetoothProfile.A2DP: - mA2dpService = (BluetoothA2dp) proxy; - break; - case BluetoothProfile.HID_HOST: - mHidService = (BluetoothHidHost) proxy; - break; - default: - break; - } - } + @Mock private BroadcastReceiver mReceiver; + private InOrder mInOrder = null; + private byte[] mReportData = {}; + @Mock private BluetoothProfile.ServiceListener mProfileServiceListener; - @Override - public void onServiceDisconnected(int profile) {} + @SuppressLint("MissingPermission") + private final Answer mIntentHandler = + inv -> { + Log.i(TAG, "onReceive(): intent=" + Arrays.toString(inv.getArguments())); + Intent intent = inv.getArgument(1); + String action = intent.getAction(); + BluetoothDevice device; + switch (action) { + case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED: + device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + int state = + intent.getIntExtra( + BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR); + int transport = + intent.getIntExtra( + BluetoothDevice.EXTRA_TRANSPORT, + BluetoothDevice.TRANSPORT_AUTO); + Log.i( + TAG, + "Connection state change: device=" + + device + + " " + + BluetoothProfile.getConnectionStateName(state) + + "(" + + state + + "), transport: " + + transport); + break; + case BluetoothDevice.ACTION_PAIRING_REQUEST: + device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + mBumble.getRemoteDevice().setPairingConfirmation(true); + Log.i(TAG, "onReceive(): setPairingConfirmation(true) for " + device); + break; + case BluetoothAdapter.ACTION_STATE_CHANGED: + int adapterState = + intent.getIntExtra( + BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + Log.i(TAG, "Adapter state change:" + adapterState); + break; + case BluetoothDevice.ACTION_BOND_STATE_CHANGED: + device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + int bondState = + intent.getIntExtra( + BluetoothDevice.EXTRA_BOND_STATE, BluetoothAdapter.ERROR); + int prevBondState = + intent.getIntExtra( + BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, + BluetoothAdapter.ERROR); + Log.i( + TAG, + "onReceive(): device " + + device + + " bond state changed from " + + prevBondState + + " to " + + bondState); + break; + case BluetoothHidHost.ACTION_PROTOCOL_MODE_CHANGED: + device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + int protocolMode = + intent.getIntExtra( + BluetoothHidHost.EXTRA_PROTOCOL_MODE, + BluetoothHidHost.PROTOCOL_UNSUPPORTED_MODE); + Log.i( + TAG, + "onReceive(): device " + device + " protocol mode " + protocolMode); + break; + case BluetoothHidHost.ACTION_HANDSHAKE: + device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + int handShake = + intent.getIntExtra( + BluetoothHidHost.EXTRA_STATUS, + BluetoothHidDevice.ERROR_RSP_UNKNOWN); + Log.i( + TAG, + "onReceive(): device " + device + " handshake status:" + handShake); + break; + case BluetoothHidHost.ACTION_VIRTUAL_UNPLUG_STATUS: + int virtualUnplug = + intent.getIntExtra( + BluetoothHidHost.EXTRA_VIRTUAL_UNPLUG_STATUS, + BluetoothHidHost.VIRTUAL_UNPLUG_STATUS_FAIL); + Log.i(TAG, "onReceive(): Virtual Unplug status:" + virtualUnplug); + break; + case BluetoothHidHost.ACTION_REPORT: + device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + mReportData = intent.getByteArrayExtra(BluetoothHidHost.EXTRA_REPORT); + int reportBufferSize = + intent.getIntExtra(BluetoothHidHost.EXTRA_REPORT_BUFFER_SIZE, 0); + Log.i( + TAG, + "onReceive(): device " + + device + + " reportBufferSize " + + reportBufferSize); + break; + case BluetoothDevice.ACTION_ACL_DISCONNECTED: + device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + Log.i(TAG, "onReceive(): ACL Disconnected with device: " + device); + break; + default: + Log.i(TAG, "onReceive(): unknown intent action " + action); + break; + } + return null; }; @SuppressLint("MissingPermission") @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + doAnswer(mIntentHandler).when(mReceiver).onReceive(any(), any()); + + mInOrder = inOrder(mReceiver); + final IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothDevice.ACTION_FOUND); filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHidHost.ACTION_PROTOCOL_MODE_CHANGED); filter.addAction(BluetoothHidHost.ACTION_HANDSHAKE); filter.addAction(BluetoothHidHost.ACTION_VIRTUAL_UNPLUG_STATUS); filter.addAction(BluetoothHidHost.ACTION_REPORT); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); + mContext.registerReceiver(mReceiver, filter); + // Get profile proxies + mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.HID_HOST); + mHidService = (BluetoothHidHost) verifyProfileServiceConnected(BluetoothProfile.HID_HOST); + mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP); + BluetoothA2dp a2dpService = + (BluetoothA2dp) verifyProfileServiceConnected(BluetoothProfile.A2DP); + mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.HEADSET); + BluetoothHeadset hfpService = + (BluetoothHeadset) verifyProfileServiceConnected(BluetoothProfile.HEADSET); - mContext.registerReceiver(mHidStateReceiver, filter); - mAdapter.getProfileProxy( - mContext, mBluetoothProfileServiceListener, BluetoothProfile.HID_HOST); - mAdapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, BluetoothProfile.A2DP); - mAdapter.getProfileProxy( - mContext, mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); mHidBlockingStub = mBumble.hidBlocking(); - mFutureConnectionIntent = SettableFuture.create(); mDevice = mBumble.getRemoteDevice(); - mFutureBondIntent = SettableFuture.create(); - assertThat(mDevice.createBond()).isTrue(); - assertThat(mFutureBondIntent.get()).isEqualTo(BluetoothDevice.BOND_BONDED); - - if (mA2dpService != null - && mA2dpService.getConnectionPolicy(mDevice) - == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { + // Remove bond if the device is already bonded + if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED) { + removeBond(mDevice); + } + assertThat(mDevice.createBond(TRANSPORT_BREDR)).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_PAIRING_REQUEST), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + + if (a2dpService.getConnectionPolicy(mDevice) + == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { assertThat( - mA2dpService.setConnectionPolicy( + a2dpService.setConnectionPolicy( mDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) .isTrue(); } - if (mHfpService != null - && mHfpService.getConnectionPolicy(mDevice) - == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { + if (hfpService.getConnectionPolicy(mDevice) == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { assertThat( - mHfpService.setConnectionPolicy( + hfpService.setConnectionPolicy( mDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) .isTrue(); } - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + if (Flags.allowSwitchingHidAndHogp() && Flags.saveInitialHidConnectionPolicy()) { + verifyConnectionState(mDevice, equalTo(TRANSPORT_BREDR), equalTo(STATE_CONNECTING)); + verifyConnectionState(mDevice, equalTo(TRANSPORT_BREDR), equalTo(STATE_CONNECTED)); + assertThat(mHidService.getPreferredTransport(mDevice)).isEqualTo(TRANSPORT_BREDR); + } else { + // Without allowSwitchingHidAndHogp, transport will be AUTO + verifyConnectionState(mDevice, equalTo(TRANSPORT_AUTO), equalTo(STATE_CONNECTING)); + verifyConnectionState(mDevice, equalTo(TRANSPORT_AUTO), equalTo(STATE_CONNECTED)); + } } @SuppressLint("MissingPermission") @@ -276,18 +332,9 @@ public class HidHostTest { public void tearDown() throws Exception { if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED) { - mFutureBondIntent = SettableFuture.create(); - mDevice.removeBond(); - assertThat(mFutureBondIntent.get()).isEqualTo(BluetoothDevice.BOND_NONE); + removeBond(mDevice); } - - if (mDevice.isConnected()) { - mAclConnectionIntent = SettableFuture.create(); - mDevice.disconnect(); - assertThat(mAclConnectionIntent.get()).isTrue(); - } - - mContext.unregisterReceiver(mHidStateReceiver); + mContext.unregisterReceiver(mReceiver); } /** @@ -305,10 +352,8 @@ public class HidHostTest { @Test public void disconnectHidDeviceTest() throws Exception { - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.disconnectHost(Empty.getDefaultInstance()); - - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyProfileDisconnectionState(); } /** @@ -338,17 +383,14 @@ public class HidHostTest { assertThat(mHidService.getConnectionPolicy(mDevice)) .isEqualTo(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.disconnectHost(Empty.getDefaultInstance()); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyProfileDisconnectionState(); - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.connectHost(Empty.getDefaultInstance()); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + verifyIncomingProfileConnectionState(); - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.disconnectHost(Empty.getDefaultInstance()); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyProfileDisconnectionState(); assertThat( mHidService.setConnectionPolicy( @@ -357,20 +399,26 @@ public class HidHostTest { reconnectionFromRemoteAndVerifyDisconnectedState(); - mFutureConnectionIntent = SettableFuture.create(); assertThat( mHidService.setConnectionPolicy( mDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED)) .isTrue(); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_CONNECTING)); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_CONNECTED)); - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.disconnectHost(Empty.getDefaultInstance()); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyProfileDisconnectionState(); - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.connectHost(Empty.getDefaultInstance()); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + verifyIncomingProfileConnectionState(); } /** @@ -396,9 +444,8 @@ public class HidHostTest { bluetoothRestart(); - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.connectHost(Empty.getDefaultInstance()); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + verifyIncomingProfileConnectionState(); } /** @@ -453,14 +500,14 @@ public class HidHostTest { assertThat(mHidService.getConnectionPolicy(mDevice)) .isEqualTo(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - mFutureConnectionIntent = SettableFuture.create(); mHidBlockingStub.disconnectHost(Empty.getDefaultInstance()); + verifyProfileDisconnectionState(); - assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); - - mFutureBondIntent = SettableFuture.create(); mDevice.removeBond(); - assertThat(mFutureBondIntent.get()).isEqualTo(BluetoothDevice.BOND_NONE); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); reconnectionFromRemoteAndVerifyDisconnectedState(); } @@ -477,8 +524,10 @@ public class HidHostTest { @Test public void hidVirtualUnplugFromHidHostTest() throws Exception { mHidService.virtualUnplug(mDevice); - mFutureBondIntent = SettableFuture.create(); - assertThat(mFutureBondIntent.get()).isEqualTo(BluetoothDevice.BOND_NONE); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); } /** @@ -491,11 +540,14 @@ public class HidHostTest { */ @SuppressLint("MissingPermission") @Test + @RequiresFlagsEnabled({Flags.FLAG_REMOVE_INPUT_DEVICE_ON_VUP}) public void hidVirtualUnplugFromHidDeviceTest() throws Exception { mHidBlockingStub.virtualCableUnplugHost(Empty.getDefaultInstance()); - mFutureVirtualUnplugIntent = SettableFuture.create(); - assertThat(mFutureVirtualUnplugIntent.get()) - .isEqualTo(BluetoothHidHost.VIRTUAL_UNPLUG_STATUS_SUCCESS); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_VIRTUAL_UNPLUG_STATUS), + hasExtra( + BluetoothHidHost.EXTRA_VIRTUAL_UNPLUG_STATUS, + BluetoothHidHost.VIRTUAL_UNPLUG_STATUS_SUCCESS)); } /** @@ -510,9 +562,11 @@ public class HidHostTest { @Test public void hidGetProtocolModeTest() throws Exception { mHidService.getProtocolMode(mDevice); - mFutureProtocolModeIntent = SettableFuture.create(); - assertThat(mFutureProtocolModeIntent.get()) - .isEqualTo(BluetoothHidHost.PROTOCOL_REPORT_MODE); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_PROTOCOL_MODE_CHANGED), + hasExtra( + BluetoothHidHost.EXTRA_PROTOCOL_MODE, + BluetoothHidHost.PROTOCOL_REPORT_MODE)); } /** @@ -532,9 +586,13 @@ public class HidHostTest { .withDeadlineAfter(PROTO_MODE_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS) .onSetProtocolMode(Empty.getDefaultInstance()); mHidService.setProtocolMode(mDevice, BluetoothHidHost.PROTOCOL_BOOT_MODE); - mFutureHandShakeIntent = SettableFuture.create(); - assertThat(mFutureHandShakeIntent.get()) - .isEqualTo(BluetoothHidDevice.ERROR_RSP_UNSUPPORTED_REQ); + // Must cast ERROR_RSP_UNSUPPORTED_REQ, otherwise, it won't match with the int extra + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_HANDSHAKE), + hasExtra( + BluetoothHidHost.EXTRA_STATUS, + (int) BluetoothHidDevice.ERROR_RSP_UNSUPPORTED_REQ)); + if (mHidProtoModeEventObserver.hasNext()) { ProtocolModeEvent hidProtoModeEvent = mHidProtoModeEventObserver.next(); Log.i(TAG, "Protocol mode:" + hidProtoModeEvent.getProtocolMode()); @@ -555,25 +613,36 @@ public class HidHostTest { @Test public void hidGetReportTest() throws Exception { // Keyboard report - byte id = KEYBD_RPT_ID; - mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, id, (int) 0); - mFutureReportIntent = SettableFuture.create(); - assertThat(mFutureReportIntent.get()).isEqualTo(KEYBD_RPT_SIZE); - assertThat(mReportId).isEqualTo(KEYBD_RPT_ID); + mReportData = new byte[0]; + mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, (byte) KEYBD_RPT_ID, 0); + // Report Buffer = Report ID (1 byte) + Report Data (KEYBD_RPT_SIZE byte) + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_REPORT), + hasExtra(BluetoothHidHost.EXTRA_REPORT_BUFFER_SIZE, KEYBD_RPT_SIZE + 1)); + assertThat(mReportData).isNotNull(); + assertThat(mReportData.length).isGreaterThan(0); + assertThat(mReportData[0]).isEqualTo(KEYBD_RPT_ID); // Mouse report - id = MOUSE_RPT_ID; - mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, id, (int) 0); - mFutureReportIntent = SettableFuture.create(); - assertThat(mFutureReportIntent.get()).isEqualTo(MOUSE_RPT_SIZE); - assertThat(mReportId).isEqualTo(MOUSE_RPT_ID); + mReportData = new byte[0]; + mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, (byte) MOUSE_RPT_ID, 0); + // Report Buffer = Report ID (1 byte) + Report Data (MOUSE_RPT_SIZE byte) + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_REPORT), + hasExtra(BluetoothHidHost.EXTRA_REPORT_BUFFER_SIZE, MOUSE_RPT_SIZE + 1)); + assertThat(mReportData).isNotNull(); + assertThat(mReportData.length).isGreaterThan(0); + assertThat(mReportData[0]).isEqualTo(MOUSE_RPT_ID); // Invalid report - id = INVALID_RPT_ID; - mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, id, (int) 0); - mFutureHandShakeIntent = SettableFuture.create(); - assertThat(mFutureHandShakeIntent.get()) - .isEqualTo(BluetoothHidDevice.ERROR_RSP_INVALID_RPT_ID); + mHidService.getReport( + mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, (byte) INVALID_RPT_ID, (int) 0); + // Must cast ERROR_RSP_INVALID_RPT_ID, otherwise, it won't match with the int extra + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_HANDSHAKE), + hasExtra( + BluetoothHidHost.EXTRA_STATUS, + (int) BluetoothHidDevice.ERROR_RSP_INVALID_RPT_ID)); } /** @@ -594,8 +663,12 @@ public class HidHostTest { // Keyboard report String kbReportData = "010203040506070809"; mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, kbReportData); - mFutureHandShakeIntent = SettableFuture.create(); - assertThat(mFutureHandShakeIntent.get()).isEqualTo(BluetoothHidDevice.ERROR_RSP_SUCCESS); + /// Must cast ERROR_RSP_SUCCESS, otherwise, it won't match with the int extra + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_HANDSHAKE), + hasExtra( + BluetoothHidHost.EXTRA_STATUS, (int) BluetoothHidDevice.ERROR_RSP_SUCCESS)); + if (mHidReportEventObserver.hasNext()) { ReportEvent hidReportEvent = mHidReportEventObserver.next(); assertThat(hidReportEvent.getReportTypeValue()) @@ -606,9 +679,13 @@ public class HidHostTest { // Keyboard report - Invalid param mHidService.setReport( mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, kbReportData.substring(0, 10)); - mFutureHandShakeIntent = SettableFuture.create(); - assertThat(mFutureHandShakeIntent.get()) - .isEqualTo(BluetoothHidDevice.ERROR_RSP_INVALID_PARAM); + // Must cast ERROR_RSP_INVALID_PARAM, otherwise, it won't match with the int extra + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_HANDSHAKE), + hasExtra( + BluetoothHidHost.EXTRA_STATUS, + (int) BluetoothHidDevice.ERROR_RSP_INVALID_PARAM)); + if (mHidReportEventObserver.hasNext()) { ReportEvent hidReportEvent = mHidReportEventObserver.next(); assertThat(hidReportEvent.getReportTypeValue()) @@ -619,8 +696,12 @@ public class HidHostTest { // Mouse report String mouseReportData = "02030405"; mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, mouseReportData); - mFutureHandShakeIntent = SettableFuture.create(); - assertThat(mFutureHandShakeIntent.get()).isEqualTo(BluetoothHidDevice.ERROR_RSP_SUCCESS); + // Must cast ERROR_RSP_SUCCESS, otherwise, it won't match with the int extra + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_HANDSHAKE), + hasExtra( + BluetoothHidHost.EXTRA_STATUS, (int) BluetoothHidDevice.ERROR_RSP_SUCCESS)); + if (mHidReportEventObserver.hasNext()) { ReportEvent hidReportEvent = mHidReportEventObserver.next(); assertThat(hidReportEvent.getReportTypeValue()) @@ -631,9 +712,12 @@ public class HidHostTest { // Invalid report id String inValidReportData = "0304"; mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, inValidReportData); - mFutureHandShakeIntent = SettableFuture.create(); - assertThat(mFutureHandShakeIntent.get()) - .isEqualTo(BluetoothHidDevice.ERROR_RSP_INVALID_RPT_ID); + // Must cast ERROR_RSP_INVALID_RPT_ID, otherwise, it won't match with the int extra + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_HANDSHAKE), + hasExtra( + BluetoothHidHost.EXTRA_STATUS, + (int) BluetoothHidDevice.ERROR_RSP_INVALID_RPT_ID)); if (mHidReportEventObserver.hasNext()) { ReportEvent hidReportEvent = mHidReportEventObserver.next(); assertThat(hidReportEvent.getReportTypeValue()) @@ -643,21 +727,115 @@ public class HidHostTest { } } + private void verifyConnectionState( + BluetoothDevice device, Matcher transport, Matcher state) { + + if (Flags.allowSwitchingHidAndHogp() && Flags.saveInitialHidConnectionPolicy()) { + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, transport), + hasExtra(BluetoothProfile.EXTRA_STATE, state)); + } else { + // skip transport verification + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(BluetoothProfile.EXTRA_STATE, state)); + } + } + + private void verifyIncomingProfileConnectionState() { + // for incoming connection, connection state transit + // from STATE_ACCEPTING -->STATE_CONNECTED + if (Flags.allowSwitchingHidAndHogp() && Flags.saveInitialHidConnectionPolicy()) { + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_CONNECTED)); + } else { + // skip transport verification + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_CONNECTED)); + } + } + + private void verifyProfileDisconnectionState() { + if (Flags.allowSwitchingHidAndHogp() && Flags.saveInitialHidConnectionPolicy()) { + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTING)); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTED)); + } else { + // skip transport verification + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTING)); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTED)); + } + } + private void reconnectionFromRemoteAndVerifyDisconnectedState() throws Exception { mHidBlockingStub.connectHost(Empty.getDefaultInstance()); final CompletableFuture future = new CompletableFuture<>(); future.completeOnTimeout(null, CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS).join(); - assertThat(mHidService.getConnectionState(mDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHidService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); } private void bluetoothRestart() throws Exception { mAdapter.disable(); - mFutureAdapterStateIntent = SettableFuture.create(); - assertThat(mFutureAdapterStateIntent.get()).isEqualTo(BluetoothAdapter.STATE_OFF); + verifyIntentReceived( + hasAction(BluetoothAdapter.ACTION_STATE_CHANGED), + hasExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)); + // Without delay, some time HID auto reconnection + // triggered by BluetoothAdapterService + final CompletableFuture future = new CompletableFuture<>(); + future.completeOnTimeout(null, BT_ON_DELAY_MS, TimeUnit.MILLISECONDS).join(); mAdapter.enable(); - mFutureAdapterStateIntent = SettableFuture.create(); - assertThat(mFutureAdapterStateIntent.get()).isEqualTo(BluetoothAdapter.STATE_ON); + verifyIntentReceived( + hasAction(BluetoothAdapter.ACTION_STATE_CHANGED), + hasExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON)); + } + + private void removeBond(BluetoothDevice device) { + assertThat(device.removeBond()).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); + } + + @SafeVarargs + private void verifyIntentReceived(Matcher... matchers) { + mInOrder.verify(mReceiver, timeout(INTENT_TIMEOUT.toMillis())) + .onReceive(any(Context.class), MockitoHamcrest.argThat(AllOf.allOf(matchers))); + } + + @SafeVarargs + private void verifyIntentReceivedAtLeast(int atLeast, Matcher... matchers) { + mInOrder.verify(mReceiver, timeout(INTENT_TIMEOUT.toMillis()).atLeast(atLeast)) + .onReceive(any(Context.class), MockitoHamcrest.argThat(AllOf.allOf(matchers))); + } + + private BluetoothProfile verifyProfileServiceConnected(int profile) { + ArgumentCaptor proxyCaptor = + ArgumentCaptor.forClass(BluetoothProfile.class); + verify(mProfileServiceListener, timeout(INTENT_TIMEOUT.toMillis())) + .onServiceConnected(eq(profile), proxyCaptor.capture()); + return proxyCaptor.getValue(); } } -- GitLab From 21b8064163a124723c0c28b66c4cd98f0ccf1bc3 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Fri, 13 Sep 2024 06:08:23 +0000 Subject: [PATCH 006/875] Remove BluetoothPbapCallLogComposer#finalize Removes the finalize method and makes BluetoothPbapCallLogComposer implement AutoCloseable to allow the use of try-with-resources. Flag: EXEMPT, no logical change Bug: 366307571 Test: atest BluetoothPbapCallLogComposer Change-Id: Idd2c50b75e23f283a860f9a3af81fa24e420e6de --- .../pbap/BluetoothPbapCallLogComposer.java | 17 +++-------------- .../pbap/BluetoothPbapVcardManager.java | 7 +------ .../pbap/BluetoothPbapCallLogComposerTest.java | 13 +++---------- 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java index dccc47b7d8f..b66295d43e2 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java @@ -42,7 +42,7 @@ import java.util.Calendar; /** VCard composer especially for Call Log used in Bluetooth. */ // Next tag value for ContentProfileErrorReportUtils.report(): 3 -public class BluetoothPbapCallLogComposer { +public class BluetoothPbapCallLogComposer implements AutoCloseable { private static final String TAG = "PbapCallLogComposer"; @VisibleForTesting @@ -92,8 +92,6 @@ public class BluetoothPbapCallLogComposer { private final Context mContext; private Cursor mCursor; - private boolean mTerminateIsCalled; - private String mErrorReason = NO_ERROR; private final String RFC_2455_FORMAT = "yyyyMMdd'T'HHmmss"; @@ -281,7 +279,8 @@ public class BluetoothPbapCallLogComposer { toRfc2455Format(dateAsLong)); } - public void terminate() { + /** Closes the composer, releasing all of its resources. */ + public void close() { if (mCursor != null) { try { mCursor.close(); @@ -296,16 +295,6 @@ public class BluetoothPbapCallLogComposer { } mCursor = null; } - - mTerminateIsCalled = true; - } - - @Override - @SuppressWarnings("Finalize") // TODO: b/366307571 remove override - public void finalize() { - if (!mTerminateIsCalled) { - terminate(); - } } public int getCount() { diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java index 620074d1c04..551beb50d81 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java @@ -1103,13 +1103,11 @@ public class BluetoothPbapVcardManager { boolean vCardSelct) { long timestamp = System.currentTimeMillis(); - BluetoothPbapCallLogComposer composer = null; HandlerForStringBuffer buffer = null; - try { + try (BluetoothPbapCallLogComposer composer = new BluetoothPbapCallLogComposer(mContext)) { VCardFilter vcardfilter = new VCardFilter(ignorefilter ? null : filter); PropertySelector vcardselector = new PropertySelector(selector); - composer = new BluetoothPbapCallLogComposer(mContext); buffer = new HandlerForStringBuffer(op, ownerVCard); if (!composer.init(CallLog.Calls.CONTENT_URI, selection, null, CALLLOG_SORT_ORDER) || !buffer.init()) { @@ -1182,9 +1180,6 @@ public class BluetoothPbapVcardManager { return pbSize; } } finally { - if (composer != null) { - composer.terminate(); - } if (buffer != null) { buffer.terminate(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java index cd1699a27c9..6b8c768d0ea 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java @@ -87,6 +87,7 @@ public class BluetoothPbapCallLogComposerTest { @After public void tearDown() throws Exception { BluetoothMethodProxy.setInstanceForTesting(null); + mComposer.close(); } @Test @@ -165,18 +166,10 @@ public class BluetoothPbapCallLogComposerTest { } @Test - public void testTerminate() { + public void testClose() { mComposer.init(CALL_LOG_URI, SELECTION, SELECTION_ARGS, SORT_ORDER); - mComposer.terminate(); - verify(mMockCursor).close(); - } - - @Test - public void testFinalize() { - mComposer.init(CALL_LOG_URI, SELECTION, SELECTION_ARGS, SORT_ORDER); - - mComposer.finalize(); + mComposer.close(); verify(mMockCursor).close(); } -- GitLab From 84f3b3a08282014896fdaa2bd22e721c830efe9f Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Fri, 13 Sep 2024 08:31:49 +0000 Subject: [PATCH 007/875] Remove BluetoothPbapSimVCardManager#finalize Removes the finalize method and makes BluetoothPbapSimVCardManager implement AutoCloseable to allow the use of try-with-resources. Flag: EXEMPT, no logical change Bug: 366307571 Test: atest BluetoothPbapSimVcardManager Change-Id: I69c310196ea805d5c8d8bd857128959b883e3a67 --- .../pbap/BluetoothPbapSimVcardManager.java | 30 ++++--------------- .../BluetoothPbapSimVcardManagerTest.java | 5 ++-- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java index 088e64a227d..ac65f6c78e0 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java @@ -49,7 +49,7 @@ import java.util.List; /** VCard composer especially for Call Log used in Bluetooth. */ // Next tag value for ContentProfileErrorReportUtils.report(): 6 -public class BluetoothPbapSimVcardManager { +public class BluetoothPbapSimVcardManager implements AutoCloseable { private static final String TAG = "PbapSIMvCardComposer"; @VisibleForTesting @@ -90,7 +90,6 @@ public class BluetoothPbapSimVcardManager { private final Context mContext; private ContentResolver mContentResolver; private Cursor mCursor; - private boolean mTerminateIsCalled; private String mErrorReason = NO_ERROR; public BluetoothPbapSimVcardManager(final Context context) { @@ -194,7 +193,8 @@ public class BluetoothPbapSimVcardManager { return builder.toString(); } - public void terminate() { + /** Closes the manager, releasing all of its resources. */ + public void close() { if (mCursor != null) { try { mCursor.close(); @@ -208,16 +208,6 @@ public class BluetoothPbapSimVcardManager { } mCursor = null; } - - mTerminateIsCalled = true; - } - - @Override - @SuppressWarnings("Finalize") // TODO: b/366307571 remove override - public void finalize() { - if (!mTerminateIsCalled) { - terminate(); - } } public int getCount() { @@ -411,10 +401,8 @@ public class BluetoothPbapSimVcardManager { 2); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } - BluetoothPbapSimVcardManager composer = null; HandlerForStringBuffer buffer = null; - try { - composer = new BluetoothPbapSimVcardManager(context); + try (BluetoothPbapSimVcardManager composer = new BluetoothPbapSimVcardManager(context)) { buffer = new HandlerForStringBuffer(op, ownerVCard); if (!composer.init(SIM_URI, null, null, null) || !buffer.init()) { @@ -446,9 +434,6 @@ public class BluetoothPbapSimVcardManager { buffer.writeVCard(vcard); } } finally { - if (composer != null) { - composer.terminate(); - } if (buffer != null) { buffer.terminate(); } @@ -473,10 +458,8 @@ public class BluetoothPbapSimVcardManager { return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } Log.v(TAG, "composeAndSendSIMPhonebookOneVcard orderByWhat " + orderByWhat); - BluetoothPbapSimVcardManager composer = null; HandlerForStringBuffer buffer = null; - try { - composer = new BluetoothPbapSimVcardManager(context); + try (BluetoothPbapSimVcardManager composer = new BluetoothPbapSimVcardManager(context)) { buffer = new HandlerForStringBuffer(op, ownerVCard); if (!composer.init(SIM_URI, null, null, null) || !buffer.init()) { return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; @@ -502,9 +485,6 @@ public class BluetoothPbapSimVcardManager { } buffer.writeVCard(vcard); } finally { - if (composer != null) { - composer.terminate(); - } if (buffer != null) { buffer.terminate(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java index 887a4a42a9b..46129216e37 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java @@ -80,6 +80,7 @@ public class BluetoothPbapSimVcardManagerTest { @After public void tearDown() { + mManager.close(); BluetoothMethodProxy.setInstanceForTesting(null); } @@ -145,9 +146,9 @@ public class BluetoothPbapSimVcardManagerTest { } @Test - public void testTerminate() { + public void testClose() { Cursor cursor = initManager(); - mManager.terminate(); + mManager.close(); verify(cursor).close(); } -- GitLab From 3a7878e1e231784614ac807030b3a16072e79205 Mon Sep 17 00:00:00 2001 From: Sal Savage Date: Mon, 16 Sep 2024 12:11:34 -0700 Subject: [PATCH 008/875] Ignore **/._* MacOS metadata files MacOS creates these hidden files to hold extra file metadata specific to their filesystem and needs when the filesystem format choosen doesn't already do it for them. These files don't need to be committed to version control. They're tedious to remove, as the OS makes them each time you save a file. Bug: 367386917 Flag: EXEMPT, only an update to our gitignore Test: m com.android.btservices Change-Id: Icee50b8f0d294136cab31ad8f5c6978a7fc3c6d9 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3e6891d63f9..057f4717e3b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ compile_commands.json **/.idea **/__pycache__/ *.py[cod] +**/._* -- GitLab From 2eca6e61a29cb9cf9d497ca2e4ddba2b3756a17d Mon Sep 17 00:00:00 2001 From: Jayden Kim Date: Tue, 17 Sep 2024 04:58:27 +0000 Subject: [PATCH 009/875] Flag to have offload socket API Bug: 367419086 Bug: 342012881 Test: m -j Change-Id: Ic1db95307086ae0ee205a0c908e469e5b2d54da2 --- flags/sockets.aconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/flags/sockets.aconfig b/flags/sockets.aconfig index 7b9d6648b62..d45406ac5ae 100644 --- a/flags/sockets.aconfig +++ b/flags/sockets.aconfig @@ -26,3 +26,12 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "bt_offload_socket_api" + namespace: "bluetooth" + description: "New socket API to create offload socket" + bug: "367419086" + is_exported: true +} + -- GitLab From 37fed2de9c8863801ea953db66cdabaa13964362 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 16 Sep 2024 15:17:45 -0700 Subject: [PATCH 010/875] Flag lib link: Use test variant when building test This focus on net_test_bluetooth, net_test_bta, net_test_avrcp because they gave me trouble to pass Bug: 311772251 Test: mmm p/m/Bluetooth Flag: Exempt build change Change-Id: I68fc37a6e1896d6ba1010da1d965f0de3e8b1641 --- system/bta/Android.bp | 2 +- system/btif/Android.bp | 2 +- system/profile/avrcp/Android.bp | 2 +- system/test/suite/Android.bp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 2a045eb9477..db142a96ad9 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -304,7 +304,7 @@ cc_test { "android.hardware.common-V2-ndk", "android.hardware.common.fmq-V1-ndk", "avrcp-target-service", - "bluetooth_flags_c_lib", + "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-types", "libbluetooth_crypto_toolbox", diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 9345183a12e..59b2d959a56 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -294,7 +294,7 @@ cc_test { "android.hardware.audio.common@5.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "bluetooth_flags_c_lib", + "bluetooth_flags_c_lib_for_test", "libFraunhoferAAC", "libbase", "libbluetooth-dumpsys", diff --git a/system/profile/avrcp/Android.bp b/system/profile/avrcp/Android.bp index 60b2947ddd3..8840ae2d9a4 100644 --- a/system/profile/avrcp/Android.bp +++ b/system/profile/avrcp/Android.bp @@ -73,7 +73,7 @@ cc_test { ], static_libs: [ "avrcp-target-service", - "bluetooth_flags_c_lib", + "bluetooth_flags_c_lib_for_test", "lib-bt-packets", "lib-bt-packets-avrcp", "lib-bt-packets-base", diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp index ce0e3f4eb8d..6ad7fdbef55 100644 --- a/system/test/suite/Android.bp +++ b/system/test/suite/Android.bp @@ -120,7 +120,7 @@ cc_test { "gatt/gatt_unittest.cc", ], static_libs: [ - "bluetooth_flags_c_lib", + "bluetooth_flags_c_lib_for_test", "libbluetooth-gdx", "libbluetooth_crypto_toolbox", "libbluetooth_gd", -- GitLab From 510559af0fab301dce366d329abdda7dbb34f6ab Mon Sep 17 00:00:00 2001 From: Ren-Pei Zeng Date: Wed, 18 Sep 2024 06:52:42 +0000 Subject: [PATCH 011/875] Don't use base::StringPrintf with non-constexpr format string https://crrev.com/c/5855070 will disallow it. Bug: 367200458 Test: mmm packages/modules/Bluetooth Tag: #floss Change-Id: Ied9ddb3716174c4664e47f31a64c847c8a0a8e6c --- system/stack/btm/power_mode.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/system/stack/btm/power_mode.h b/system/stack/btm/power_mode.h index f5761436783..cfa98d52294 100644 --- a/system/stack/btm/power_mode.h +++ b/system/stack/btm/power_mode.h @@ -16,8 +16,6 @@ #pragma once -#include - #include #include @@ -85,7 +83,7 @@ inline bool is_legal_power_mode(tBTM_PM_MODE mode) { } inline std::string power_mode_text(tBTM_PM_MODE mode) { - std::string s = base::StringPrintf((mode & BTM_PM_MD_FORCE) ? "" : "forced:"); + std::string s = (mode & BTM_PM_MD_FORCE) ? "" : "forced:"; switch (mode & ~BTM_PM_MD_FORCE) { case BTM_PM_MD_ACTIVE: return s + std::string("active"); -- GitLab From 12a59cda2a755604914320b1652e6c6ce7dac931 Mon Sep 17 00:00:00 2001 From: Ying Hsu Date: Fri, 6 Sep 2024 15:20:03 +0000 Subject: [PATCH 012/875] Add suspend preparation and resume functions to JNI This patch exports the following native bluetooth function to bluetooth service for suspend preparation: + setDefaultEventMaskExcept + clearEventFilter + clearFilterAcceptList + disconnectAllAcls + allowWakeByHid + restoreFilterAcceptList Bug: 327644045 Test: m -j Test: adb shell cmd power sleep Flag: exempt, exporting existing functions to JNI Change-Id: Ia6e8d3fb308e8879bc8f49e91aa6cc095a33efa7 --- ...oid_bluetooth_btservice_AdapterService.cpp | 77 +++++++++++++++++++ .../btservice/AdapterNativeInterface.java | 36 +++++++++ 2 files changed, 113 insertions(+) diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index 72f1e7ce8ad..0d69e449398 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -2143,6 +2143,73 @@ static jint getSocketL2capRemoteChannelIdNative(JNIEnv* /* env */, jobject /* ob return (jint)cid; } +static jboolean setDefaultEventMaskExceptNative(JNIEnv* /* env */, jobject /* obj */, jlong mask, + jlong le_mask) { + log::verbose(""); + + if (!sBluetoothInterface) { + return JNI_FALSE; + } + + int ret = sBluetoothInterface->set_default_event_mask_except(mask, le_mask); + return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean clearEventFilterNative(JNIEnv* /* env */, jobject /* obj */) { + log::verbose(""); + + if (!sBluetoothInterface) { + return JNI_FALSE; + } + + int ret = sBluetoothInterface->clear_event_filter(); + return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean clearFilterAcceptListNative(JNIEnv* /* env */, jobject /* obj */) { + log::verbose(""); + + if (!sBluetoothInterface) { + return JNI_FALSE; + } + + int ret = sBluetoothInterface->clear_filter_accept_list(); + return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean disconnectAllAclsNative(JNIEnv* /* env */, jobject /* obj */) { + log::verbose(""); + + if (!sBluetoothInterface) { + return JNI_FALSE; + } + + int ret = sBluetoothInterface->disconnect_all_acls(); + return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean allowWakeByHidNative(JNIEnv* /* env */, jobject /* obj */) { + log::verbose(""); + + if (!sBluetoothInterface) { + return JNI_FALSE; + } + + int ret = sBluetoothInterface->allow_wake_by_hid(); + return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + +static jboolean restoreFilterAcceptListNative(JNIEnv* /* env */, jobject /* obj */) { + log::verbose(""); + + if (!sBluetoothInterface) { + return JNI_FALSE; + } + + int ret = sBluetoothInterface->restore_filter_accept_list(); + return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; +} + int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) { const JNINativeMethod methods[] = { {"initNative", "(ZZI[Ljava/lang/String;ZLjava/lang/String;)Z", @@ -2207,6 +2274,16 @@ int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) { reinterpret_cast(getSocketL2capLocalChannelIdNative)}, {"getSocketL2capRemoteChannelIdNative", "(JJ)I", reinterpret_cast(getSocketL2capRemoteChannelIdNative)}, + {"setDefaultEventMaskExceptNative", "(JJ)Z", + reinterpret_cast(setDefaultEventMaskExceptNative)}, + {"clearEventFilterNative", "()Z", reinterpret_cast(clearEventFilterNative)}, + {"clearFilterAcceptListNative", "()Z", + reinterpret_cast(clearFilterAcceptListNative)}, + {"disconnectAllAclsNative", "()Z", reinterpret_cast(disconnectAllAclsNative)}, + {"allowWakeByHidNative", "()Z", reinterpret_cast(allowWakeByHidNative)}, + {"restoreFilterAcceptListNative", "()Z", + reinterpret_cast(restoreFilterAcceptListNative)}, + }; const int result = REGISTER_NATIVE_METHODS( env, "com/android/bluetooth/btservice/AdapterNativeInterface", methods); diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java index 1ab1a7ea0c5..28bff10bb75 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java @@ -259,6 +259,30 @@ public class AdapterNativeInterface { connectionUuid.getUuid().getMostSignificantBits()); } + boolean setDefaultEventMaskExcept(long mask, long leMask) { + return setDefaultEventMaskExceptNative(mask, leMask); + } + + boolean clearEventFilter() { + return clearEventFilterNative(); + } + + boolean clearFilterAcceptList() { + return clearFilterAcceptListNative(); + } + + boolean disconnectAllAcls() { + return disconnectAllAclsNative(); + } + + boolean allowWakeByHid() { + return allowWakeByHidNative(); + } + + boolean restoreFilterAcceptList() { + return restoreFilterAcceptListNative(); + } + /**********************************************************************************************/ /*********************************** callbacks from native ************************************/ /**********************************************************************************************/ @@ -371,4 +395,16 @@ public class AdapterNativeInterface { private native int getSocketL2capRemoteChannelIdNative( long connectionUuidLsb, long connectionUuidMsb); + + private native boolean setDefaultEventMaskExceptNative(long mask, long leMask); + + private native boolean clearEventFilterNative(); + + private native boolean clearFilterAcceptListNative(); + + private native boolean disconnectAllAclsNative(); + + private native boolean allowWakeByHidNative(); + + private native boolean restoreFilterAcceptListNative(); } -- GitLab From 4c97123eb6b56b8282a29509201f2a263cd58485 Mon Sep 17 00:00:00 2001 From: Ying Hsu Date: Thu, 19 Sep 2024 12:00:19 +0000 Subject: [PATCH 013/875] Flag: add adapter_suspend_mgmt Bug: 366432079 Test: m -j Flag: Exempt, adding a flag Change-Id: I2f96799686c17c292bc2e015dd5c39881467d69f --- flags/system_service.aconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/flags/system_service.aconfig b/flags/system_service.aconfig index ef23559dd50..517b9f03371 100644 --- a/flags/system_service.aconfig +++ b/flags/system_service.aconfig @@ -64,3 +64,10 @@ flag { description: "Replace binder call to the system server with a Messenger to enforce thread safety" bug: "321804999" } + +flag { + name: "adapter_suspend_mgmt" + namespace: "bluetooth" + description: "Configure the BT adapter in a suspend state to avoid unexpected wake-up" + bug: "366432079" +} -- GitLab From 2ecb9971bec37972a8646023bc2a1604bdd91df7 Mon Sep 17 00:00:00 2001 From: Yun-Hao Chung Date: Fri, 20 Sep 2024 06:29:58 +0000 Subject: [PATCH 014/875] Floss: Remove delay to register callback in non-interactive mode Only introduce delay on interactive mode. This is because we expect the user to ensure the adapter interface is ready when they issue the command in non-interactive mode. Otherwise, there will always have 1 second delay and in most of the case it is not needed. Bug: 368387445 Tag: #floss Test: mmm packages/modules/Bluetooth Test: btclient --command "media info" and observe no delay Test: btclient adapter enable in interactive mode and observe a delay Flag: EXEMPT, Floss-only changes Change-Id: Ica0d9146c1947c3cd9236b5d2541d8fc8c9bf3d8 --- system/gd/rust/linux/client/src/main.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/system/gd/rust/linux/client/src/main.rs b/system/gd/rust/linux/client/src/main.rs index 8d609b7cd0f..f966314dbbc 100644 --- a/system/gd/rust/linux/client/src/main.rs +++ b/system/gd/rust/linux/client/src/main.rs @@ -146,6 +146,9 @@ pub(crate) struct ClientContext { /// Is btclient running in restricted mode? is_restricted: bool, + /// Is btclient running in interactive mode? + is_interactive: bool, + /// Data of GATT client preference. gatt_client_context: GattClientContext, @@ -174,6 +177,7 @@ impl ClientContext { dbus_crossroads: Arc>, tx: mpsc::Sender, is_restricted: bool, + is_interactive: bool, client_commands_with_callbacks: Vec, ) -> ClientContext { // Manager interface is almost always available but adapter interface @@ -212,6 +216,7 @@ impl ClientContext { socket_manager_callback_id: None, qa_callback_id: None, is_restricted, + is_interactive, gatt_client_context: GattClientContext::new(), gatt_server_context: GattServerContext::new(), socket_test_schedule: None, @@ -271,11 +276,19 @@ impl ClientContext { // Trigger callback registration in the foreground let fg = self.fg.clone(); + let is_interactive = self.is_interactive; tokio::spawn(async move { let adapter = format!("adapter{}", idx); + // Floss won't export the interface until it is ready to be used. // Wait 1 second before registering the callbacks. - sleep(Duration::from_millis(1000)).await; + // Only introduce such delay on interactive mode. This is because we expect the user to + // ensure the adapter interface is ready when they issue the command in non-interactive + // mode. Otherwise, there will always have 1 second delay and in most of the case it is + // not needed. + if is_interactive { + sleep(Duration::from_millis(1000)).await; + } let _ = fg.send(ForegroundActions::RegisterAdapterCallback(adapter)).await; }); } @@ -364,6 +377,7 @@ fn main() -> Result<(), Box> { .get_matches(); let command = value_t!(matches, "command", String).ok(); let is_restricted = matches.is_present("restricted"); + let is_interactive = command.is_none(); let timeout_secs = value_t!(matches, "timeout", u64); topstack::get_runtime().block_on(async move { @@ -408,6 +422,7 @@ fn main() -> Result<(), Box> { cr.clone(), tx.clone(), is_restricted, + is_interactive, client_commands_with_callbacks, ))); @@ -449,7 +464,7 @@ fn main() -> Result<(), Box> { }; let handler = CommandHandler::new(context.clone()); - if command.is_some() { + if !is_interactive { // Timeout applies only to non-interactive commands. if let Ok(timeout_secs) = timeout_secs { let timeout_duration = Duration::from_secs(timeout_secs); -- GitLab From 2d2786a4676629aa023e7b5e1e4b849ef3b9609d Mon Sep 17 00:00:00 2001 From: Ying Hsu Date: Fri, 6 Sep 2024 15:33:09 +0000 Subject: [PATCH 015/875] Initial implementation for AdapterSuspend AdapterSuspend listens to Display state changes and configures the Bluetooth controller to only allow wake events from bonded Bluetooth HID devices. This ensures that the system can be woken up by Bluetooth while minimizing power consumption. Bug: 327644045 Bug: 366432079 Test: m -j Test: suspend system and wake it up by classic mouse Flag: adapter_suspend_mgmt Change-Id: I22f7fa49397d365ec59d4db61da14372bffe5b86 --- .../bluetooth/btservice/AdapterService.java | 13 ++ .../bluetooth/btservice/AdapterSuspend.java | 120 ++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 953b1144b58..822b0d462f5 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -87,6 +87,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.hardware.display.DisplayManager; import android.os.AsyncTask; import android.os.BatteryStatsManager; import android.os.Binder; @@ -280,6 +281,7 @@ public class AdapterService extends Service { private AdapterState mAdapterStateMachine; private BondStateMachine mBondStateMachine; private RemoteDevices mRemoteDevices; + private AdapterSuspend mAdapterSuspend; /* TODO: Consider to remove the search API from this class, if changed to use call-back */ private SdpManager mSdpManager = null; @@ -754,6 +756,12 @@ public class AdapterService extends Service { mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this); + if (Flags.adapterSuspendMgmt()) { + mAdapterSuspend = + new AdapterSuspend( + mNativeInterface, mLooper, getSystemService(DisplayManager.class)); + } + if (!Flags.fastBindToApp()) { setAdapterService(this); } @@ -1481,6 +1489,11 @@ public class AdapterService extends Service { mBluetoothSocketManagerBinder = null; } + if (mAdapterSuspend != null) { + mAdapterSuspend.cleanup(); + mAdapterSuspend = null; + } + mPreferredAudioProfilesCallbacks.kill(); mBluetoothQualityReportReadyCallbacks.kill(); diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java b/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java new file mode 100644 index 00000000000..ab5187b14b1 --- /dev/null +++ b/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java @@ -0,0 +1,120 @@ +/* + * 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. + */ + +package com.android.bluetooth.btservice; + +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE; +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE; + +import static java.util.Objects.requireNonNull; + +import android.hardware.display.DisplayManager; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.view.Display; + +import java.util.Arrays; + +public class AdapterSuspend { + private static final String TAG = "BtAdapterSuspend"; + + // Event mask bits corresponding to specific HCI events + // as defined in Bluetooth core v5.4, Vol 4, Part E, 7.3.1. + private static final long MASK_DISCONNECT_CMPLT = 1 << 4; + private static final long MASK_MODE_CHANGE = 1 << 19; + + private boolean mSuspended = false; + + private final AdapterNativeInterface mAdapterNativeInterface; + private final Looper mLooper; + private final DisplayManager mDisplayManager; + private final DisplayManager.DisplayListener mDisplayListener = + new DisplayManager.DisplayListener() { + @Override + public void onDisplayAdded(int displayId) {} + + @Override + public void onDisplayRemoved(int displayId) {} + + @Override + public void onDisplayChanged(int displayId) { + if (isScreenOn()) { + handleResume(); + } else { + handleSuspend(); + } + } + }; + + public AdapterSuspend( + AdapterNativeInterface adapterNativeInterface, + Looper looper, + DisplayManager displayManager) { + mAdapterNativeInterface = requireNonNull(adapterNativeInterface); + mLooper = requireNonNull(looper); + mDisplayManager = requireNonNull(displayManager); + + mDisplayManager.registerDisplayListener(mDisplayListener, new Handler(mLooper)); + } + + void cleanup() { + mDisplayManager.unregisterDisplayListener(mDisplayListener); + } + + private boolean isScreenOn() { + return Arrays.stream(mDisplayManager.getDisplays()) + .anyMatch(display -> display.getState() == Display.STATE_ON); + } + + private void handleSuspend() { + if (mSuspended) { + return; + } + mSuspended = true; + + long mask = MASK_DISCONNECT_CMPLT | MASK_MODE_CHANGE; + long leMask = 0; + + // Avoid unexpected interrupt during suspend. + mAdapterNativeInterface.setDefaultEventMaskExcept(mask, leMask); + + // Disable inquiry scan and page scan. + mAdapterNativeInterface.setScanMode(AdapterService.convertScanModeToHal(SCAN_MODE_NONE)); + + mAdapterNativeInterface.clearEventFilter(); + mAdapterNativeInterface.clearFilterAcceptList(); + mAdapterNativeInterface.disconnectAllAcls(); + mAdapterNativeInterface.allowWakeByHid(); + Log.i(TAG, "ready to suspend"); + } + + private void handleResume() { + if (!mSuspended) { + return; + } + mSuspended = false; + + long mask = 0; + long leMask = 0; + mAdapterNativeInterface.setDefaultEventMaskExcept(mask, leMask); + mAdapterNativeInterface.clearEventFilter(); + mAdapterNativeInterface.restoreFilterAcceptList(); + mAdapterNativeInterface.setScanMode( + AdapterService.convertScanModeToHal(SCAN_MODE_CONNECTABLE)); + Log.i(TAG, "resumed"); + } +} -- GitLab From b72f776ff5f5c277eb15d410d5b1cef5e5144d13 Mon Sep 17 00:00:00 2001 From: Mariusz Skamra Date: Fri, 26 Jul 2024 12:54:11 +0000 Subject: [PATCH 016/875] btm: btm_iso: Fix handling cancelled Create CIS procedure This fixes kIsoEventCisDisconnected event that was not generated when the CIS creation has been cancelled by local host. As per Core 5.4 Vol 4, Part E, 7.1.6 Disconnect Command: "If this command is issued for a CIS on the Central and the CIS is successfully terminated before being established, then an HCI_LE_CIS_Established event shall also be sent for this CIS with the Status Operation Cancelled by Host (0x44)." Bug: 357472821 Flag: Exempt; regression covered by unit test added Test: atest net_test_btm_iso Change-Id: I7512e5ff26f40ef4f58f0b7f1473ba07170a7582 --- system/stack/btm/btm_iso_impl.h | 15 ++- system/stack/include/hci_error_code.h | 4 +- system/stack/test/btm_iso_test.cc | 168 +++++++++++++++++++++++++- 3 files changed, 182 insertions(+), 5 deletions(-) diff --git a/system/stack/btm/btm_iso_impl.h b/system/stack/btm/btm_iso_impl.h index a4ee3694ac5..6c5f0887136 100644 --- a/system/stack/btm/btm_iso_impl.h +++ b/system/stack/btm/btm_iso_impl.h @@ -53,6 +53,7 @@ static constexpr uint8_t kStateFlagIsConnecting = 0x01; static constexpr uint8_t kStateFlagIsConnected = 0x02; static constexpr uint8_t kStateFlagHasDataPathSet = 0x04; static constexpr uint8_t kStateFlagIsBroadcast = 0x10; +static constexpr uint8_t kStateFlagIsCancelled = 0x20; constexpr char kBtmLogTag[] = "ISO"; @@ -282,8 +283,9 @@ struct iso_impl { for (auto& el : conn_params.conn_pairs) { auto cis = GetCisIfKnown(el.cis_conn_handle); log::assert_that(cis, "No such cis: {}", el.cis_conn_handle); - log::assert_that(!(cis->state_flags & (kStateFlagIsConnected | kStateFlagIsConnecting)), - "cis: {} is already connected or connecting flags: {}, " + log::assert_that(!(cis->state_flags & + (kStateFlagIsConnected | kStateFlagIsConnecting | kStateFlagIsCancelled)), + "cis: {} is already connected/connecting/cancelled flags: {}, " "num of cis params: {}", el.cis_conn_handle, cis->state_flags, conn_params.conn_pairs.size()); @@ -307,6 +309,12 @@ struct iso_impl { log::assert_that( cis->state_flags & kStateFlagIsConnected || cis->state_flags & kStateFlagIsConnecting, "Not connected"); + + if (cis->state_flags & kStateFlagIsConnecting) { + cis->state_flags &= ~kStateFlagIsConnecting; + cis->state_flags |= kStateFlagIsCancelled; + } + bluetooth::legacy::hci::GetInterface().Disconnect(cis_handle, static_cast(reason)); BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[cis_handle], "Disconnect CIS ", @@ -603,7 +611,7 @@ struct iso_impl { hci_error_code_text((tHCI_REASON)(reason)).c_str())); cis_hdl_to_addr.erase(handle); - if (cis->state_flags & kStateFlagIsConnected) { + if (cis->state_flags & kStateFlagIsConnected || cis->state_flags & kStateFlagIsCancelled) { cis_disconnected_evt evt = { .reason = reason, .cig_id = cis->cig_id, @@ -612,6 +620,7 @@ struct iso_impl { cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt); cis->state_flags &= ~kStateFlagIsConnected; + cis->state_flags &= ~kStateFlagIsCancelled; /* return used credits */ iso_credits_ += cis->used_credits; diff --git a/system/stack/include/hci_error_code.h b/system/stack/include/hci_error_code.h index fff15c1f353..cb20570591c 100644 --- a/system/stack/include/hci_error_code.h +++ b/system/stack/include/hci_error_code.h @@ -68,8 +68,9 @@ typedef enum : uint8_t { HCI_ERR_ADVERTISING_TIMEOUT = 0x3C, // stack/btm/btm_ble HCI_ERR_CONN_FAILED_ESTABLISHMENT = 0x3E, // GATT_CONN_FAIL_ESTABLISH HCI_ERR_LIMIT_REACHED = 0x43, // stack/btm/btm_ble_multi_adv.cc + HCI_ERR_CANCELLED_BY_LOCAL_HOST = 0x44, // stack/btm/btm_iso_impl.h - _HCI_ERR_MAX_ERR = 0x43, + _HCI_ERR_MAX_ERR = 0x44, HCI_ERR_UNDEFINED = 0xff, } tHCI_ERROR_CODE; @@ -117,6 +118,7 @@ inline std::string hci_error_code_text(const tHCI_ERROR_CODE& error_code) { CASE_RETURN_TEXT(HCI_ERR_ADVERTISING_TIMEOUT); CASE_RETURN_TEXT(HCI_ERR_CONN_FAILED_ESTABLISHMENT); CASE_RETURN_TEXT(HCI_ERR_LIMIT_REACHED); + CASE_RETURN_TEXT(HCI_ERR_CANCELLED_BY_LOCAL_HOST); default: return base::StringPrintf("UNKNOWN[0x%02hx]", error_code); } diff --git a/system/stack/test/btm_iso_test.cc b/system/stack/test/btm_iso_test.cc index b9a1cc036d8..489a356f4e0 100644 --- a/system/stack/test/btm_iso_test.cc +++ b/system/stack/test/btm_iso_test.cc @@ -932,7 +932,7 @@ TEST_F(IsoManagerDeathTest, ConnectSameCisTwice) { IsoManager::GetInstance()->EstablishCis(params); ASSERT_EXIT(IsoManager::GetInstance()->IsoManager::GetInstance()->EstablishCis(params), - ::testing::KilledBySignal(SIGABRT), "already connected or connecting"); + ::testing::KilledBySignal(SIGABRT), "already connected/connecting/cancelled"); } TEST_F(IsoManagerDeathTest, EstablishCisInvalidResponsePacket) { @@ -1133,6 +1133,172 @@ TEST_F(IsoManagerTest, EstablishCisLateArrivingCallback) { std::move(iso_cb).Run(buf.data(), buf.size()); } +TEST_F(IsoManagerTest, CancelPendingCreateCis_EstablishedThenDisconnected) { + /** + * Verify the HCI Disconnect command will cancel pending CIS creation. + * As the Core is not strict about event order, in this scenario HCI CIS Established event comes + * before HCI Disconnection Complete event. + * + * Scenario: + * 1. Issue the HCI LE Create CIS command. + * 2. Issue HCI Disconnect command with CIS connection handle parameter before the HCI CIS + * Established event is received. + * 3. Verify the kIsoEventCisEstablishCmpl event is generated once HCI CIS Established event is + * received with Operation Cancelled By Local Host error. + * 4. Verify the kIsoEventCisDisconnected event is generated once HCI Disconnection Complete event + * is received. + */ + + IsoManager::GetInstance()->CreateCig(volatile_test_cig_create_cmpl_evt_.cig_id, + kDefaultCigParams); + ON_CALL(hcic_interface_, CreateCis) + .WillByDefault([](uint8_t, const EXT_CIS_CREATE_CFG*, + base::OnceCallback /* cb */) { + /* We override default mock. Nothing to do here */ + }); + + ON_CALL(hcic_interface_, Disconnect).WillByDefault([](uint16_t, uint8_t) { + /* We override default mock. Nothing to do here */ + }); + + EXPECT_CALL(*cig_callbacks_, + OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisEstablishCmpl, _)) + .Times(kDefaultCigParams.cis_cfgs.size()) + .WillRepeatedly([this](uint8_t /* type */, void* data) { + auto* event = static_cast(data); + ASSERT_EQ(event->status, HCI_ERR_CANCELLED_BY_LOCAL_HOST); + ASSERT_EQ(event->cig_id, volatile_test_cig_create_cmpl_evt_.cig_id); + ASSERT_TRUE(std::find(volatile_test_cig_create_cmpl_evt_.conn_handles.begin(), + volatile_test_cig_create_cmpl_evt_.conn_handles.end(), + event->cis_conn_hdl) != + volatile_test_cig_create_cmpl_evt_.conn_handles.end()); + }); + + EXPECT_CALL(*cig_callbacks_, OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDisconnected, _)) + .Times(kDefaultCigParams.cis_cfgs.size()) + .WillRepeatedly([this](uint8_t /* type */, void* data) { + auto* event = static_cast(data); + ASSERT_EQ(event->reason, HCI_ERR_CONN_CAUSE_LOCAL_HOST); + ASSERT_EQ(event->cig_id, volatile_test_cig_create_cmpl_evt_.cig_id); + ASSERT_TRUE(std::find(volatile_test_cig_create_cmpl_evt_.conn_handles.begin(), + volatile_test_cig_create_cmpl_evt_.conn_handles.end(), + event->cis_conn_hdl) != + volatile_test_cig_create_cmpl_evt_.conn_handles.end()); + }); + + EXPECT_CALL(hcic_interface_, CreateCis).Times(1); + + // Establish all CISes before setting up their data paths + bluetooth::hci::iso_manager::cis_establish_params params; + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + params.conn_pairs.push_back({handle, 1}); + } + IsoManager::GetInstance()->EstablishCis(params); + + EXPECT_CALL(hcic_interface_, Disconnect).Times(kDefaultCigParams.cis_cfgs.size()); + + /* Cancel pending HCI LE Create CIS command */ + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + IsoManager::GetInstance()->DisconnectCis(handle, HCI_ERR_CONN_CAUSE_LOCAL_HOST); + } + + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + std::vector buf(28, 0); + uint8_t* p = buf.data(); + UINT8_TO_STREAM(p, HCI_ERR_CANCELLED_BY_LOCAL_HOST); + UINT16_TO_STREAM(p, handle); + + /* inject HCI LE CIS Established event */ + IsoManager::GetInstance()->HandleHciEvent(HCI_BLE_CIS_EST_EVT, buf.data(), buf.size()); + + /* followed by HCI Disconnection Complete event */ + IsoManager::GetInstance()->HandleDisconnect(handle, HCI_ERR_CONN_CAUSE_LOCAL_HOST); + } +} + +TEST_F(IsoManagerTest, CancelPendingCreateCis_DisconnectedThenEstablished) { + /** + * Verify the HCI Disconnect command will cancel pending CIS creation. + * As the Core is not strict about event order, in this scenario HCI Disconnection Complete event + * comes before HCI CIS Established event. + * + * Scenario: + * 1. Issue the HCI LE Create CIS command. + * 2. Issue HCI Disconnect command with CIS connection handle parameter before the HCI CIS + * Established event is received. + * 3. Verify the kIsoEventCisEstablishCmpl event is generated once HCI CIS Established event is + * received with Operation Cancelled By Local Host error. + * 4. Verify the kIsoEventCisDisconnected event is generated once HCI Disconnection Complete event + * is received. + */ + + IsoManager::GetInstance()->CreateCig(volatile_test_cig_create_cmpl_evt_.cig_id, + kDefaultCigParams); + ON_CALL(hcic_interface_, CreateCis) + .WillByDefault([](uint8_t, const EXT_CIS_CREATE_CFG*, + base::OnceCallback /* cb */) { + /* We override default mock. Nothing to do here */ + }); + + ON_CALL(hcic_interface_, Disconnect).WillByDefault([](uint16_t, uint8_t) { + /* We override default mock. Nothing to do here */ + }); + + EXPECT_CALL(*cig_callbacks_, + OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisEstablishCmpl, _)) + .Times(kDefaultCigParams.cis_cfgs.size()) + .WillRepeatedly([this](uint8_t /* type */, void* data) { + auto* event = static_cast(data); + ASSERT_EQ(event->status, HCI_ERR_CANCELLED_BY_LOCAL_HOST); + ASSERT_EQ(event->cig_id, volatile_test_cig_create_cmpl_evt_.cig_id); + ASSERT_TRUE(std::find(volatile_test_cig_create_cmpl_evt_.conn_handles.begin(), + volatile_test_cig_create_cmpl_evt_.conn_handles.end(), + event->cis_conn_hdl) != + volatile_test_cig_create_cmpl_evt_.conn_handles.end()); + }); + + EXPECT_CALL(*cig_callbacks_, OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDisconnected, _)) + .Times(kDefaultCigParams.cis_cfgs.size()) + .WillRepeatedly([this](uint8_t /* type */, void* data) { + auto* event = static_cast(data); + ASSERT_EQ(event->reason, HCI_ERR_CONN_CAUSE_LOCAL_HOST); + ASSERT_EQ(event->cig_id, volatile_test_cig_create_cmpl_evt_.cig_id); + ASSERT_TRUE(std::find(volatile_test_cig_create_cmpl_evt_.conn_handles.begin(), + volatile_test_cig_create_cmpl_evt_.conn_handles.end(), + event->cis_conn_hdl) != + volatile_test_cig_create_cmpl_evt_.conn_handles.end()); + }); + + EXPECT_CALL(hcic_interface_, CreateCis).Times(1); + + // Establish all CISes before setting up their data paths + bluetooth::hci::iso_manager::cis_establish_params params; + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + params.conn_pairs.push_back({handle, 1}); + } + IsoManager::GetInstance()->EstablishCis(params); + + EXPECT_CALL(hcic_interface_, Disconnect).Times(kDefaultCigParams.cis_cfgs.size()); + + /* Cancel pending HCI LE Create CIS command */ + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + IsoManager::GetInstance()->DisconnectCis(handle, HCI_ERR_CONN_CAUSE_LOCAL_HOST); + } + + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + /* inject HCI Disconnection Complete event */ + IsoManager::GetInstance()->HandleDisconnect(handle, HCI_ERR_CONN_CAUSE_LOCAL_HOST); + + std::vector buf(28, 0); + uint8_t* p = buf.data(); + UINT8_TO_STREAM(p, HCI_ERR_CANCELLED_BY_LOCAL_HOST); + UINT16_TO_STREAM(p, handle); + + /* followed by inject HCI LE CIS Established event */ + IsoManager::GetInstance()->HandleHciEvent(HCI_BLE_CIS_EST_EVT, buf.data(), buf.size()); + } +} + TEST_F(IsoManagerTest, ReconnectCisValid) { IsoManager::GetInstance()->CreateCig(volatile_test_cig_create_cmpl_evt_.cig_id, kDefaultCigParams); -- GitLab From e0f16d16da06462d8ef911343cc0b0bc5834c105 Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Fri, 20 Sep 2024 18:19:41 +0000 Subject: [PATCH 017/875] Pandora: add linter file for Pandora Server Bug: 367811137 Test: manual Flag: EXEMPT Change-Id: If2ccf4d57af5816176d594e7db5fb6dd34b051b2 --- android/pandora/server/build.gradle.kts | 59 +++++++++++++++++++++++++ android/pandora/server/kls-classpath | 34 ++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 android/pandora/server/build.gradle.kts create mode 100755 android/pandora/server/kls-classpath diff --git a/android/pandora/server/build.gradle.kts b/android/pandora/server/build.gradle.kts new file mode 100644 index 00000000000..c80dc5e612a --- /dev/null +++ b/android/pandora/server/build.gradle.kts @@ -0,0 +1,59 @@ +/* + * Copyright (C) 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. + */ + +// This build.gradle.kts file is solely for the purpose of satisfying the linter's requirements. +// The actual build process is handled by Soong via the Android.bp +plugins { + // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. + id("org.jetbrains.kotlin.jvm") version "1.8.20" + + // Apply the java-library plugin for API and implementation separation. + `java-library` +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +sourceSets.main { + java { + exclude("**/*.bp") + srcDirs("src") + } +} + +val android_build_top = System.getenv("ANDROID_BUILD_TOP") ?: "../../../../../../" +val out = "${android_build_top}/out/soong/.intermediates" + +dependencies { + // Kotlin coroutines + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2") + // Kotlin std + implementation(files("$android_build_top/external/kotlinc/lib/kotlin-stdlib.jar")) + // Android system SDK + implementation(files("$android_build_top/prebuilts/sdk/33/system-server/android.jar")) + // Framework Bluetooth + implementation(files("$out/packages/modules/Bluetooth/framework/framework-bluetooth-pre-jarjar/android_common/turbine-combined/framework-bluetooth-pre-jarjar.jar")) + // Pandora APIs + implementation(files("$out/packages/modules/Bluetooth/pandora/interfaces/pandora-grpc-java/android_common/combined/pandora-grpc-java.jar")) + implementation(files("$out/packages/modules/Bluetooth/pandora/interfaces/pandora-proto-java/android_common/combined/pandora-proto-java.jar")) + // Androidx Test Core + implementation(files("$out/prebuilts/misc/common/androidx-test/androidx.test.core/android_common/combined/androidx.test.core.jar")) + // Protobuf + implementation(files("$out/external/protobuf/libprotobuf-java-micro/android_common/turbine-combined/libprotobuf-java-micro.jar")) +} + diff --git a/android/pandora/server/kls-classpath b/android/pandora/server/kls-classpath new file mode 100755 index 00000000000..ee395ff4b78 --- /dev/null +++ b/android/pandora/server/kls-classpath @@ -0,0 +1,34 @@ +#!/bin/bash +# Copyright (C) 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. + +if [ -n "${ANDROID_BUILD_TOP}" ]; then + ANDROID_SOURCE_TREE="${ANDROID_BUILD_TOP}" +else + ANDROID_SOURCE_TREE="$PWD/../../../../../../" +fi + +OUT="${ANDROID_SOURCE_TREE}out/soong/.intermediates/" + +CLASSPATH="" +CLASSPATH+="${ANDROID_SOURCE_TREE}external/kotlinc/lib/kotlin-stdlib.jar" +CLASSPATH+=":${ANDROID_SOURCE_TREE}prebuilts/sdk/33/system-server/android.jar" +CLASSPATH+=":${OUT}external/kotlinx.coroutines/kotlinx-coroutines-core/android_common/turbine-combined/kotlinx-coroutines-core.jar" +CLASSPATH+=":${OUT}packages/modules/Bluetooth/framework/framework-bluetooth-pre-jarjar/android_common/turbine-combined/framework-bluetooth-pre-jarjar.jar" +CLASSPATH+=":${OUT}packages/modules/Bluetooth/pandora/interfaces/pandora-grpc-java/android_common/turbine-combined/pandora-grpc-java.jar" +CLASSPATH+=":${OUT}packages/modules/Bluetooth/pandora/interfaces/pandora-proto-java/android_common/turbine-combined/pandora-proto-java.jar" +CLASSPATH+=":${OUT}prebuilts/misc/common/androidx-test/androidx.test.core/android_common/combined/androidx.test.core.jar" +CLASSPATH+=":${OUT}external/protobuf/libprotobuf-java-micro/android_common/turbine-combined/libprotobuf-java-micro.jar" + +echo "$CLASSPATH" -- GitLab From 2a954456cdf8130410a91c1af0a8ecfa9229e16d Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Fri, 20 Sep 2024 18:20:22 +0000 Subject: [PATCH 018/875] Pandora: update linter file for BumbleBluetoothTests Update file to reflect recent proto build modification Bug: 367811137 Test: manual Flag: EXEMPT Change-Id: Ibc430ec4c77819d689f06f6883e67caa18e9d226 --- framework/tests/bumble/build.gradle.kts | 4 ++-- framework/tests/bumble/kls-classpath | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/tests/bumble/build.gradle.kts b/framework/tests/bumble/build.gradle.kts index c2c39c4c1e0..4d926fa1334 100644 --- a/framework/tests/bumble/build.gradle.kts +++ b/framework/tests/bumble/build.gradle.kts @@ -49,8 +49,8 @@ dependencies { // Framework Bluetooth implementation(files("$out/packages/modules/Bluetooth/framework/framework-bluetooth-pre-jarjar/android_common/turbine-combined/framework-bluetooth-pre-jarjar.jar")) // Pandora APIs - implementation(files("$out/packages/modules/Bluetooth/pandora/interfaces/pandora_experimental-grpc-java/android_common/combined/pandora_experimental-grpc-java.jar")) - implementation(files("$out/packages/modules/Bluetooth/pandora/interfaces/pandora_experimental-proto-java/android_common/combined/pandora_experimental-proto-java.jar")) + implementation(files("$out/packages/modules/Bluetooth/pandora/interfaces/pandora-grpc-java/android_common/combined/pandora-grpc-java.jar")) + implementation(files("$out/packages/modules/Bluetooth/pandora/interfaces/pandora-proto-java/android_common/combined/pandora-proto-java.jar")) // Junit implementation(files("$out/external/junit/junit/android_common/turbine-combined/junit.jar")) // Truth diff --git a/framework/tests/bumble/kls-classpath b/framework/tests/bumble/kls-classpath index 581ec695597..623aeb0428a 100755 --- a/framework/tests/bumble/kls-classpath +++ b/framework/tests/bumble/kls-classpath @@ -26,8 +26,8 @@ CLASSPATH+="${ANDROID_SOURCE_TREE}external/kotlinc/lib/kotlin-stdlib.jar" CLASSPATH+=":${ANDROID_SOURCE_TREE}prebuilts/sdk/33/system-server/android.jar" CLASSPATH+=":${OUT}external/kotlinx.coroutines/kotlinx-coroutines-core/android_common/turbine-combined/kotlinx-coroutines-core.jar" CLASSPATH+=":${OUT}packages/modules/Bluetooth/framework/framework-bluetooth-pre-jarjar/android_common/turbine-combined/framework-bluetooth-pre-jarjar.jar" -CLASSPATH+=":${OUT}packages/modules/Bluetooth/pandora/interfaces/pandora_experimental-grpc-java/android_common/combined/pandora_experimental-grpc-java.jar" -CLASSPATH+=":${OUT}packages/modules/Bluetooth/pandora/interfaces/pandora_experimental-proto-java/android_common/combined/pandora_experimental-proto-java.jar" +CLASSPATH+=":${OUT}packages/modules/Bluetooth/pandora/interfaces/pandora-grpc-java/android_common/turbine-combined/pandora-grpc-java.jar" +CLASSPATH+=":${OUT}packages/modules/Bluetooth/pandora/interfaces/pandora-proto-java/android_common/turbine-combined/pandora-proto-java.jar" CLASSPATH+=":${OUT}external/junit/junit/android_common/turbine-combined/junit.jar" CLASSPATH+=":${OUT}external/truth/truth/android_common/turbine-combined/truth.jar" CLASSPATH+=":${OUT}prebuilts/misc/common/androidx-test/androidx.test.core/android_common/combined/androidx.test.core.jar" -- GitLab From 896d90a10b8d50e5a6f5fcb51a3d48e6e2548fcd Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Mon, 23 Sep 2024 07:56:45 +0000 Subject: [PATCH 019/875] fix for exception TypeError:to_bytes() missing required argument 'byteorder' (pos 2) Test: atest HidHostTest Flag: TEST_ONLY Bug: 368575445 Change-Id: I9831bd2b394bf823e8e23f29ebc4bd6ab09ed384 --- pandora/server/bumble_experimental/hid.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandora/server/bumble_experimental/hid.py b/pandora/server/bumble_experimental/hid.py index 71f49bb0d6d..0b2f6867e26 100644 --- a/pandora/server/bumble_experimental/hid.py +++ b/pandora/server/bumble_experimental/hid.py @@ -4,6 +4,7 @@ import grpc import grpc.aio import logging import struct +import sys from bumble.device import Device from google.protobuf import empty_pb2 # pytype: disable=pyi-error @@ -674,7 +675,7 @@ def on_set_report_cb(report_id: int, report_type: int, report_size: int, data: b def on_get_protocol_cb(): retValue = hid_device.GetSetStatus() - retValue.data = protocol_mode.to_bytes(length=1) + retValue.data = protocol_mode.to_bytes(length=1, byteorder=sys.byteorder) retValue.status = hid_device.GetSetReturn.SUCCESS return retValue -- GitLab From 256ed77be15751a933edb553f310dea544d27429 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Thu, 19 Sep 2024 07:04:59 +0000 Subject: [PATCH 020/875] Add assumption to test SmsMessage.calculateLength() requires the FEATURE_TELEPHONY_MESSAGING feature. This commit adds an assumption to disable the test on environments lacking this feature. Flag: EXEMPT, test only change Test: atest BluetoothMapsmsPduTest Bug: 367385963 Change-Id: Id84442abb6ea5006a897779f17e32b50a0c93740 --- .../bluetooth/map/BluetoothMapSmsPduTest.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java index 2eeadc299aa..98c44f03c7d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java @@ -16,22 +16,26 @@ package com.android.bluetooth.map; +import static android.content.pm.PackageManager.FEATURE_TELEPHONY_MESSAGING; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.pm.PackageManager; import android.telephony.SmsManager; import android.telephony.SmsMessage; import android.telephony.TelephonyManager; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.map.BluetoothMapSmsPdu.SmsPdu; -import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -66,6 +70,9 @@ public class BluetoothMapSmsPduTest { @Before public void setUp() throws Exception { + PackageManager packageManager = + InstrumentationRegistry.getTargetContext().getPackageManager(); + assumeTrue(packageManager.isPackageAvailable(FEATURE_TELEPHONY_MESSAGING)); when(mTargetContext.getSystemServiceName(TelephonyManager.class)) .thenReturn("TELEPHONY_SERVICE"); when(mTargetContext.getSystemService("TELEPHONY_SERVICE")).thenReturn(mTelephonyManager); @@ -104,7 +111,7 @@ public class BluetoothMapSmsPduTest { @Test public void getSubmitPdus_withTypeGSM_whenMsgCountIsMoreThanOne() throws Exception { // Do not run test if sms is not supported - Assume.assumeTrue(mSmsManager.isImsSmsSupported()); + assumeTrue(mSmsManager.isImsSmsSupported()); when(mTelephonyManager.getCurrentPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM); List pdus = @@ -133,7 +140,7 @@ public class BluetoothMapSmsPduTest { @Test public void getSubmitPdus_withTypeCDMA() throws Exception { // Do not run test if sms is not supported - Assume.assumeTrue(mSmsManager.isImsSmsSupported()); + assumeTrue(mSmsManager.isImsSmsSupported()); when(mTelephonyManager.getCurrentPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA); List pdus = BluetoothMapSmsPdu.getSubmitPdus(mTargetContext, TEST_TEXT, null); @@ -158,7 +165,7 @@ public class BluetoothMapSmsPduTest { @Test public void getDeliverPdus_withTypeGSM() throws Exception { // Do not run test if sms is not supported - Assume.assumeTrue(mSmsManager.isImsSmsSupported()); + assumeTrue(mSmsManager.isImsSmsSupported()); when(mTelephonyManager.getCurrentPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM); List pdus = @@ -187,7 +194,7 @@ public class BluetoothMapSmsPduTest { @Test public void getDeliverPdus_withTypeCDMA() throws Exception { // Do not run test if sms is not supported - Assume.assumeTrue(mSmsManager.isImsSmsSupported()); + assumeTrue(mSmsManager.isImsSmsSupported()); when(mTelephonyManager.getCurrentPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA); List pdus = -- GitLab From 472ac7e75cbf24d7cac6607dc19e7da981bcaa7e Mon Sep 17 00:00:00 2001 From: Nitin Jadhav Date: Thu, 23 May 2024 06:37:39 +0000 Subject: [PATCH 021/875] Call Index: To Handle HFP index change after call Merge and disconnect Bug: 318460024 Bug: 345380335 Test: Manual | Make two incomming calls, merge calls & disconnect first call Test: atest BluetoothInCallServiceTest#conferenceLastCallIndexIsMaintained Flag: com.android.bluetooth.flags.maintain_call_index_after_conference Change-Id: Ibf7015d7a250d62641a9e1df417d17d75bad71b6 --- .../telephony/BluetoothInCallService.java | 56 +++++++++ .../telephony/BluetoothInCallServiceTest.java | 119 ++++++++++++++++++ 2 files changed, 175 insertions(+) diff --git a/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java b/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java index ee7a14cbfb4..bd0b40ec4fe 100644 --- a/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java +++ b/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java @@ -55,6 +55,7 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.bluetooth.Utils; +import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hfp.BluetoothHeadsetProxy; import com.android.bluetooth.tbs.BluetoothLeCallControlProxy; @@ -138,6 +139,8 @@ public class BluetoothInCallService extends InCallService { private final HashMap mBluetoothConferenceCallInference = new HashMap<>(); + private final HashMap mConferenceCallClccIndexMap = new HashMap<>(); + // A queue record the removal order of bluetooth calls private final Queue mBluetoothCallQueue = new ArrayDeque<>(); @@ -705,6 +708,19 @@ public class BluetoothInCallService extends InCallService { Log.d(TAG, "add inference call with reason: " + cause.getReason()); mBluetoothCallQueue.add(call.getId()); mBluetoothConferenceCallInference.put(call.getId(), call); + if (Flags.maintainCallIndexAfterConference()) { + // If the disconnect is due to call merge, store the index for future use. + if (cause.getReason() != null + && cause.getReason().equals("IMS_MERGED_SUCCESSFULLY")) { + if (!mConferenceCallClccIndexMap.containsKey(getClccMapKey(call))) { + if (call.mClccIndex > -1) { + mConferenceCallClccIndexMap.put( + getClccMapKey(call), call.mClccIndex); + } + } + } + } + // queue size limited to 2 because merge operation only happens on 2 calls // we are only interested in last 2 calls merged if (mBluetoothCallQueue.size() > 2) { @@ -723,6 +739,15 @@ public class BluetoothInCallService extends InCallService { updateHeadsetWithCallState(false /* force */); + if (Flags.maintainCallIndexAfterConference() && mConferenceCallClccIndexMap.size() > 0) { + int anyActiveCalls = mCallInfo.isNullCall(mCallInfo.getActiveCall()) ? 0 : 1; + int numHeldCalls = mCallInfo.getNumHeldCalls(); + // If no call is active or held clear the hashmap. + if (anyActiveCalls == 0 && numHeldCalls == 0) { + mConferenceCallClccIndexMap.clear(); + } + } + if (mBluetoothLeCallControl != null) { mBluetoothLeCallControl.onCallRemoved( call.getTbsCallId(), getTbsTerminationReason(call)); @@ -1073,6 +1098,23 @@ public class BluetoothInCallService extends InCallService { return availableIndex.first(); } + @VisibleForTesting + /* Function to extract and return call handle. */ + private String getClccMapKey(BluetoothCall call) { + if (mCallInfo.isNullCall(call) || call.getHandle() == null) { + return ""; + } + Uri handle = call.getHandle(); + String key; + if (call.hasProperty(Call.Details.PROPERTY_SELF_MANAGED)) { + key = handle.toString() + " self managed " + call.getId(); + } else { + key = handle.toString(); + } + Log.d(TAG, "getClccMapKey Key: " + key); + return key; + } + /** * Returns the caches index for the specified call. If no such index exists, then an index is * given (the smallest number starting from 1 that isn't already taken). @@ -1082,6 +1124,13 @@ public class BluetoothInCallService extends InCallService { Log.w(TAG, "empty or null call"); return -1; } + + // Check if the call handle is already stored. Return the previously stored index. + if (Flags.maintainCallIndexAfterConference() + && mConferenceCallClccIndexMap.containsKey(getClccMapKey(call))) { + call.mClccIndex = mConferenceCallClccIndexMap.get(getClccMapKey(call)); + } + if (call.mClccIndex >= 1) { return call.mClccIndex; } @@ -1094,6 +1143,13 @@ public class BluetoothInCallService extends InCallService { // NOTE: Indexes are removed in {@link #onCallRemoved}. call.mClccIndex = getNextAvailableClccIndex(index); + if (Flags.maintainCallIndexAfterConference()) { + // Remove the index from conference hashmap, this can be later added if call merges in + // conference + mConferenceCallClccIndexMap + .entrySet() + .removeIf(entry -> entry.getValue() == call.mClccIndex); + } Log.d(TAG, "call " + call.getId() + " CLCC index is " + call.mClccIndex); return call.mClccIndex; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java index 4d639e79bfd..e568fc7bace 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java @@ -28,6 +28,7 @@ import android.content.Intent; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.platform.test.flag.junit.SetFlagsRule; import android.telecom.BluetoothCallQualityReport; import android.telecom.Call; import android.telecom.Connection; @@ -44,6 +45,7 @@ import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; +import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hfp.BluetoothHeadsetProxy; import com.android.bluetooth.tbs.BluetoothLeCallControlProxy; @@ -92,6 +94,7 @@ public class BluetoothInCallServiceTest { private BluetoothInCallService mBluetoothInCallService; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private BluetoothHeadsetProxy mMockBluetoothHeadset; @Mock private BluetoothLeCallControlProxy mLeCallControl; @@ -978,6 +981,122 @@ public class BluetoothInCallServiceTest { anyInt()); } + @Test + public void conferenceLastCallIndexIsMaintained() throws Exception { + mSetFlagsRule.enableFlags(Flags.FLAG_MAINTAIN_CALL_INDEX_AFTER_CONFERENCE); + doReturn("").when(mMockTelephonyManager).getNetworkCountryIso(); + + List calls = new ArrayList<>(); + doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); + + // Call 1 active call is added + BluetoothCall activeCall_1 = createActiveCall(UUID.randomUUID()); + calls.add(activeCall_1); + mBluetoothInCallService.onCallAdded(activeCall_1); + + doReturn(Call.STATE_ACTIVE).when(activeCall_1).getState(); + doReturn(Uri.parse("tel:555-0001")).when(activeCall_1).getHandle(); + doReturn(new GatewayInfo(null, null, Uri.parse("tel:555-0001"))) + .when(activeCall_1) + .getGatewayInfo(); + + // Call 2 holding call is added + BluetoothCall activeCall_2 = createHeldCall(UUID.randomUUID()); + calls.add(activeCall_2); + mBluetoothInCallService.onCallAdded(activeCall_2); + + doReturn(Call.STATE_HOLDING).when(activeCall_2).getState(); + doReturn(true).when(activeCall_2).isIncoming(); + doReturn(Uri.parse("tel:555-0002")).when(activeCall_2).getHandle(); + doReturn(new GatewayInfo(null, null, Uri.parse("tel:555-0002"))) + .when(activeCall_2) + .getGatewayInfo(); + + // needs to have at least one CLCC response before merge to enable call inference + clearInvocations(mMockBluetoothHeadset); + mBluetoothInCallService.listCurrentCalls(); + verify(mMockBluetoothHeadset) + .clccResponse( + 1, 0, CALL_STATE_ACTIVE, 0, false, "5550001", PhoneNumberUtils.TOA_Unknown); + verify(mMockBluetoothHeadset) + .clccResponse( + 2, 1, CALL_STATE_HELD, 0, false, "5550002", PhoneNumberUtils.TOA_Unknown); + calls.clear(); + + // calls merged for conference call + DisconnectCause cause = + new DisconnectCause(DisconnectCause.OTHER, "IMS_MERGED_SUCCESSFULLY"); + doReturn(cause).when(activeCall_1).getDisconnectCause(); + doReturn(cause).when(activeCall_2).getDisconnectCause(); + mBluetoothInCallService.onCallRemoved(activeCall_1, true); + mBluetoothInCallService.onCallRemoved(activeCall_2, true); + + BluetoothCall conferenceCall = createActiveCall(UUID.randomUUID()); + addCallCapability(conferenceCall, Connection.CAPABILITY_MANAGE_CONFERENCE); + + doReturn(Uri.parse("tel:555-1234")).when(conferenceCall).getHandle(); + doReturn(true).when(conferenceCall).isConference(); + doReturn(Call.STATE_ACTIVE).when(conferenceCall).getState(); + doReturn(true).when(conferenceCall).hasProperty(Call.Details.PROPERTY_GENERIC_CONFERENCE); + doReturn(true).when(conferenceCall).isIncoming(); + doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); + + // parent call arrived, but children have not, then do inference on children + calls.add(conferenceCall); + Assert.assertEquals(calls.size(), 1); + mBluetoothInCallService.onCallAdded(conferenceCall); + + clearInvocations(mMockBluetoothHeadset); + mBluetoothInCallService.listCurrentCalls(); + verify(mMockBluetoothHeadset) + .clccResponse( + 1, 0, CALL_STATE_ACTIVE, 0, true, "5550001", PhoneNumberUtils.TOA_Unknown); + verify(mMockBluetoothHeadset) + .clccResponse( + 2, 1, CALL_STATE_ACTIVE, 0, true, "5550002", PhoneNumberUtils.TOA_Unknown); + + // real children arrive, no change on CLCC response + calls.add(activeCall_1); + mBluetoothInCallService.onCallAdded(activeCall_1); + doReturn(true).when(activeCall_1).isConference(); + calls.add(activeCall_2); + mBluetoothInCallService.onCallAdded(activeCall_2); + doReturn(Call.STATE_ACTIVE).when(activeCall_2).getState(); + doReturn(true).when(activeCall_2).isConference(); + doReturn(List.of(1, 2)).when(conferenceCall).getChildrenIds(); + + clearInvocations(mMockBluetoothHeadset); + mBluetoothInCallService.listCurrentCalls(); + verify(mMockBluetoothHeadset) + .clccResponse( + 1, 0, CALL_STATE_ACTIVE, 0, true, "5550001", PhoneNumberUtils.TOA_Unknown); + verify(mMockBluetoothHeadset) + .clccResponse( + 2, 1, CALL_STATE_ACTIVE, 0, true, "5550002", PhoneNumberUtils.TOA_Unknown); + + // Call 1 Disconnected and removed from conf + doReturn(Call.STATE_DISCONNECTED).when(activeCall_1).getState(); + cause = new DisconnectCause(DisconnectCause.OTHER); + doReturn(cause).when(activeCall_1).getDisconnectCause(); + mBluetoothInCallService.onCallRemoved(activeCall_1, true); + doReturn(false).when(activeCall_1).isConference(); + calls.remove(activeCall_1); + Assert.assertEquals(calls.size(), 2); + + // Call 2 removed from conf + doReturn(cause).when(activeCall_2).getDisconnectCause(); + mBluetoothInCallService.onCallRemoved(activeCall_2, true); + doReturn(false).when(activeCall_2).isConference(); + + clearInvocations(mMockBluetoothHeadset); + mBluetoothInCallService.listCurrentCalls(); + + // Index 2 is retained + verify(mMockBluetoothHeadset) + .clccResponse( + 2, 1, CALL_STATE_ACTIVE, 0, false, "5550002", PhoneNumberUtils.TOA_Unknown); + } + @Test public void queryPhoneState() { BluetoothCall ringingCall = createRingingCall(UUID.randomUUID()); -- GitLab From 15a9026a58eb6c3ab80824749215b1edc01122da Mon Sep 17 00:00:00 2001 From: Kihong Seong Date: Tue, 30 Jul 2024 12:53:36 +0000 Subject: [PATCH 022/875] Remove flag enumerate_gatt_errors Bug: 320574336 Test: m com.android.btservices Flag: EXEMPT, flag removal only Change-Id: I75d7afd1b227b25c18907cc4852c1bb61e97a40f --- flags/gap.aconfig | 8 -------- framework/api/current.txt | 2 +- framework/java/android/bluetooth/BluetoothGatt.java | 2 -- .../bumble/src/android/bluetooth/GattClientTest.java | 1 - system/bta/gatt/bta_gattc_act.cc | 3 +-- system/stack/gatt/gatt_main.cc | 6 +----- system/stack/test/gatt/stack_gatt_test.cc | 3 +-- 7 files changed, 4 insertions(+), 21 deletions(-) diff --git a/flags/gap.aconfig b/flags/gap.aconfig index f6da6494243..96749aaede3 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -36,14 +36,6 @@ flag { bug: "320402249" } -flag { - name: "enumerate_gatt_errors" - is_exported: true - namespace: "bluetooth" - description: "Enumerate GATT error situations" - bug: "320574336" -} - flag { name: "gatt_fix_device_busy" namespace: "bluetooth" diff --git a/framework/api/current.txt b/framework/api/current.txt index 29d8ef989df..c92d72252c4 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -627,7 +627,7 @@ package android.bluetooth { field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1 field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2 field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f - field @FlaggedApi("com.android.bluetooth.flags.enumerate_gatt_errors") public static final int GATT_CONNECTION_TIMEOUT = 147; // 0x93 + field public static final int GATT_CONNECTION_TIMEOUT = 147; // 0x93 field public static final int GATT_FAILURE = 257; // 0x101 field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5 field public static final int GATT_INSUFFICIENT_AUTHORIZATION = 8; // 0x8 diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java index f2f15735c3c..92d058207f6 100644 --- a/framework/java/android/bluetooth/BluetoothGatt.java +++ b/framework/java/android/bluetooth/BluetoothGatt.java @@ -18,7 +18,6 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; -import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresNoPermission; @@ -132,7 +131,6 @@ public final class BluetoothGatt implements BluetoothProfile { * GATT connection timed out, likely due to the remote device being out of range or not * advertising as connectable. */ - @FlaggedApi(Flags.FLAG_ENUMERATE_GATT_ERRORS) public static final int GATT_CONNECTION_TIMEOUT = 0x93; /** A GATT operation failed, errors other than the above */ diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java index 77af379148d..fb2585ba1da 100644 --- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java +++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java @@ -286,7 +286,6 @@ public class GattClientTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_ENUMERATE_GATT_ERRORS) public void connectTimeout() { BluetoothDevice device = mAdapter.getRemoteLeDevice( diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index 0590d973384..7309ae6a6fb 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -417,8 +417,7 @@ void bta_gattc_open_error(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* /* p_d } void bta_gattc_open_fail(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { - if (com::android::bluetooth::flags::enumerate_gatt_errors() && - p_data->int_conn.reason == GATT_CONN_TIMEOUT) { + if (p_data->int_conn.reason == GATT_CONN_TIMEOUT) { log::warn( "Connection timed out after 30 seconds. conn_id=0x{:x}. Return " "GATT_CONNECTION_TIMEOUT({})", diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index d8c5a1c75ac..4cc8c2d3368 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -493,11 +493,7 @@ bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr, tBT_TRANSPORT namespace connection_manager { void on_connection_timed_out(uint8_t /* app_id */, const RawAddress& address) { - if (com::android::bluetooth::flags::enumerate_gatt_errors()) { - gatt_le_connect_cback(L2CAP_ATT_CID, address, false, 0x08, BT_TRANSPORT_LE); - } else { - gatt_le_connect_cback(L2CAP_ATT_CID, address, false, 0xff, BT_TRANSPORT_LE); - } + gatt_le_connect_cback(L2CAP_ATT_CID, address, false, 0x08, BT_TRANSPORT_LE); } } // namespace connection_manager diff --git a/system/stack/test/gatt/stack_gatt_test.cc b/system/stack/test/gatt/stack_gatt_test.cc index 3ae3ea11698..dd730be8ab9 100644 --- a/system/stack/test/gatt/stack_gatt_test.cc +++ b/system/stack/test/gatt/stack_gatt_test.cc @@ -164,8 +164,7 @@ TEST_F(StackGattTest, GATT_Register_Deregister) { gatt_free(); } -TEST_F_WITH_FLAGS(StackGattTest, gatt_status_text, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, enumerate_gatt_errors))) { +TEST_F(StackGattTest, gatt_status_text) { std::vector> statuses = { std::make_pair(GATT_SUCCESS, "GATT_SUCCESS"), // Also GATT_ENCRYPED_MITM std::make_pair(GATT_INVALID_HANDLE, "GATT_INVALID_HANDLE"), -- GitLab From e88d7925d843d1c116238523b32d90613bee0b64 Mon Sep 17 00:00:00 2001 From: WhaleChang Date: Mon, 23 Sep 2024 19:57:42 +0800 Subject: [PATCH 023/875] Disable SWB for desktop if bluetooth.hfp.swb.supported=false Adds a property to control whether SWB is supported over Bluetooth. Bug: 368211009 Test: atest bluetooth_test_gd Test: SWB is not enabled if bluetooth.hfp.swb.supported=false Flag: EXEMPT desktop only Change-Id: I0f1cd81d445b11934a5c566ecf55893fc349fe6f --- system/stack/btm/btm_sco_hfp_hal_linux.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/stack/btm/btm_sco_hfp_hal_linux.cc b/system/stack/btm/btm_sco_hfp_hal_linux.cc index 96bb4ded371..1488b6899eb 100644 --- a/system/stack/btm/btm_sco_hfp_hal_linux.cc +++ b/system/stack/btm/btm_sco_hfp_hal_linux.cc @@ -324,8 +324,13 @@ bool get_wbs_supported() { // Check if super-wideband speech is supported on local device bool get_swb_supported() { +#ifdef TARGET_FLOSS // We only support SWB via transparent mode. return is_coding_format_supported(ESCO_CODING_FORMAT_TRANSPNT); +#else + return is_coding_format_supported(ESCO_CODING_FORMAT_TRANSPNT) && + osi_property_get_bool("bluetooth.hfp.swb.supported", true); // TODO: add SWB for desktop +#endif } // Checks the supported codecs -- GitLab From 71558ba487968ad83ec59d2461c48126b003c1dd Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 17 Sep 2024 12:59:47 +0000 Subject: [PATCH 024/875] bta_ag_sco: add mock files and funcs for tests This prepares the mock files for the next CL. Bug: 349290628 Test: m com.google.android.btservices Flag: EXEMPT, test-only Change-Id: I17e1d4c8194471bcac7fca8ca761cfcdf9ce49ff --- .../hfp_client_interface_host.cc | 3 + system/bta/ag/bta_ag_sco.cc | 2 +- system/test/mock/mock_bta_ag_sco.cc | 187 +++++++++++ system/test/mock/mock_bta_ag_sco.h | 312 ++++++++++++++++++ 4 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 system/test/mock/mock_bta_ag_sco.cc create mode 100644 system/test/mock/mock_bta_ag_sco.h diff --git a/system/audio_hal_interface/hfp_client_interface_host.cc b/system/audio_hal_interface/hfp_client_interface_host.cc index d4ef2576bff..c48822065d6 100644 --- a/system/audio_hal_interface/hfp_client_interface_host.cc +++ b/system/audio_hal_interface/hfp_client_interface_host.cc @@ -48,6 +48,9 @@ HfpClientInterface::Offload::GetHfpScoConfig() { return std::unordered_map(); } +size_t HfpClientInterface::Encode::Read(uint8_t* p_buf, uint32_t len) { return 0; } + +size_t HfpClientInterface::Decode::Write(const uint8_t* p_buf, uint32_t len) { return 0; } } // namespace hfp } // namespace audio } // namespace bluetooth diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index 4a7369fca38..4c6e06e8a7f 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -30,7 +30,7 @@ #include "audio_hal_interface/hfp_client_interface.h" #include "bta/ag/bta_ag_int.h" -#include "bta_ag_swb_aptx.h" +#include "bta/include/bta_ag_swb_aptx.h" #include "btm_status.h" #include "hci/controller_interface.h" #include "internal_include/bt_target.h" diff --git a/system/test/mock/mock_bta_ag_sco.cc b/system/test/mock/mock_bta_ag_sco.cc new file mode 100644 index 00000000000..09da576c348 --- /dev/null +++ b/system/test/mock/mock_bta_ag_sco.cc @@ -0,0 +1,187 @@ +/* + * Copyright 2023 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:24 + * + * mockcify.pl ver 0.7.1 + */ + +// Mock include file to share data between tests and mock +#include "test/mock/mock_bta_ag_sco.h" + +#include + +#include "test/common/mock_functions.h" + +// Original usings +using HfpInterface = bluetooth::audio::hfp::HfpClientInterface; +using namespace bluetooth; + +// Mocked internal structures, if any + +namespace test { +namespace mock { +namespace bta_ag_sco { + +// Function state capture and return values, if needed +struct bta_ag_api_set_active_device bta_ag_api_set_active_device; +struct bta_ag_codec_negotiate bta_ag_codec_negotiate; +struct bta_ag_create_sco bta_ag_create_sco; +struct bta_ag_get_active_device bta_ag_get_active_device; +struct bta_ag_get_sco_offload_enabled bta_ag_get_sco_offload_enabled; +struct bta_ag_is_sco_managed_by_audio bta_ag_is_sco_managed_by_audio; +struct bta_ag_sco_close bta_ag_sco_close; +struct bta_ag_sco_codec_nego bta_ag_sco_codec_nego; +struct bta_ag_sco_conn_close bta_ag_sco_conn_close; +struct bta_ag_sco_conn_open bta_ag_sco_conn_open; +struct bta_ag_sco_conn_rsp bta_ag_sco_conn_rsp; +struct bta_ag_sco_is_active_device bta_ag_sco_is_active_device; +struct bta_ag_sco_is_open bta_ag_sco_is_open; +struct bta_ag_sco_is_opening bta_ag_sco_is_opening; +struct bta_ag_sco_listen bta_ag_sco_listen; +struct bta_ag_sco_open bta_ag_sco_open; +struct bta_ag_sco_read bta_ag_sco_read; +struct bta_ag_sco_shutdown bta_ag_sco_shutdown; +struct bta_ag_sco_write bta_ag_sco_write; +struct bta_ag_set_sco_allowed bta_ag_set_sco_allowed; +struct bta_ag_set_sco_offload_enabled bta_ag_set_sco_offload_enabled; +struct bta_ag_stream_suspended bta_ag_stream_suspended; +struct bta_clear_active_device bta_clear_active_device; +struct updateCodecParametersFromProviderInfo updateCodecParametersFromProviderInfo; + +} // namespace bta_ag_sco +} // namespace mock +} // namespace test + +// Mocked function return values, if any +namespace test { +namespace mock { +namespace bta_ag_sco { + +const RawAddress& bta_ag_get_active_device::return_value = RawAddress::kEmpty; +bool bta_ag_get_sco_offload_enabled::return_value = false; +bool bta_ag_is_sco_managed_by_audio::return_value = false; +bool bta_ag_sco_is_active_device::return_value = false; +bool bta_ag_sco_is_open::return_value = false; +bool bta_ag_sco_is_opening::return_value = false; +size_t bta_ag_sco_read::return_value = 0; +size_t bta_ag_sco_write::return_value = 0; + +} // namespace bta_ag_sco +} // namespace mock +} // namespace test + +// Mocked functions, if any +void bta_ag_api_set_active_device(const RawAddress& new_active_device) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_api_set_active_device(new_active_device); +} +void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_codec_negotiate(p_scb); +} +void bta_ag_create_sco(tBTA_AG_SCB* p_scb, bool is_orig) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_create_sco(p_scb, is_orig); +} +const RawAddress& bta_ag_get_active_device() { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_get_active_device(); +} +bool bta_ag_get_sco_offload_enabled() { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_get_sco_offload_enabled(); +} +bool bta_ag_is_sco_managed_by_audio() { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_is_sco_managed_by_audio(); +} +void bta_ag_sco_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_close(p_scb, data); +} +void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_codec_nego(p_scb, result); +} +void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_conn_close(p_scb, data); +} +void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_conn_open(p_scb, data); +} +void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA* p_data) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_conn_rsp(p_scb, p_data); +} +bool bta_ag_sco_is_active_device(const RawAddress& bd_addr) { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_sco_is_active_device(bd_addr); +} +bool bta_ag_sco_is_open(tBTA_AG_SCB* p_scb) { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_sco_is_open(p_scb); +} +bool bta_ag_sco_is_opening(tBTA_AG_SCB* p_scb) { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_sco_is_opening(p_scb); +} +void bta_ag_sco_listen(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_listen(p_scb, data); +} +void bta_ag_sco_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_open(p_scb, data); +} +size_t bta_ag_sco_read(uint8_t* p_buf, uint32_t len) { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_sco_read(p_buf, len); +} +void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_sco_shutdown(p_scb, data); +} +size_t bta_ag_sco_write(const uint8_t* p_buf, uint32_t len) { + inc_func_call_count(__func__); + return test::mock::bta_ag_sco::bta_ag_sco_write(p_buf, len); +} +void bta_ag_set_sco_allowed(bool value) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_set_sco_allowed(value); +} +void bta_ag_set_sco_offload_enabled(bool value) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_set_sco_offload_enabled(value); +} +void bta_ag_stream_suspended() { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_ag_stream_suspended(); +} +void bta_clear_active_device() { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::bta_clear_active_device(); +} +void updateCodecParametersFromProviderInfo(tBTA_AG_UUID_CODEC esco_codec, + enh_esco_params_t& params) { + inc_func_call_count(__func__); + test::mock::bta_ag_sco::updateCodecParametersFromProviderInfo(esco_codec, params); +} +// Mocked functions complete +// END mockcify generation diff --git a/system/test/mock/mock_bta_ag_sco.h b/system/test/mock/mock_bta_ag_sco.h new file mode 100644 index 00000000000..11f40a758a3 --- /dev/null +++ b/system/test/mock/mock_bta_ag_sco.h @@ -0,0 +1,312 @@ +/* + * Copyright 2023 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 + +/* + * Generated mock file from original source file + * Functions generated:24 + * + * mockcify.pl ver 0.7.1 + */ + +#include +#include + +// Original included files, if any +// NOTE: Since this is a mock file with mock definitions some number of +// include files may not be required. The include-what-you-use +// still applies, but crafting proper inclusion is out of scope +// for this effort. This compilation unit may compile as-is, or +// may need attention to prune from (or add to ) the inclusion set. +#include +#include + +#include + +#include "audio_hal_interface/hfp_client_interface.h" +#include "bta/ag/bta_ag_int.h" +#include "bta/include/bta_ag_swb_aptx.h" +#include "btm_status.h" +#include "hci/controller_interface.h" +#include "internal_include/bt_target.h" +#include "main/shim/entry.h" +#include "osi/include/properties.h" +#include "stack/btm/btm_int_types.h" +#include "stack/btm/btm_sco.h" +#include "stack/btm/btm_sco_hfp_hal.h" +#include "stack/include/btm_client_interface.h" +#include "stack/include/btm_status.h" +#include "stack/include/main_thread.h" +#include "types/raw_address.h" + +// Original usings +using HfpInterface = bluetooth::audio::hfp::HfpClientInterface; +using namespace bluetooth; + +// Mocked compile conditionals, if any + +namespace test { +namespace mock { +namespace bta_ag_sco { + +// Shared state between mocked functions and tests +// Name: bta_ag_api_set_active_device +// Params: const RawAddress& new_active_device +// Return: void +struct bta_ag_api_set_active_device { + std::function body{ + [](const RawAddress& /* new_active_device */) {}}; + void operator()(const RawAddress& new_active_device) { body(new_active_device); } +}; +extern struct bta_ag_api_set_active_device bta_ag_api_set_active_device; + +// Name: bta_ag_codec_negotiate +// Params: tBTA_AG_SCB* p_scb +// Return: void +struct bta_ag_codec_negotiate { + std::function body{[](tBTA_AG_SCB* /* p_scb */) {}}; + void operator()(tBTA_AG_SCB* p_scb) { body(p_scb); } +}; +extern struct bta_ag_codec_negotiate bta_ag_codec_negotiate; + +// Name: bta_ag_create_sco +// Params: tBTA_AG_SCB* p_scb, bool is_orig +// Return: void +struct bta_ag_create_sco { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, bool /* is_orig */) {}}; + void operator()(tBTA_AG_SCB* p_scb, bool is_orig) { body(p_scb, is_orig); } +}; +extern struct bta_ag_create_sco bta_ag_create_sco; + +// Name: bta_ag_get_active_device +// Params: +// Return: const RawAddress& +struct bta_ag_get_active_device { + static const RawAddress& return_value; + std::function body{[]() { return return_value; }}; + const RawAddress& operator()() { return body(); } +}; +extern struct bta_ag_get_active_device bta_ag_get_active_device; + +// Name: bta_ag_get_sco_offload_enabled +// Params: +// Return: bool +struct bta_ag_get_sco_offload_enabled { + static bool return_value; + std::function body{[]() { return return_value; }}; + bool operator()() { return body(); } +}; +extern struct bta_ag_get_sco_offload_enabled bta_ag_get_sco_offload_enabled; + +// Name: bta_ag_is_sco_managed_by_audio +// Params: +// Return: bool +struct bta_ag_is_sco_managed_by_audio { + static bool return_value; + std::function body{[]() { return return_value; }}; + bool operator()() { return body(); } +}; +extern struct bta_ag_is_sco_managed_by_audio bta_ag_is_sco_managed_by_audio; + +// Name: bta_ag_sco_close +// Params: tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& +// Return: void +struct bta_ag_sco_close { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, const tBTA_AG_DATA& /* data */) {}}; + void operator()(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { body(p_scb, data); } +}; +extern struct bta_ag_sco_close bta_ag_sco_close; + +// Name: bta_ag_sco_codec_nego +// Params: tBTA_AG_SCB* p_scb, bool result +// Return: void +struct bta_ag_sco_codec_nego { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, bool /* result */) {}}; + void operator()(tBTA_AG_SCB* p_scb, bool result) { body(p_scb, result); } +}; +extern struct bta_ag_sco_codec_nego bta_ag_sco_codec_nego; + +// Name: bta_ag_sco_conn_close +// Params: tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& +// Return: void +struct bta_ag_sco_conn_close { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, const tBTA_AG_DATA& /* data */) {}}; + void operator()(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { body(p_scb, data); } +}; +extern struct bta_ag_sco_conn_close bta_ag_sco_conn_close; + +// Name: bta_ag_sco_conn_open +// Params: tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& +// Return: void +struct bta_ag_sco_conn_open { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, const tBTA_AG_DATA& /* data */) {}}; + void operator()(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { body(p_scb, data); } +}; +extern struct bta_ag_sco_conn_open bta_ag_sco_conn_open; + +// Name: bta_ag_sco_conn_rsp +// Params: tBTA_AG_SCB* p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA* p_data +// Return: void +struct bta_ag_sco_conn_rsp { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, tBTM_ESCO_CONN_REQ_EVT_DATA* /* p_data */) {}}; + void operator()(tBTA_AG_SCB* p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA* p_data) { body(p_scb, p_data); } +}; +extern struct bta_ag_sco_conn_rsp bta_ag_sco_conn_rsp; + +// Name: bta_ag_sco_is_active_device +// Params: const RawAddress& bd_addr +// Return: bool +struct bta_ag_sco_is_active_device { + static bool return_value; + std::function body{ + [](const RawAddress& /* bd_addr */) { return return_value; }}; + bool operator()(const RawAddress& bd_addr) { return body(bd_addr); } +}; +extern struct bta_ag_sco_is_active_device bta_ag_sco_is_active_device; + +// Name: bta_ag_sco_is_open +// Params: tBTA_AG_SCB* p_scb +// Return: bool +struct bta_ag_sco_is_open { + static bool return_value; + std::function body{ + [](tBTA_AG_SCB* /* p_scb */) { return return_value; }}; + bool operator()(tBTA_AG_SCB* p_scb) { return body(p_scb); } +}; +extern struct bta_ag_sco_is_open bta_ag_sco_is_open; + +// Name: bta_ag_sco_is_opening +// Params: tBTA_AG_SCB* p_scb +// Return: bool +struct bta_ag_sco_is_opening { + static bool return_value; + std::function body{ + [](tBTA_AG_SCB* /* p_scb */) { return return_value; }}; + bool operator()(tBTA_AG_SCB* p_scb) { return body(p_scb); } +}; +extern struct bta_ag_sco_is_opening bta_ag_sco_is_opening; + +// Name: bta_ag_sco_listen +// Params: tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& +// Return: void +struct bta_ag_sco_listen { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, const tBTA_AG_DATA& /* data */) {}}; + void operator()(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { body(p_scb, data); } +}; +extern struct bta_ag_sco_listen bta_ag_sco_listen; + +// Name: bta_ag_sco_open +// Params: tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data +// Return: void +struct bta_ag_sco_open { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, const tBTA_AG_DATA& /* data */) {}}; + void operator()(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { body(p_scb, data); } +}; +extern struct bta_ag_sco_open bta_ag_sco_open; + +// Name: bta_ag_sco_read +// Params: uint8_t* p_buf, uint32_t len +// Return: size_t +struct bta_ag_sco_read { + static size_t return_value; + std::function body{ + [](uint8_t* /* p_buf */, uint32_t /* len */) { return return_value; }}; + size_t operator()(uint8_t* p_buf, uint32_t len) { return body(p_buf, len); } +}; +extern struct bta_ag_sco_read bta_ag_sco_read; + +// Name: bta_ag_sco_shutdown +// Params: tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& +// Return: void +struct bta_ag_sco_shutdown { + std::function body{ + [](tBTA_AG_SCB* /* p_scb */, const tBTA_AG_DATA& /* data */) {}}; + void operator()(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { body(p_scb, data); } +}; +extern struct bta_ag_sco_shutdown bta_ag_sco_shutdown; + +// Name: bta_ag_sco_write +// Params: const uint8_t* p_buf, uint32_t len +// Return: size_t +struct bta_ag_sco_write { + static size_t return_value; + std::function body{ + [](const uint8_t* /* p_buf */, uint32_t /* len */) { return return_value; }}; + size_t operator()(const uint8_t* p_buf, uint32_t len) { return body(p_buf, len); } +}; +extern struct bta_ag_sco_write bta_ag_sco_write; + +// Name: bta_ag_set_sco_allowed +// Params: bool value +// Return: void +struct bta_ag_set_sco_allowed { + std::function body{[](bool /* value */) {}}; + void operator()(bool value) { body(value); } +}; +extern struct bta_ag_set_sco_allowed bta_ag_set_sco_allowed; + +// Name: bta_ag_set_sco_offload_enabled +// Params: bool value +// Return: void +struct bta_ag_set_sco_offload_enabled { + std::function body{[](bool /* value */) {}}; + void operator()(bool value) { body(value); } +}; +extern struct bta_ag_set_sco_offload_enabled bta_ag_set_sco_offload_enabled; + +// Name: bta_ag_stream_suspended +// Params: +// Return: void +struct bta_ag_stream_suspended { + std::function body{[]() {}}; + void operator()() { body(); } +}; +extern struct bta_ag_stream_suspended bta_ag_stream_suspended; + +// Name: bta_clear_active_device +// Params: +// Return: void +struct bta_clear_active_device { + std::function body{[]() {}}; + void operator()() { body(); } +}; +extern struct bta_clear_active_device bta_clear_active_device; + +// Name: updateCodecParametersFromProviderInfo +// Params: tBTA_AG_UUID_CODEC esco_codec, enh_esco_params_t& params +// Return: void +struct updateCodecParametersFromProviderInfo { + std::function body{ + [](tBTA_AG_UUID_CODEC /* esco_codec */, enh_esco_params_t& /* params */) {}}; + void operator()(tBTA_AG_UUID_CODEC esco_codec, enh_esco_params_t& params) { + body(esco_codec, params); + } +}; +extern struct updateCodecParametersFromProviderInfo updateCodecParametersFromProviderInfo; + +} // namespace bta_ag_sco +} // namespace mock +} // namespace test + +// END mockcify generation -- GitLab From e07ce4f2d46e992b73ad45a2235555934f1d86f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 24 Sep 2024 13:29:13 +0000 Subject: [PATCH 025/875] leaudio: Minor cleanup Avoid this warinig system/bta/le_audio/state_machine.cc:137: You seem to be initializing a member variable with itself. [runtime/init] [4] Bug: 331775328 Flag: Exempt, mechanical change. Test: atest bluetooth_le_audio_test Change-Id: Ic0dffd527b796cb9fda02f6b5c59a035dc547f62 --- system/bta/le_audio/client.cc | 8 ++++---- system/bta/le_audio/state_machine.cc | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 8a935434cb8..e958b6e5159 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -233,11 +233,11 @@ public: alarm_free(suspend_timeout_); } - LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks* callbacks_, - LeAudioGroupStateMachine::Callbacks* state_machine_callbacks_, + LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks* callbacks, + LeAudioGroupStateMachine::Callbacks* state_machine_callbacks, base::Closure initCb) : gatt_if_(0), - callbacks_(callbacks_), + callbacks_(callbacks), active_group_id_(bluetooth::groups::kGroupUnknown), configuration_context_type_(LeAudioContextType::UNINITIALIZED), in_call_metadata_context_types_({.sink = AudioContexts(), .source = AudioContexts()}), @@ -256,7 +256,7 @@ public: close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")), suspend_timeout_(alarm_new("LeAudioSuspendTimeout")), disable_timer_(alarm_new("LeAudioDisableTimer")) { - LeAudioGroupStateMachine::Initialize(state_machine_callbacks_); + LeAudioGroupStateMachine::Initialize(state_machine_callbacks); groupStateMachine_ = LeAudioGroupStateMachine::Get(); log::info("Reconnection mode: TARGETED_ANNOUNCEMENTS"); diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 280adb5db24..62eae8dc3d7 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -133,8 +133,8 @@ LeAudioGroupStateMachineImpl* instance; class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { public: - LeAudioGroupStateMachineImpl(Callbacks* state_machine_callbacks_) - : state_machine_callbacks_(state_machine_callbacks_), + LeAudioGroupStateMachineImpl(Callbacks* state_machine_callbacks) + : state_machine_callbacks_(state_machine_callbacks), watchdog_(alarm_new("LeAudioStateMachineTimer")) { log_history_ = LeAudioLogHistory::Get(); } -- GitLab From a1b76d5aec8d95a6452e9d6aead561a7ed4abf29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 24 Sep 2024 09:14:11 +0000 Subject: [PATCH 026/875] leaudio: Minor cleanups around state machine mocks Couple of things * Logging * Proper state handling Bug: 331775328 Test: atest bluetooth_le_audio_client_test Flag: TEST_ONLY Change-Id: I7e5c6e3d3372b979741653ddc74fac1dcfd7ab38 --- system/bta/le_audio/le_audio_client_test.cc | 260 ++++++++++---------- 1 file changed, 134 insertions(+), 126 deletions(-) diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 9f06ea6032b..ebda915932b 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -37,7 +37,6 @@ #include "common/message_loop_thread.h" #include "fake_osi.h" #include "gatt/database_builder.h" -#include "gmock/gmock.h" #include "hardware/bt_gatt_types.h" #include "hardware/bt_le_audio.h" #include "hci/controller_interface_mock.h" @@ -850,74 +849,83 @@ protected: .WillByDefault(SaveArg<0>(&state_machine_callbacks_)); ON_CALL(mock_state_machine_, ConfigureStream(_, _, _, _)) - .WillByDefault( - [this](LeAudioDeviceGroup* group, types::LeAudioContextType context_type, - types::BidirectionalPair metadata_context_types, - types::BidirectionalPair> ccid_lists) { - bool isReconfiguration = group->IsPendingConfiguration(); - - /* This shall be called only for user reconfiguration */ - if (!isReconfiguration) { - return false; - } + .WillByDefault([this](LeAudioDeviceGroup* group, types::LeAudioContextType context_type, + types::BidirectionalPair + metadata_context_types, + types::BidirectionalPair> ccid_lists) { + bool isReconfiguration = group->IsPendingConfiguration(); - /* Do what ReleaseCisIds(group) does: start */ - LeAudioDevice* leAudioDevice = group->GetFirstDevice(); - while (leAudioDevice != nullptr) { - for (auto& ase : leAudioDevice->ases_) { - ase.cis_id = bluetooth::le_audio::kInvalidCisId; - } - leAudioDevice = group->GetNextDevice(leAudioDevice); - } - group->ClearAllCises(); - /* end */ + log::info("ConfigureStream: group_id {}, context_type {} isReconfiguration {}", + group->group_id_, bluetooth::common::ToString(context_type), + isReconfiguration); - if (!group->Configure(context_type, metadata_context_types, ccid_lists)) { - log::error("Could not configure ASEs for group {} content type {}", - group->group_id_, int(context_type)); + /* Do what ReleaseCisIds(group) does: start */ + LeAudioDevice* leAudioDevice = group->GetFirstDevice(); + while (leAudioDevice != nullptr) { + for (auto& ase : leAudioDevice->ases_) { + ase.cis_id = bluetooth::le_audio::kInvalidCisId; + } + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + group->ClearAllCises(); + /* end */ - return false; - } + if (!group->Configure(context_type, metadata_context_types, ccid_lists)) { + log::error("ConfigureStream: Could not configure ASEs for group {} content type {}", + group->group_id_, int(context_type)); + + return false; + } - group->cig.GenerateCisIds(context_type); + group->cig.GenerateCisIds(context_type); - for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr; - device = group->GetNextDevice(device)) { - if (!group->cig.AssignCisIds(device)) { - continue; - } + types::AseState config_state = + types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; - if (group->cig.GetState() == types::CigState::CREATED) { - group->AssignCisConnHandlesToAses(device); - } + for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr; + device = group->GetNextDevice(device)) { + if (!group->cig.AssignCisIds(device)) { + continue; + } - for (auto& ase : device->ases_) { - ase.cis_state = types::CisState::IDLE; - ase.data_path_state = types::DataPathState::IDLE; - ase.active = false; - ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; - } - } + if (group->cig.GetState() == types::CigState::CREATED) { + group->AssignCisConnHandlesToAses(device); + } - // Inject the state - group->SetTargetState( - types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); - group->SetState(group->GetTargetState()); - group->ClearPendingConfiguration(); - do_in_main_thread(base::BindOnce( - [](int group_id, - bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* - state_machine_callbacks) { - state_machine_callbacks->StatusReportCb( - group_id, GroupStreamStatus::CONFIGURED_BY_USER); - }, - group->group_id_, base::Unretained(this->state_machine_callbacks_))); - return true; - }); + for (auto& ase : device->ases_) { + if (!ase.active) { + continue; + } + + ase.cis_state = types::CisState::IDLE; + ase.data_path_state = types::DataPathState::IDLE; + ase.state = config_state; + } + } + + // Inject the state + group->SetTargetState(config_state); + group->SetState(group->GetTargetState()); + group->ClearPendingConfiguration(); + do_in_main_thread(base::BindOnce( + [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* + state_machine_callbacks) { + state_machine_callbacks->StatusReportCb( + group_id, GroupStreamStatus::CONFIGURED_BY_USER); + }, + group->group_id_, base::Unretained(this->state_machine_callbacks_))); + return true; + }); ON_CALL(mock_state_machine_, AttachToStream(_, _, _)) .WillByDefault([this](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice, types::BidirectionalPair> ccids) { + log::info( + "AttachToStream: group_id {}, address {}, current_state {}, target_state {}", + group->group_id_, leAudioDevice->address_, + bluetooth::common::ToString(group->GetState()), + bluetooth::common::ToString(group->GetTargetState())); + if (group->GetState() != types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { if (group->GetTargetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { attach_to_stream_scheduled = true; @@ -964,7 +972,8 @@ protected: stream_conf->stream_params.source.num_of_channels += ase.channel_count; log::info( - "Added Source Stream Configuration. CIS Connection Handle: " + "AttachToStream: Added Source Stream Configuration. CIS Connection " + "Handle: " "{}, Audio Channel Allocation: {}, Source Number Of " "Devices: {}, Source Number Of Channels: {}", ase.cis_conn_hdl, *core_config.audio_channel_allocation, @@ -985,7 +994,8 @@ protected: stream_conf->stream_params.sink.num_of_channels += ase.channel_count; log::info( - "Added Sink Stream Configuration. CIS Connection Handle: " + "AttachToStream: Added Sink Stream Configuration. CIS Connection " + "Handle: " "{}, Audio Channel Allocation: {}, Sink Number Of Devices: " "{}, Sink Number Of Channels: {}", ase.cis_conn_hdl, *core_config.audio_channel_allocation, @@ -1004,7 +1014,7 @@ protected: metadata_context_types, types::BidirectionalPair> ccid_lists) { auto group_state = group->GetState(); - log::info("group {} state {}, context type {}", group->group_id_, + log::info("StartStream: group {} state {}, context type {}", group->group_id_, bluetooth::common::ToString(group_state), bluetooth::common::ToString(context_type)); @@ -1015,37 +1025,42 @@ protected: return true; } - /* Do what ReleaseCisIds(group) does: start */ - LeAudioDevice* leAudioDevice = group->GetFirstDevice(); - while (leAudioDevice != nullptr) { - for (auto& ase : leAudioDevice->ases_) { - ase.cis_id = bluetooth::le_audio::kInvalidCisId; + // Inject the state + group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + + if (group_state != types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { + /* Do what ReleaseCisIds(group) does: start */ + LeAudioDevice* leAudioDevice = group->GetFirstDevice(); + while (leAudioDevice != nullptr) { + for (auto& ase : leAudioDevice->ases_) { + ase.cis_id = bluetooth::le_audio::kInvalidCisId; + } + leAudioDevice = group->GetNextDevice(leAudioDevice); } - leAudioDevice = group->GetNextDevice(leAudioDevice); - } - group->ClearAllCises(); - /* end */ + group->ClearAllCises(); + /* end */ - if (!group->Configure(context_type, metadata_context_types, ccid_lists)) { - log::error("failed to set ASE configuration"); - return false; - } + if (!group->Configure(context_type, metadata_context_types, ccid_lists)) { + log::error("StartStream: failed to set ASE configuration"); + return false; + } - if (group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE || - group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) { - group->cig.GenerateCisIds(context_type); + if (group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE || + group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) { + group->cig.GenerateCisIds(context_type); - std::vector conn_handles; - for (uint8_t i = 0; i < (uint8_t)(group->cig.cises.size()); i++) { - conn_handles.push_back(iso_con_counter_++); - } - group->cig.AssignCisConnHandles(conn_handles); - for (LeAudioDevice* device = group->GetFirstActiveDevice(); device != nullptr; - device = group->GetNextActiveDevice(device)) { - if (!group->cig.AssignCisIds(device)) { - return false; + std::vector conn_handles; + for (uint8_t i = 0; i < (uint8_t)(group->cig.cises.size()); i++) { + conn_handles.push_back(iso_con_counter_++); + } + group->cig.AssignCisConnHandles(conn_handles); + for (LeAudioDevice* device = group->GetFirstActiveDevice(); device != nullptr; + device = group->GetNextActiveDevice(device)) { + if (!group->cig.AssignCisIds(device)) { + return false; + } + group->AssignCisConnHandlesToAses(device); } - group->AssignCisConnHandlesToAses(device); } } @@ -1095,7 +1110,7 @@ protected: } else { log::assert_that(stream_conf->stream_params.source.sample_frequency_hz == core_config.GetSamplingFrequencyHz(), - "sample freq mismatch: {}!={}", + "StartStream: sample freq mismatch: {}!={}", stream_conf->stream_params.source.sample_frequency_hz, core_config.GetSamplingFrequencyHz()); } @@ -1106,7 +1121,7 @@ protected: } else { log::assert_that(stream_conf->stream_params.source.octets_per_codec_frame == *core_config.octets_per_codec_frame, - "octets per frame mismatch: {}!={}", + "StartStream: octets per frame mismatch: {}!={}", stream_conf->stream_params.source.octets_per_codec_frame, *core_config.octets_per_codec_frame); } @@ -1120,13 +1135,13 @@ protected: log::assert_that( stream_conf->stream_params.source.codec_frames_blocks_per_sdu == *core_config.codec_frames_blocks_per_sdu, - "codec_frames_blocks_per_sdu: {}!={}", + "StartStream: codec_frames_blocks_per_sdu: {}!={}", stream_conf->stream_params.source.codec_frames_blocks_per_sdu, *core_config.codec_frames_blocks_per_sdu); } log::info( - "Added Source Stream Configuration. CIS Connection " + "StartStream: Added Source Stream Configuration. CIS Connection " "Handle: {}, Audio Channel Allocation: {}, Source Number " "Of Devices: {}, Source Number Of Channels: {}", ase.cis_conn_hdl, *core_config.audio_channel_allocation, @@ -1155,7 +1170,7 @@ protected: } else { log::assert_that(stream_conf->stream_params.sink.sample_frequency_hz == core_config.GetSamplingFrequencyHz(), - "sample freq mismatch: {}!={}", + "StartStream: sample freq mismatch: {}!={}", stream_conf->stream_params.sink.sample_frequency_hz, core_config.GetSamplingFrequencyHz()); } @@ -1166,7 +1181,7 @@ protected: } else { log::assert_that(stream_conf->stream_params.sink.octets_per_codec_frame == *core_config.octets_per_codec_frame, - "octets per frame mismatch: {}!={}", + "StartStream: octets per frame mismatch: {}!={}", stream_conf->stream_params.sink.octets_per_codec_frame, *core_config.octets_per_codec_frame); } @@ -1180,13 +1195,14 @@ protected: log::assert_that( stream_conf->stream_params.sink.codec_frames_blocks_per_sdu == *core_config.codec_frames_blocks_per_sdu, - "codec_frames_blocks_per_sdu: {}!={}", + "StartStream: codec_frames_blocks_per_sdu: {}!={}", stream_conf->stream_params.sink.codec_frames_blocks_per_sdu, *core_config.codec_frames_blocks_per_sdu); } log::info( - "Added Sink Stream Configuration. CIS Connection Handle: " + "StartStream: Added Sink Stream Configuration. CIS Connection " + "Handle: " "{}, Audio Channel Allocation: {}, Sink Number Of " "Devices: {}, Sink Number Of Channels: {}", ase.cis_conn_hdl, *core_config.audio_channel_allocation, @@ -1195,22 +1211,14 @@ protected: } } } + group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); + /* Assume CIG is created */ + group->cig.SetState(bluetooth::le_audio::types::CigState::CREATED); } - // Inject the state - group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); - - if (block_qos_config) { - return true; - } - - group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); streaming_groups[group->group_id_] = group; - /* Assume CIG is created */ - group->cig.SetState(bluetooth::le_audio::types::CigState::CREATED); - - if (block_streaming_state_callback) { + if (stay_at_qos_config_in_start_stream) { return true; } @@ -1231,7 +1239,6 @@ protected: device = group->GetNextDevice(device)) { for (auto& ase : device->ases_) { ase.cis_state = types::CisState::CONNECTED; - ase.active = false; ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED; } } @@ -1444,8 +1451,7 @@ protected: SetUpMockGatt(); SetUpMockCodecManager(codec_location); - block_streaming_state_callback = false; - block_qos_config = false; + stay_at_qos_config_in_start_stream = false; available_snk_context_types_ = 0xffff; available_src_context_types_ = 0xffff; @@ -1668,8 +1674,8 @@ protected: void SyncOnMainLoop() { // Wait for the main loop to flush // WARNING: Not tested with Timers pushing periodic tasks to the main loop - while (num_async_tasks > 0) - ; + while (num_async_tasks > 0) { + } } void ConnectLeAudio(const RawAddress& address, bool isEncrypted = true, @@ -2667,8 +2673,7 @@ protected: uint16_t global_conn_id = 1; bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks_; std::map streaming_groups; - bool block_streaming_state_callback = false; - bool block_qos_config = false; + bool stay_at_qos_config_in_start_stream = false; bool attach_to_stream_scheduled = false; @@ -4406,7 +4411,7 @@ TEST_F(UnicastTest, DoubleResumeFromAF) { types::BidirectionalPair> ccids = {.sink = {gmcs_ccid}, .source = {}}; EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1); - block_streaming_state_callback = true; + stay_at_qos_config_in_start_stream = true; UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC); LocalAudioSourceResume(false); @@ -4464,7 +4469,7 @@ TEST_F(UnicastTest, DoubleResumeFromAFOnLocalSink) { EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1); - block_streaming_state_callback = true; + stay_at_qos_config_in_start_stream = true; UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC); LocalAudioSinkResume(); @@ -4832,7 +4837,7 @@ TEST_F(UnicastTest, GroupSetActive_and_InactiveDuringStreamConfiguration) { EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1); - block_qos_config = true; + stay_at_qos_config_in_start_stream = true; LeAudioClient::Get()->GroupSetActive(group_id); StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, false, @@ -5840,40 +5845,43 @@ TEST_F(UnicastTest, EarbudsTwsStyleStreaming) { OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) .WillOnce(DoAll(SaveArg<1>(&group_id))); + log::info("Connect device"); ConnectLeAudio(test_address0); ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); - // Start streaming + // Expected CIS count on streaming uint8_t cis_count_out = 2; uint8_t cis_count_in = 0; + log::info("Group is getting Active"); // Audio sessions are started only when device gets active EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1); LeAudioClient::Get()->GroupSetActive(group_id); SyncOnMainLoop(); + log::info("Start stream"); StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); SyncOnMainLoop(); - // Verify Data transfer on one audio source cis + log::info("Verify Data transfer on one audio source cis"); TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920); - // Suspend - /*TODO Need a way to verify STOP */ + log::info("Suspend"); + EXPECT_CALL(mock_state_machine_, SuspendStream(_)).Times(1); LeAudioClient::Get()->GroupSuspend(group_id); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); - // Resume + log::info("Resume"); StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); - // Stop + log::info("Stop"); StopStreaming(group_id); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); @@ -8507,7 +8515,7 @@ TEST_F(UnicastTest, LateStreamConnectBasedOnContextType) { InjectAvailableContextTypes(test_address1, 2, types::AudioContexts(0), types::AudioContexts(0)); // Block streaming state - block_streaming_state_callback = true; + stay_at_qos_config_in_start_stream = true; UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC); LocalAudioSourceResume(false); @@ -8590,7 +8598,7 @@ TEST_F(UnicastTest, LateStreamConnectBasedOnContextTypeNotFullyConnected) { device1->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY); // Resume but block the final streaming state - keep the group in transition - block_streaming_state_callback = true; + stay_at_qos_config_in_start_stream = true; UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC); LocalAudioSourceResume(false); @@ -8642,7 +8650,7 @@ TEST_F(UnicastTest, CheckDeviceIsNotAttachedToStreamWhenNotNeeded) { SyncOnMainLoop(); // Block streaming state - block_streaming_state_callback = true; + stay_at_qos_config_in_start_stream = true; UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC); LocalAudioSourceResume(false); @@ -12324,7 +12332,7 @@ TEST_F(UnicastTest, CodecFrameBlocks2) { types::BidirectionalPair> ccids = {.sink = {gmcs_ccid}, .source = {}}; EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1); - block_streaming_state_callback = true; + stay_at_qos_config_in_start_stream = true; UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC); LocalAudioSourceResume(false); -- GitLab From a91f0ccd474101886e79b2232cbda98fd2b66e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 24 Sep 2024 11:54:29 +0000 Subject: [PATCH 027/875] flag: Add leaudio_improve_switch_during_phone_call Bug: 369322905 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: Ia734195b9e2d2b9726b13ce0db215a2ae675c2f1 --- flags/leaudio.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index d0b05c01170..26382229e8d 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -369,3 +369,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "leaudio_improve_switch_during_phone_call" + namespace: "bluetooth" + description: "Fix audio slip to speaker while switching bt audio device during phonecall" + bug: "369322905" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 1a7634547160aad8a1cc3d50f8e892fb9208247d Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Tue, 24 Sep 2024 13:07:13 +0000 Subject: [PATCH 028/875] Tbs: Fix restoring CCC values when not initialised There's no point restoring CCC descriptor values of the not yet initialized GATT service. Register the callback after creating the GATT service. Bug: 353756651 Test: atest GoogleBluetoothInstrumentationTests Flag: Exempt; fix covered with unit test Change-Id: Id469f388fb8bb4f3945d14866fb7578385355db7 --- .../app/src/com/android/bluetooth/tbs/TbsGatt.java | 13 ++++++++----- .../src/com/android/bluetooth/tbs/TbsGattTest.java | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java index 55dd3e2f4e2..af1cc022910 100644 --- a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java +++ b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java @@ -249,9 +249,6 @@ public class TbsGatt { AdapterService.getAdapterService(), "AdapterService shouldn't be null when creating TbsGatt"); - mAdapterService.registerBluetoothStateCallback( - mContext.getMainExecutor(), mBluetoothStateChangeCallback); - mBearerProviderNameCharacteristic = new GattCharacteristic( UUID_BEARER_PROVIDER_NAME, @@ -377,9 +374,15 @@ public class TbsGatt { mEventLogger = new BluetoothEventLogger( LOG_NB_EVENTS, TAG + " instance (CCID= " + ccid + ") event log"); - mEventLogger.add("Initializing"); + if (!mBluetoothGattServer.addService(gattService)) { + mEventLogger.add("Initialization failed"); + return false; + } - return mBluetoothGattServer.addService(gattService); + mEventLogger.add("Initialized"); + mAdapterService.registerBluetoothStateCallback( + mContext.getMainExecutor(), mBluetoothStateChangeCallback); + return true; } public void cleanup() { diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java index 675d7fc1308..2ad93593319 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java @@ -137,6 +137,7 @@ public class TbsGattTest { mMockTbsGattCallback)); Assert.assertNotNull(mMockGattServer); + verify(mAdapterService, times(1)).registerBluetoothStateCallback(any(), any()); verify(mMockGattServer).addService(mGattServiceCaptor.capture()); doReturn(mGattServiceCaptor.getValue()).when(mMockGattServer).getService(any(UUID.class)); Assert.assertNotNull(mMockGattServer); -- GitLab From cefd9244e2cca95ebd7d297d49239fbd557f3bc0 Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Mon, 23 Sep 2024 14:12:32 +0000 Subject: [PATCH 029/875] Bumble Java Le Audio Service Discovery Test cases Service discovery using Random address Bug: 361377820 Test: atest -v LeAudioServiceDiscoveryTest Flag: TEST_ONLY Change-Id: Id7e8846d730e81cd0b3d3ce7f820911f9eae83a7 --- framework/tests/bumble/bumble_config.json | 1 + .../LeAudioServiceDiscoveryTest.java | 370 ++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java diff --git a/framework/tests/bumble/bumble_config.json b/framework/tests/bumble/bumble_config.json index adbd21fa3d2..9a079fc5157 100644 --- a/framework/tests/bumble/bumble_config.json +++ b/framework/tests/bumble/bumble_config.json @@ -2,5 +2,6 @@ "advertising_interval": 200, "address": "51:F7:A8:75:AC:5E", "classic_enabled": true, + "class_of_device": 2376708, "irk": "1F66F4B5F0C742F807DD0DDBF64E9213" } diff --git a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java new file mode 100644 index 00000000000..27b0f106e45 --- /dev/null +++ b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2023 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 android.bluetooth.service_discovery.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 static org.mockito.Mockito.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.timeout; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothUuid; +import android.bluetooth.Host; +import android.bluetooth.PandoraDevice; +import android.bluetooth.test_utils.EnableBluetoothRule; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.ParcelUuid; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.util.Log; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.compatibility.common.util.AdoptShellPermissionsRule; + +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +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.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.hamcrest.MockitoHamcrest; + +import pandora.GattProto; +import pandora.HostProto.AdvertiseRequest; +import pandora.HostProto.DiscoverabilityMode; +import pandora.HostProto.OwnAddressType; +import pandora.HostProto.SetDiscoverabilityModeRequest; + +import java.time.Duration; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +public class LeAudioServiceDiscoveryTest { + private static final String TAG = LeAudioServiceDiscoveryTest.class.getSimpleName(); + private static final String BUMBLE_DEVICE_NAME = "Bumble"; + private static final Duration BOND_INTENT_TIMEOUT = Duration.ofSeconds(10); + private static final int DISCOVERY_TIMEOUT = 2000; // 2 seconds + private CompletableFuture mDeviceFound; + private static final ParcelUuid BATTERY_UUID = + ParcelUuid.fromString("0000180F-0000-1000-8000-00805F9B34FB"); + private static final ParcelUuid LEAUDIO_UUID = + ParcelUuid.fromString("0000184E-0000-1000-8000-00805F9B34FB"); + + private static final Context sTargetContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + private static final BluetoothAdapter sAdapter = + sTargetContext.getSystemService(BluetoothManager.class).getAdapter(); + + @Rule(order = 0) + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @Rule(order = 1) + public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule(); + + @Rule(order = 2) + public final PandoraDevice mBumble = new PandoraDevice(); + + @Rule(order = 3) + public final EnableBluetoothRule mEnableBluetoothRule = + new EnableBluetoothRule(false /* enableTestMode */, true /* toggleBluetooth */); + + @Mock private BroadcastReceiver mReceiver; + private final Map mActionRegistrationCounts = new HashMap<>(); + private InOrder mInOrder = null; + private BluetoothDevice mBumbleDevice; + private Host mHost; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + doAnswer( + inv -> { + Log.d( + TAG, + "onReceive(): intent=" + Arrays.toString(inv.getArguments())); + Intent intent = inv.getArgument(1); + String action = intent.getAction(); + if (BluetoothDevice.ACTION_UUID.equals(action)) { + ParcelUuid[] uuids = + intent.getParcelableArrayExtra( + BluetoothDevice.EXTRA_UUID, ParcelUuid.class); + Log.d(TAG, "onReceive(): UUID=" + Arrays.toString(uuids)); + } else if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) { + BluetoothDevice device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, + BluetoothDevice.class); + String deviceName = + String.valueOf( + intent.getStringExtra(BluetoothDevice.EXTRA_NAME)); + Log.i( + TAG, + "Discovered device: " + + device + + " with name: " + + deviceName); + if (deviceName != null && BUMBLE_DEVICE_NAME.equals(deviceName)) { + mDeviceFound.complete(device); + } + } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals( + intent.getAction())) { + BluetoothDevice device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, + BluetoothDevice.class); + int transport = + intent.getIntExtra( + BluetoothDevice.EXTRA_TRANSPORT, + BluetoothDevice.TRANSPORT_AUTO); + Log.i( + TAG, + "ACL connected for device=" + + device + + " with transport: " + + transport); + } + return null; + }) + .when(mReceiver) + .onReceive(any(), any()); + + mInOrder = inOrder(mReceiver); + mHost = new Host(sTargetContext); + } + + @After + public void tearDown() throws Exception { + if (mBumbleDevice.getBondState() == BluetoothDevice.BOND_BONDED) { + mHost.removeBondAndVerify(mBumbleDevice); + } + mHost.close(); + mBumbleDevice = null; + if (getTotalActionRegistrationCounts() > 0) { + sTargetContext.unregisterReceiver(mReceiver); + mActionRegistrationCounts.clear(); + } + } + + /** + * Ensure that successful service discovery results on both Transport for LE Audio capable + * device + * + *

    Prerequisites: + * + *

      + *
    1. Bumble and Android are not bonded + *
    2. Bumble has GATT services in addition to GAP and GATT services + *
    + * + *

    Steps: + * + *

      + *
    1. Bumble is discoverable and connectable on both Transport + *
    2. Android creates the Bond + *
    3. Android starts service discovery on both Transport + *
    + * + * Expectation: ACTION_UUID intent is received and The ACTION_UUID intent has both LE and + * Classic services + */ + @Test + public void testServiceDiscoveryWithRandomAddr() { + + registerIntentActions( + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_UUID, + BluetoothDevice.ACTION_FOUND); + + // Register Battery and Le Audio services on Bumble + mBumble.gattBlocking() + .registerService( + GattProto.RegisterServiceRequest.newBuilder() + .setService( + GattProto.GattServiceParams.newBuilder() + .setUuid(BATTERY_UUID.toString()) + .build()) + .build()); + mBumble.gattBlocking() + .registerService( + GattProto.RegisterServiceRequest.newBuilder() + .setService( + GattProto.GattServiceParams.newBuilder() + .setUuid(LEAUDIO_UUID.toString()) + .build()) + .build()); + + // Make Bumble connectable + mBumble.hostBlocking() + .advertise( + AdvertiseRequest.newBuilder() + .setLegacy(true) + .setConnectable(true) + .setOwnAddressType(OwnAddressType.RANDOM) + .build()); + // Make Bumble discoverable over BR/EDR + mBumble.hostBlocking() + .setDiscoverabilityMode( + SetDiscoverabilityModeRequest.newBuilder() + .setMode(DiscoverabilityMode.DISCOVERABLE_GENERAL) + .build()); + // Start Discovery + mDeviceFound = new CompletableFuture<>(); + assertThat(sAdapter.startDiscovery()).isTrue(); + mBumbleDevice = + mDeviceFound + .completeOnTimeout(null, DISCOVERY_TIMEOUT, TimeUnit.MILLISECONDS) + .join(); + assertThat(sAdapter.cancelDiscovery()).isTrue(); + // Create Bond + mHost.createBondAndVerify(mBumbleDevice); + + // Verify ACL connection on classic transport first and then LE transport + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_CONNECTED), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_CONNECTED), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE)); + + // Verify both LE and Classic Services + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_UUID), + hasExtra( + BluetoothDevice.EXTRA_UUID, + Matchers.allOf( + Matchers.hasItemInArray(BluetoothUuid.HFP), + Matchers.hasItemInArray(BluetoothUuid.HID), + Matchers.hasItemInArray(BluetoothUuid.A2DP_SOURCE), + Matchers.hasItemInArray(BluetoothUuid.A2DP_SINK), + Matchers.hasItemInArray(BluetoothUuid.AVRCP), + Matchers.hasItemInArray(BluetoothUuid.LE_AUDIO), + Matchers.hasItemInArray(BluetoothUuid.BATTERY), + Matchers.hasItemInArray(BluetoothUuid.HOGP)))); + unregisterIntentActions( + BluetoothDevice.ACTION_UUID, + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_FOUND); + } + + @SafeVarargs + private void verifyIntentReceived(Matcher... matchers) { + mInOrder.verify(mReceiver, timeout(BOND_INTENT_TIMEOUT.toMillis())) + .onReceive(any(Context.class), MockitoHamcrest.argThat(AllOf.allOf(matchers))); + } + + /** + * Helper function to add reference count to registered intent actions + * + * @param actions new intent actions to add. If the array is empty, it is a no-op. + */ + private void registerIntentActions(String... actions) { + if (actions.length == 0) { + return; + } + if (getTotalActionRegistrationCounts() > 0) { + Log.d(TAG, "registerIntentActions(): unregister ALL intents"); + sTargetContext.unregisterReceiver(mReceiver); + } + for (String action : actions) { + mActionRegistrationCounts.merge(action, 1, Integer::sum); + } + IntentFilter filter = new IntentFilter(); + mActionRegistrationCounts.entrySet().stream() + .filter(entry -> entry.getValue() > 0) + .forEach( + entry -> { + Log.d( + TAG, + "registerIntentActions(): Registering action = " + + entry.getKey()); + filter.addAction(entry.getKey()); + }); + sTargetContext.registerReceiver(mReceiver, filter); + } + + /** + * Helper function to reduce reference count to registered intent actions If total reference + * count is zero after removal, no broadcast receiver will be registered. + * + * @param actions intent actions to be removed. If some action is not registered, it is no-op + * for that action. If the actions array is empty, it is also a no-op. + */ + private void unregisterIntentActions(String... actions) { + if (actions.length == 0) { + return; + } + if (getTotalActionRegistrationCounts() <= 0) { + return; + } + Log.d(TAG, "unregisterIntentActions(): unregister ALL intents"); + sTargetContext.unregisterReceiver(mReceiver); + for (String action : actions) { + if (!mActionRegistrationCounts.containsKey(action)) { + continue; + } + mActionRegistrationCounts.put(action, mActionRegistrationCounts.get(action) - 1); + if (mActionRegistrationCounts.get(action) <= 0) { + mActionRegistrationCounts.remove(action); + } + } + if (getTotalActionRegistrationCounts() > 0) { + IntentFilter filter = new IntentFilter(); + mActionRegistrationCounts.entrySet().stream() + .filter(entry -> entry.getValue() > 0) + .forEach( + entry -> { + Log.d( + TAG, + "unregisterIntentActions(): Registering action = " + + entry.getKey()); + filter.addAction(entry.getKey()); + }); + sTargetContext.registerReceiver(mReceiver, filter); + } + } + + /** + * Get sum of reference count from all registered actions + * + * @return sum of reference count from all registered actions + */ + private int getTotalActionRegistrationCounts() { + return mActionRegistrationCounts.values().stream().reduce(0, Integer::sum); + } +} -- GitLab From 7de5617f7d5266fe57c990c428621b5d4e92728a Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Thu, 12 Sep 2024 17:26:55 +0000 Subject: [PATCH 030/875] Fix OOB writes in gatt_sr.cc At various points in gatt_sr.cc, the output of the gatt_tcb_get_payload_size function is used without checking for a positive length. However, in exceptional cases it is possible for the channel to be closed at the time the function is called, which will lead to a zero length and cause an OOB write in subsequent processing. Fix all of these. Bug: 364026473 Bug: 364027038 Bug: 364027949 Bug: 364025411 Test: m libbluetooth Test: researcher POC Flag: EXEMPT trivial validity checks Tag: #security Ignore-AOSP-First: Security Change-Id: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404 --- system/stack/gatt/gatt_sr.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 995ea810cb0..0235ba964e7 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -772,6 +772,11 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_ uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t msg_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); reason = gatt_build_primary_service_rsp(p_msg, tcb, cid, op_code, s_hdl, e_hdl, p_data, value); @@ -804,6 +809,12 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint16_t cid, uint8_t op_cod } uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t buf_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(buf_len); @@ -949,6 +960,11 @@ static void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint16_t cid, uint8_t uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t msg_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; @@ -1096,6 +1112,11 @@ static void gatts_process_read_req(tGATT_TCB& tcb, uint16_t cid, tGATT_SRV_LIST_ uint8_t* p_data) { uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t buf_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; uint16_t offset = 0; -- GitLab From 7cb84b932a4fa0b01d87a049d93b9864de6271af Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Tue, 24 Sep 2024 09:10:49 +0000 Subject: [PATCH 031/875] RAS: Fix null pointer dereference when remote device does not support real-time functionality Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 358120531 Test: m com.android.btservice Change-Id: Ic4d14535ddf78ddbbd31cb400a1c557a587e4804 --- system/bta/ras/ras_client.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/system/bta/ras/ras_client.cc b/system/bta/ras/ras_client.cc index 0323a19ddba..9b459fdb5ed 100644 --- a/system/bta/ras/ras_client.cc +++ b/system/bta/ras/ras_client.cc @@ -38,6 +38,7 @@ RasClientImpl* instance; enum CallbackDataType { VENDOR_SPECIFIC_REPLY }; static constexpr uint16_t kCachedDataSize = 10; +static constexpr uint16_t kInvalidGattHandle = 0x0000; class RasClientImpl : public bluetooth::ras::RasClient { public: @@ -128,9 +129,12 @@ public: trackers_.emplace_back(std::make_shared(ble_bd_addr.bda, address)); } else if (tracker->is_connected_) { log::info("Already connected"); - uint16_t att_handle = tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic) - ->value_handle; - callbacks_->OnConnected(address, att_handle, tracker->vendor_specific_characteristics_); + auto characteristic = + tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic); + uint16_t real_time_att_handle = + characteristic == nullptr ? kInvalidGattHandle : characteristic->value_handle; + callbacks_->OnConnected(address, real_time_att_handle, + tracker->vendor_specific_characteristics_); return; } BTA_GATTC_Open(gatt_if_, ble_bd_addr.bda, BTM_BLE_DIRECT_CONNECTION, true); @@ -636,9 +640,10 @@ public: SubscribeCharacteristic(tracker, kRasRangingDataReadyCharacteristic); SubscribeCharacteristic(tracker, kRasRangingDataOverWrittenCharacteristic); } - uint16_t att_handle = - tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic)->value_handle; - callbacks_->OnConnected(tracker->address_for_cs_, att_handle, + auto characteristic = tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic); + uint16_t real_time_att_handle = + characteristic == nullptr ? kInvalidGattHandle : characteristic->value_handle; + callbacks_->OnConnected(tracker->address_for_cs_, real_time_att_handle, tracker->vendor_specific_characteristics_); } -- GitLab From 9cccf3f8fbb58e95967f9d9154321c4f27e0dca3 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Tue, 24 Sep 2024 09:38:43 +0000 Subject: [PATCH 032/875] RAS: Refine variable and function naming Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 369303724 Test: m com.android.btservice Change-Id: Id5afab05485c6d4dff9511d403cff9e8e1257ceb --- system/bta/ras/ras_client.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/system/bta/ras/ras_client.cc b/system/bta/ras/ras_client.cc index 9b459fdb5ed..b007c71ff43 100644 --- a/system/bta/ras/ras_client.cc +++ b/system/bta/ras/ras_client.cc @@ -69,8 +69,8 @@ public: bool is_connected_ = false; bool service_search_complete_ = false; std::vector vendor_specific_characteristics_; - uint8_t writeReplyCounter_ = 0; - uint8_t writeReplySuccessCounter_ = 0; + uint8_t write_reply_counter_ = 0; + uint8_t write_reply_success_counter_ = 0; const gatt::Characteristic* FindCharacteristicByUuid(Uuid uuid) { for (auto& characteristic : service_->characteristics) { @@ -438,9 +438,9 @@ public: if (structPtr->type_ == CallbackDataType::VENDOR_SPECIFIC_REPLY) { log::info("Write vendor specific reply complete"); auto tracker = FindTrackerByHandle(conn_id); - tracker->writeReplyCounter_++; + tracker->write_reply_counter_++; if (status == GATT_SUCCESS) { - tracker->writeReplySuccessCounter_++; + tracker->write_reply_success_counter_++; } else { log::error( "Fail to write vendor specific reply conn_id {}, status {}, " @@ -448,16 +448,16 @@ public: conn_id, gatt_status_text(status), handle); } // All reply complete - if (tracker->writeReplyCounter_ == tracker->vendor_specific_characteristics_.size()) { + if (tracker->write_reply_counter_ == tracker->vendor_specific_characteristics_.size()) { log::info( "All vendor specific reply write complete, size {} " "successCounter {}", tracker->vendor_specific_characteristics_.size(), - tracker->writeReplySuccessCounter_); - bool success = tracker->writeReplySuccessCounter_ == + tracker->write_reply_success_counter_); + bool success = tracker->write_reply_success_counter_ == tracker->vendor_specific_characteristics_.size(); - tracker->writeReplyCounter_ = 0; - tracker->writeReplySuccessCounter_ = 0; + tracker->write_reply_counter_ = 0; + tracker->write_reply_success_counter_ = 0; callbacks_->OnWriteVendorSpecificReplyComplete(tracker->address_for_cs_, success); } return; @@ -616,7 +616,7 @@ public: } STREAM_TO_UINT32(tracker->remote_supported_features_, value); log::info("Remote supported features : {}", - getFeaturesString(tracker->remote_supported_features_)); + GetFeaturesString(tracker->remote_supported_features_)); } break; default: log::warn("Unexpected UUID"); @@ -678,7 +678,7 @@ public: } } - std::string getFeaturesString(uint32_t value) { + std::string GetFeaturesString(uint32_t value) { std::stringstream ss; ss << value; if (value == 0) { -- GitLab From b30c0ef521097bda43131194ff63c32b93f0c0ae Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Tue, 24 Sep 2024 09:58:43 +0000 Subject: [PATCH 033/875] RAS: Use notifcation if both registered Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 369303724 Test: m com.android.btservice Change-Id: Ica8227052e9f3bea5eb393efac8a63a14c41c71b --- system/bta/ras/ras_server.cc | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/system/bta/ras/ras_server.cc b/system/bta/ras/ras_server.cc index 0152fe9506d..e6720a440c4 100644 --- a/system/bta/ras/ras_server.cc +++ b/system/bta/ras/ras_server.cc @@ -128,11 +128,11 @@ public: uint16_t ccc_data_over_written = tracker.ccc_values_[kRasRangingDataOverWrittenCharacteristic]; if (ccc_real_time != GATT_CLT_CONFIG_NONE) { - bool need_confirm = ccc_real_time & GATT_CLT_CONFIG_INDICATION; + bool use_notification = ccc_real_time & GATT_CLT_CONFIG_NOTIFICATION; uint16_t attr_id = GetCharacteristic(kRasRealTimeRangingDataCharacteristic)->attribute_handle_; log::debug("Send Real-time Ranging Data is_last {}", is_last); - BTA_GATTS_HandleValueIndication(tracker.conn_id_, attr_id, data, need_confirm); + BTA_GATTS_HandleValueIndication(tracker.conn_id_, attr_id, data, !use_notification); } if (ccc_data_ready == GATT_CLT_CONFIG_NONE && ccc_data_over_written == GATT_CLT_CONFIG_NONE) { @@ -369,15 +369,11 @@ public: } break; case kRasRangingDataReadyCharacteristic16bit: { p_msg.attr_value.len = kRingingCounterSize; - std::vector value(kRingingCounterSize); - if (tracker->buffers_.size() > 0) { - p_msg.attr_value.value[0] = (tracker->last_ready_procedure_ & 0xFF); - p_msg.attr_value.value[1] = (tracker->last_ready_procedure_ >> 8) & 0xFF; - } + p_msg.attr_value.value[0] = (tracker->last_ready_procedure_ & 0xFF); + p_msg.attr_value.value[1] = (tracker->last_ready_procedure_ >> 8) & 0xFF; } break; case kRasRangingDataOverWrittenCharacteristic16bit: { p_msg.attr_value.len = kRingingCounterSize; - std::vector value(kRingingCounterSize); p_msg.attr_value.value[0] = (tracker->last_overwritten_procedure_ & 0xFF); p_msg.attr_value.value[1] = (tracker->last_overwritten_procedure_ >> 8) & 0xFF; } break; @@ -454,11 +450,6 @@ public: return; } ClientTracker* tracker = &trackers_[p_data->req_data.remote_bda]; - if (tracker->handling_control_point_command_) { - log::warn("Server busy"); - SendResponseCode(ResponseCodeValue::SERVER_BUSY, tracker); - return; - } if (need_rsp) { BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); } @@ -566,6 +557,12 @@ public: return; } + if (tracker->handling_control_point_command_ && command.opcode_ != Opcode::ABORT_OPERATION) { + log::warn("Server busy"); + SendResponseCode(ResponseCodeValue::SERVER_BUSY, tracker); + return; + } + tracker->handling_control_point_command_ = true; switch (command.opcode_) { @@ -596,7 +593,7 @@ public: uint16_t ccc_value = tracker->ccc_values_[kRasOnDemandDataCharacteristic]; uint16_t attr_id = GetCharacteristic(kRasOnDemandDataCharacteristic)->attribute_handle_; - bool need_confirm = ccc_value & GATT_CLT_CONFIG_INDICATION; + bool use_notification = ccc_value & GATT_CLT_CONFIG_NOTIFICATION; std::lock_guard lock(on_demand_ranging_mutex_); auto it = std::find_if(tracker->buffers_.begin(), tracker->buffers_.end(), @@ -610,7 +607,8 @@ public: break; } log::info("Send On Demand Ranging Data, segment {}", i); - BTA_GATTS_HandleValueIndication(tracker->conn_id_, attr_id, it->segments_[i], need_confirm); + BTA_GATTS_HandleValueIndication(tracker->conn_id_, attr_id, it->segments_[i], + !use_notification); } log::info("Send COMPLETE_RANGING_DATA_RESPONSE, ranging_counter:{}", ranging_counter); std::vector response(3, 0); -- GitLab From fe1323145828764ea1b1785dd329423e13afbc64 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Tue, 24 Sep 2024 18:06:44 +0800 Subject: [PATCH 034/875] Flag: Add dont_send_hid_set_idle Bug: 369310847 Bug: 315241296 Test: m -j Change-Id: I5c314dd1188e5ab39266d733d4fe92fd17dfaffd --- flags/hid.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/hid.aconfig b/flags/hid.aconfig index e2dda1a5ede..caf160415eb 100644 --- a/flags/hid.aconfig +++ b/flags/hid.aconfig @@ -112,3 +112,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "dont_send_hid_set_idle" + namespace: "bluetooth" + description: "Don't send the SET IDLE HID message" + bug: "369310847" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 66c401199d0d42caa5abc75f97f02625355dfa43 Mon Sep 17 00:00:00 2001 From: Hsin-yu Chao Date: Thu, 15 Aug 2024 14:07:27 +0000 Subject: [PATCH 035/875] bta_ag_sco: Init and start HFP SW encode/decode Add HFP encode/decode interface if property bluetooth.hfp.software_datapath.enabled is set. Bug: 349290628 Bug: 315234036 Test: m com.google.android.btservices Flag: com::android::bluetooth::flags::is_sco_managed_by_audio and HFP and bluetooth.hfp.software_datapath.enabled Change-Id: Idd0cd9aacc9fc121f21c2160f41c69c64298a530 --- system/bta/ag/bta_ag_int.h | 2 + system/bta/ag/bta_ag_sco.cc | 133 +++++++++++++++++++++++++++----- system/stack/Android.bp | 1 + system/stack/btm/btm_sco_hci.cc | 13 +--- 4 files changed, 121 insertions(+), 28 deletions(-) diff --git a/system/bta/ag/bta_ag_int.h b/system/bta/ag/bta_ag_int.h index 5b2cded3f7c..0b673a24d59 100644 --- a/system/bta/ag/bta_ag_int.h +++ b/system/bta/ag/bta_ag_int.h @@ -445,6 +445,8 @@ void bta_ag_result(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data); void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data); void bta_ag_send_ring(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data); void bta_ag_handle_collision(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data); +size_t bta_ag_sco_write(const uint8_t* p_buf, uint32_t len); +size_t bta_ag_sco_read(uint8_t* p_buf, uint32_t len); /* Internal utility functions */ void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result); diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index 4c6e06e8a7f..13c76de33c3 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -63,9 +63,12 @@ using namespace bluetooth; HCI_AIR_CODING_FORMAT_TRANSPNT)) static bool sco_allowed = true; +static bool hfp_software_datapath_enabled = false; static RawAddress active_device_addr = {}; static std::unique_ptr hfp_client_interface; static std::unique_ptr hfp_offload_interface; +static std::unique_ptr hfp_encode_interface; +static std::unique_ptr hfp_decode_interface; static std::unordered_map sco_config_map; static std::unordered_map codec_coding_format_map{ {tBTA_AG_UUID_CODEC::UUID_CODEC_LC3, ESCO_CODING_FORMAT_LC3}, @@ -282,7 +285,14 @@ static void bta_ag_sco_disc_cback(uint16_t sco_idx) { } else { log::error("eSCO/SCO failed to open, no more fall back"); if (bta_ag_is_sco_managed_by_audio()) { - hfp_offload_interface->CancelStreamingRequest(); + if (hfp_software_datapath_enabled) { + if (hfp_encode_interface) { + hfp_encode_interface->CancelStreamingRequest(); + hfp_decode_interface->CancelStreamingRequest(); + } + } else { + hfp_offload_interface->CancelStreamingRequest(); + } } } } @@ -1359,6 +1369,40 @@ void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) { bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E); } +/******************************************************************************* + * + * Function bta_ag_sco_write + * + * Description Writes bytes to decoder interface + * + * + * Returns Number of bytes written + * + ******************************************************************************/ +size_t bta_ag_sco_write(const uint8_t* p_buf, uint32_t len) { + if (hfp_software_datapath_enabled && hfp_decode_interface) { + return hfp_decode_interface->Write(p_buf, len); + } + return 0; +} + +/******************************************************************************* + * + * Function bta_ag_sco_read + * + * Description Reads bytes from encoder interface + * + * + * Returns Number of bytes read + * + ******************************************************************************/ +size_t bta_ag_sco_read(uint8_t* p_buf, uint32_t len) { + if (hfp_software_datapath_enabled && hfp_encode_interface) { + return hfp_encode_interface->Read(p_buf, len); + } + return 0; +} + /******************************************************************************* * * Function bta_ag_sco_conn_open @@ -1388,10 +1432,24 @@ void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) { .is_controller_codec = is_controller_codec, .is_nrec = p_scb->nrec_enabled, }; - hfp_offload_interface->UpdateAudioConfigToHal(config); + if (hfp_software_datapath_enabled) { + if (hfp_encode_interface) { + hfp_encode_interface->UpdateAudioConfigToHal(config); + hfp_decode_interface->UpdateAudioConfigToHal(config); + } + } else { + hfp_offload_interface->UpdateAudioConfigToHal(config); + } // ConfirmStreamingRequest before sends callback to java layer - hfp_offload_interface->ConfirmStreamingRequest(); + if (hfp_software_datapath_enabled) { + if (hfp_encode_interface) { + hfp_encode_interface->ConfirmStreamingRequest(); + hfp_decode_interface->ConfirmStreamingRequest(); + } + } else { + hfp_offload_interface->ConfirmStreamingRequest(); + } } /* call app callback */ @@ -1549,8 +1607,17 @@ bool bta_ag_is_sco_managed_by_audio() { } void bta_ag_stream_suspended() { - if (bta_ag_is_sco_managed_by_audio() && hfp_offload_interface) { - hfp_offload_interface->CancelStreamingRequest(); + if (bta_ag_is_sco_managed_by_audio()) { + if (hfp_software_datapath_enabled) { + if (hfp_encode_interface) { + hfp_encode_interface->CancelStreamingRequest(); + hfp_decode_interface->CancelStreamingRequest(); + } + } else { + if (hfp_offload_interface) { + hfp_offload_interface->CancelStreamingRequest(); + } + } } } @@ -1559,8 +1626,15 @@ const RawAddress& bta_ag_get_active_device() { return active_device_addr; } void bta_clear_active_device() { log::debug("Set bta active device to null, current active device:{}", active_device_addr); if (bta_ag_is_sco_managed_by_audio()) { - if (hfp_offload_interface && !active_device_addr.IsEmpty()) { - hfp_offload_interface->StopSession(); + if (hfp_software_datapath_enabled) { + if (hfp_encode_interface && !active_device_addr.IsEmpty()) { + hfp_encode_interface->StopSession(); + hfp_decode_interface->StopSession(); + } + } else { + if (hfp_offload_interface && !active_device_addr.IsEmpty()) { + hfp_offload_interface->StopSession(); + } } } active_device_addr = RawAddress::kEmpty; @@ -1574,26 +1648,49 @@ void bta_ag_api_set_active_device(const RawAddress& new_active_device) { } if (bta_ag_is_sco_managed_by_audio()) { + // Initialize and start HFP software data path if (!hfp_client_interface) { hfp_client_interface = std::unique_ptr(HfpInterface::Get()); if (!hfp_client_interface) { log::error("could not acquire audio source interface"); } } + hfp_software_datapath_enabled = + osi_property_get_bool("bluetooth.hfp.software_datapath.enabled", false); + + // Initialize and start HFP software datapath if enabled + if (hfp_software_datapath_enabled) { + if (hfp_client_interface && !hfp_encode_interface && !hfp_decode_interface) { + hfp_encode_interface = std::unique_ptr( + hfp_client_interface->GetEncode(get_main_thread())); + hfp_decode_interface = std::unique_ptr( + hfp_client_interface->GetDecode(get_main_thread())); + if (!hfp_encode_interface || !hfp_decode_interface) { + log::warn("could not get HFP SW interface"); + } + } - if (hfp_client_interface && !hfp_offload_interface) { - hfp_offload_interface = std::unique_ptr( - hfp_client_interface->GetOffload(get_main_thread())); - if (!hfp_offload_interface) { - log::warn("could not get offload interface"); + if (hfp_encode_interface && hfp_decode_interface) { + if (active_device_addr.IsEmpty()) { + hfp_encode_interface->StartSession(); + hfp_decode_interface->StartSession(); + } + } + } else { // Initialize and start HFP offloading + if (hfp_client_interface && !hfp_offload_interface) { + hfp_offload_interface = std::unique_ptr( + hfp_client_interface->GetOffload(get_main_thread())); + if (!hfp_offload_interface) { + log::warn("could not get offload interface"); + } } - } - if (hfp_offload_interface) { - sco_config_map = hfp_offload_interface->GetHfpScoConfig(); - // start audio session if there was no previous active device - if (active_device_addr.IsEmpty()) { - hfp_offload_interface->StartSession(); + if (hfp_offload_interface) { + sco_config_map = hfp_offload_interface->GetHfpScoConfig(); + // start audio session if there was no previous active device + if (active_device_addr.IsEmpty()) { + hfp_offload_interface->StartSession(); + } } } } diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 817c94ee166..ff7c956bcd4 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -203,6 +203,7 @@ cc_library_static { ], include_dirs: [ "packages/modules/Bluetooth/system", + "packages/modules/Bluetooth/system/bta/ag", "packages/modules/Bluetooth/system/bta/include", "packages/modules/Bluetooth/system/bta/sys", "packages/modules/Bluetooth/system/gd", diff --git a/system/stack/btm/btm_sco_hci.cc b/system/stack/btm/btm_sco_hci.cc index 44bb5e81178..a7f5e152ace 100644 --- a/system/stack/btm/btm_sco_hci.cc +++ b/system/stack/btm/btm_sco_hci.cc @@ -25,6 +25,7 @@ #include #include +#include "bta/ag/bta_ag_int.h" #include "btif/include/core_callbacks.h" #include "btif/include/stack_manager_t.h" #include "os/log.h" @@ -144,17 +145,9 @@ size_t write(const uint8_t* p_buf, uint32_t len) { void open() {} void cleanup() {} -size_t read(uint8_t* p_buf, uint32_t len) { - (void)p_buf; - (void)len; - return 0; -} +size_t read(uint8_t* p_buf, uint32_t len) { return bta_ag_sco_read(p_buf, len); } -size_t write(const uint8_t* p_buf, uint32_t len) { - (void)p_buf; - (void)len; - return 0; -} +size_t write(const uint8_t* p_buf, uint32_t len) { return bta_ag_sco_write(p_buf, len); } #endif enum decode_buf_state { -- GitLab From db95abe4abd4622c5be242981dd7ca6e139694e6 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 14 Sep 2024 16:55:12 +0000 Subject: [PATCH 036/875] StopWatchLegacy: fix OOB array access in |RecordLog| |current_buffer_index| does not guarantee to be less than |LOG_BUFFER_LENGTH| on read. Bug: 364491209 Bug: 349290628 Flag: EXEMPT, obvious and risk-free bug fix Test: m Bluetooth Change-Id: I9652364667586ed1c0595fb84e822fafdb217cf9 --- system/common/stop_watch_legacy.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/system/common/stop_watch_legacy.cc b/system/common/stop_watch_legacy.cc index 1056fd4a51f..45595ed19f9 100644 --- a/system/common/stop_watch_legacy.cc +++ b/system/common/stop_watch_legacy.cc @@ -37,11 +37,14 @@ static std::recursive_mutex stopwatch_log_mutex; void StopWatchLegacy::RecordLog(StopWatchLog log) { std::unique_lock lock(stopwatch_log_mutex, std::defer_lock); if (!lock.try_lock()) { - log::info("try_lock fail. log content: {}, took {} us", log.message, - static_cast(std::chrono::duration_cast( - stopwatch_logs[current_buffer_index].end_timestamp - - stopwatch_logs[current_buffer_index].start_timestamp) - .count())); + log::info( + "try_lock fail. log content: {}, took {} us", log.message, + static_cast( + std::chrono::duration_cast( + stopwatch_logs[current_buffer_index % LOG_BUFFER_LENGTH].end_timestamp - + stopwatch_logs[current_buffer_index % LOG_BUFFER_LENGTH] + .start_timestamp) + .count())); return; } if (current_buffer_index >= LOG_BUFFER_LENGTH) { -- GitLab From 75313b0a452320c0eb347f4c21ba38fad37a34b9 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 5 Sep 2024 03:22:10 +0000 Subject: [PATCH 037/875] HfpClientInterface: fix decoder client suspend |Decode::CancelStreamingRequest| should propagate the event to the decoder interface, rather than to the encoder interface. Bug: 349290628 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio and HFP Test: atest --host bluetooth-test-audio-hal-hfp-client-interface Change-Id: Ib644c143ca88437519371e9a7cb3a03685b64d7b --- system/audio_hal_interface/hfp_client_interface.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index 35aeea0728f..ae8b41fee76 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -206,7 +206,7 @@ void HfpClientInterface::Decode::CancelStreamingRequest() { return; case aidl::hfp::HFP_CTRL_CMD_SUSPEND: log::info("suspends"); - aidl::hfp::HfpEncodingTransport::software_hal_interface->StreamSuspended( + aidl::hfp::HfpDecodingTransport::software_hal_interface->StreamSuspended( aidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED); instance->ResetPendingCmd(); return; -- GitLab From f1a650c77020e25b16e70d5d41e5fa23777d38ad Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 6 Sep 2024 09:52:35 +0000 Subject: [PATCH 038/875] HfpClientInterface: always ack on |*StreamingRequest| The audio HAL expects a response from the BT stack on start/suspend. Since SCO connections can be opened on demand for either directions (w.r.t. audio streams), but closed for both directions at once, it can be tricky to try to validate which suspend acks should be sent to which client (e.g., there could be a race between the two start requests and a suspend in between). Here we enfore acks to the listeners of both directions on SCO connection start/suspend. Test: verify BT audio works Test: m Bluetooth Bug: 349290628 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio and HFP Change-Id: I5b19e763d0a663c2b8234638f43fb4fb2da43fbc --- .../audio_hal_interface/hfp_client_interface.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index ae8b41fee76..e5c578151a1 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -179,14 +179,14 @@ void HfpClientInterface::Decode::ConfirmStreamingRequest() { auto instance = aidl::hfp::HfpDecodingTransport::instance_; auto pending_cmd = instance->GetPendingCmd(); switch (pending_cmd) { + case aidl::hfp::HFP_CTRL_CMD_NONE: + log::warn("no pending start stream request"); + FALLTHROUGH_INTENDED; case aidl::hfp::HFP_CTRL_CMD_START: aidl::hfp::HfpDecodingTransport::software_hal_interface->StreamStarted( aidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED); instance->ResetPendingCmd(); return; - case aidl::hfp::HFP_CTRL_CMD_NONE: - log::warn("no pending start stream request"); - return; default: log::warn("Invalid state, {}", pending_cmd); } @@ -203,7 +203,7 @@ void HfpClientInterface::Decode::CancelStreamingRequest() { return; case aidl::hfp::HFP_CTRL_CMD_NONE: log::warn("no pending start stream request"); - return; + FALLTHROUGH_INTENDED; case aidl::hfp::HFP_CTRL_CMD_SUSPEND: log::info("suspends"); aidl::hfp::HfpDecodingTransport::software_hal_interface->StreamSuspended( @@ -330,14 +330,14 @@ void HfpClientInterface::Encode::ConfirmStreamingRequest() { auto instance = aidl::hfp::HfpEncodingTransport::instance_; auto pending_cmd = instance->GetPendingCmd(); switch (pending_cmd) { + case aidl::hfp::HFP_CTRL_CMD_NONE: + log::warn("no pending start stream request"); + FALLTHROUGH_INTENDED; case aidl::hfp::HFP_CTRL_CMD_START: aidl::hfp::HfpEncodingTransport::software_hal_interface->StreamStarted( aidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED); instance->ResetPendingCmd(); return; - case aidl::hfp::HFP_CTRL_CMD_NONE: - log::warn("no pending start stream request"); - return; default: log::warn("Invalid state, {}", pending_cmd); } @@ -354,7 +354,7 @@ void HfpClientInterface::Encode::CancelStreamingRequest() { return; case aidl::hfp::HFP_CTRL_CMD_NONE: log::warn("no pending start stream request"); - return; + FALLTHROUGH_INTENDED; case aidl::hfp::HFP_CTRL_CMD_SUSPEND: log::info("suspends"); aidl::hfp::HfpEncodingTransport::software_hal_interface->StreamSuspended( -- GitLab From a56cd183914bd28652b21d28fb126ee605bd4d0f Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 29 Aug 2024 01:28:26 +0000 Subject: [PATCH 039/875] HfpClientInterface: implement UpdateAudioConfigToHal This CL implements the function that allows updating audio config (specifically, to account for codec change in HFP) for SW path. Test: m com.google.android.btservices Bug: 349290628 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio and HFP and bluetooth.hfp.software_datapath.enabled Change-Id: I801f5baabc5fef9081650336a52a194b3235de0e --- .../hfp_client_interface.cc | 40 +++++++++++++++++-- .../hfp_client_interface.h | 4 ++ system/bta/ag/bta_ag_sco.cc | 31 +++++++++++--- system/bta/include/bta_ag_api.h | 11 ++++- 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index e5c578151a1..51c80efab8f 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -97,6 +97,12 @@ AudioConfiguration offload_config_to_hal_audio_config(const ::hfp::offload_confi return AudioConfiguration(hfp_config); } +AudioConfiguration pcm_config_to_hal_audio_config(const ::hfp::pcm_config& pcm_config) { + PcmConfiguration config = get_default_pcm_configuration(); + config.sampleRateHz = pcm_config.sample_rate_hz; + return AudioConfiguration(config); +} + bool is_aidl_support_hfp() { return HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::AIDL && HalVersionManager::GetHalVersion() >= BluetoothAudioHalVersion::VERSION_AIDL_V4; @@ -157,13 +163,23 @@ void HfpClientInterface::Decode::StopSession() { void HfpClientInterface::Decode::UpdateAudioConfigToHal( const ::hfp::offload_config& offload_config) { + log::warn( + "'UpdateAudioConfigToHal(offload_config)' should not be called on " + "HfpClientInterface::Decode"); +} + +void HfpClientInterface::Decode::UpdateAudioConfigToHal(const ::hfp::pcm_config& pcm_config) { if (!is_aidl_support_hfp()) { log::warn("Unsupported HIDL or AIDL version"); return; } - log::warn("decode - Unsupported update audio config for software session"); - return; + log::info("decode"); + if (!get_decode_client_interface()->UpdateAudioConfig( + pcm_config_to_hal_audio_config(pcm_config))) { + log::error("cannot update audio config to HAL"); + return; + } } size_t HfpClientInterface::Decode::Write(const uint8_t* p_buf, uint32_t len) { @@ -308,13 +324,23 @@ void HfpClientInterface::Encode::StopSession() { void HfpClientInterface::Encode::UpdateAudioConfigToHal( const ::hfp::offload_config& offload_config) { + log::warn( + "'UpdateAudioConfigToHal(offload_config)' should not be called on " + "HfpClientInterface::Encode"); +} + +void HfpClientInterface::Encode::UpdateAudioConfigToHal(const ::hfp::pcm_config& pcm_config) { if (!is_aidl_support_hfp()) { log::warn("Unsupported HIDL or AIDL version"); return; } - log::warn("encode - Unsupported update audio config for software session"); - return; + log::info("encode"); + if (!get_encode_client_interface()->UpdateAudioConfig( + pcm_config_to_hal_audio_config(pcm_config))) { + log::error("cannot update audio config to HAL"); + return; + } } size_t HfpClientInterface::Encode::Read(uint8_t* p_buf, uint32_t len) { @@ -469,6 +495,12 @@ void HfpClientInterface::Offload::UpdateAudioConfigToHal( offload_config_to_hal_audio_config(offload_config)); } +void HfpClientInterface::Offload::UpdateAudioConfigToHal(const ::hfp::pcm_config& pcm_config) { + log::warn( + "'UpdateAudioConfigToHal(pcm_config)' should not be called on " + "HfpClientInterface::Offload"); +} + void HfpClientInterface::Offload::ConfirmStreamingRequest() { auto instance = aidl::hfp::HfpEncodingTransport::instance_; auto pending_cmd = instance->GetPendingCmd(); diff --git a/system/audio_hal_interface/hfp_client_interface.h b/system/audio_hal_interface/hfp_client_interface.h index 3b512171a45..63c42c340ca 100644 --- a/system/audio_hal_interface/hfp_client_interface.h +++ b/system/audio_hal_interface/hfp_client_interface.h @@ -36,6 +36,7 @@ private: virtual void StartSession() = 0; virtual void StopSession() = 0; virtual void UpdateAudioConfigToHal(const ::hfp::offload_config& config) = 0; + virtual void UpdateAudioConfigToHal(const ::hfp::pcm_config& config) = 0; virtual void ConfirmStreamingRequest() = 0; virtual void CancelStreamingRequest() = 0; }; @@ -50,6 +51,7 @@ public: void StartSession() override; void StopSession() override; void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override; + void UpdateAudioConfigToHal(const ::hfp::pcm_config& config) override; void ConfirmStreamingRequest() override; void CancelStreamingRequest() override; size_t Write(const uint8_t* p_buf, uint32_t len); @@ -63,6 +65,7 @@ public: void StartSession() override; void StopSession() override; void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override; + void UpdateAudioConfigToHal(const ::hfp::pcm_config& config) override; void ConfirmStreamingRequest() override; void CancelStreamingRequest() override; size_t Read(uint8_t* p_buf, uint32_t len); @@ -76,6 +79,7 @@ public: void StartSession() override; void StopSession() override; void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override; + void UpdateAudioConfigToHal(const ::hfp::pcm_config& config) override; void ConfirmStreamingRequest() override; void CancelStreamingRequest() override; std::unordered_map GetHfpScoConfig(); diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index 13c76de33c3..eb858adcc98 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -127,6 +127,22 @@ static const char* bta_ag_sco_state_str(uint8_t state) { } } +static int codec_uuid_to_sample_rate(tBTA_AG_UUID_CODEC codec) { + int sample_rate; + switch (codec) { + case tBTA_AG_UUID_CODEC::UUID_CODEC_LC3: + sample_rate = 32000; + break; + case tBTA_AG_UUID_CODEC::UUID_CODEC_MSBC: + sample_rate = 16000; + break; + case tBTA_AG_UUID_CODEC::UUID_CODEC_CVSD: + default: + sample_rate = 8000; + } + return sample_rate; +} + /** * Check if bd_addr is the current active device. * @@ -1426,18 +1442,21 @@ void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) { is_controller_codec = sco_config_map[p_scb->inuse_codec].useControllerCodec; } - hfp::offload_config config{ - .sco_codec = p_scb->inuse_codec, - .connection_handle = p_scb->conn_handle, - .is_controller_codec = is_controller_codec, - .is_nrec = p_scb->nrec_enabled, - }; if (hfp_software_datapath_enabled) { if (hfp_encode_interface) { + int sample_rate = codec_uuid_to_sample_rate(p_scb->inuse_codec); + hfp::pcm_config config{.sample_rate_hz = sample_rate}; hfp_encode_interface->UpdateAudioConfigToHal(config); hfp_decode_interface->UpdateAudioConfigToHal(config); } } else { + hfp::offload_config config{ + .sco_codec = p_scb->inuse_codec, + .connection_handle = p_scb->conn_handle, + .is_controller_codec = is_controller_codec, + .is_nrec = p_scb->nrec_enabled, + }; + hfp_offload_interface->UpdateAudioConfigToHal(config); } diff --git a/system/bta/include/bta_ag_api.h b/system/bta/include/bta_ag_api.h index 36b77d76d3f..04c5b66eac5 100644 --- a/system/bta/include/bta_ag_api.h +++ b/system/bta/include/bta_ag_api.h @@ -293,9 +293,9 @@ typedef uint16_t tBTA_AG_PEER_CODEC; #define BTA_AG_AT_MAX_LEN 256 #endif -// Define hfp offload config structure namespace hfp { +// Define hfp offload config structure struct offload_config { tBTA_AG_UUID_CODEC sco_codec; int32_t connection_handle; @@ -303,6 +303,15 @@ struct offload_config { bool is_nrec; }; +// Define hfp pcm config structure +struct pcm_config { + int sample_rate_hz; + // The below fields are always fixed + // int channel_mode = ChannelMode::MONO; + // uint8_t bits_per_sample = 16; + // int data_interval_us = 7500; +}; + struct sco_config { int inputDataPath; int outputDataPath; -- GitLab From da9cdc0bbdbfe4ad3654d3689752be249c6df1d9 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 24 Sep 2024 01:28:14 +0000 Subject: [PATCH 040/875] HfpClientInterface: r/w logs to verbose level r/w operations are too spammy and is often not of interest. This CL changes the level from info to verbose. Bug: 349290628 Test: m com.google.android.btservices Flag: EXEMPT, trivial log level change Change-Id: I03eb0c6ab1312f34ad7e64c9099d359245f269e9 --- system/audio_hal_interface/hfp_client_interface.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index 51c80efab8f..52963a11e3e 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -187,7 +187,7 @@ size_t HfpClientInterface::Decode::Write(const uint8_t* p_buf, uint32_t len) { log::warn("Unsupported HIDL or AIDL version"); return 0; } - log::info("decode"); + log::verbose("decode"); return get_decode_client_interface()->WriteAudioData(p_buf, len); } @@ -348,7 +348,7 @@ size_t HfpClientInterface::Encode::Read(uint8_t* p_buf, uint32_t len) { log::warn("Unsupported HIDL or AIDL version"); return 0; } - log::info("encode"); + log::verbose("encode"); return get_encode_client_interface()->ReadAudioData(p_buf, len); } -- GitLab From e3a7961f07f400cabd3e55c78a6fe47e4be2ee83 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 16 Sep 2024 06:57:49 +0000 Subject: [PATCH 041/875] HfpClientInterface: allow uni-directional audio stream on SCO In some cases (e.g., on start-suspend transient states), there could be only one direction of active audio stream, and either of the r/w is not allowed. In this CL, we capture the precise state of the active directions, and make the streams appear to be active to the lower layers that assume both are always active. Test: verify BT audio works Test: m Bluetooth Bug: 349290628 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio and HFP and bluetooth.hfp.software_datapath.enabled Change-Id: Ide1006b016c94960d5e869b5b48c85d3e3a7754f --- .../aidl/hfp_client_interface_aidl.cc | 34 +++++++++++++++- .../aidl/hfp_client_interface_aidl.h | 10 +++++ .../hfp_client_interface.cc | 18 ++++++++- .../hfp_client_interface_unittest.cc | 40 +++++++++++++++++++ 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc index 67082b85de6..8d3b7114cbd 100644 --- a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc @@ -18,6 +18,7 @@ #include "hfp_client_interface_aidl.h" #include +#include #include @@ -70,11 +71,19 @@ std::unordered_map HfpTransport::GetHfpSc return providerInfo->GetHfpScoConfig(); } -HfpTransport::HfpTransport() { hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; } +bool HfpTransport::IsStreamActive() { return is_stream_active; } + +void HfpTransport::SetStreamActive(bool active) { is_stream_active = active; } + +HfpTransport::HfpTransport() { + hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; + is_stream_active = false; +} BluetoothAudioCtrlAck HfpTransport::StartRequest() { if (hfp_pending_cmd_ == HFP_CTRL_CMD_START) { log::info("HFP_CTRL_CMD_START in progress"); + is_stream_active = true; return BluetoothAudioCtrlAck::PENDING; } else if (hfp_pending_cmd_ != HFP_CTRL_CMD_NONE) { log::warn("busy in pending_cmd={}", hfp_pending_cmd_); @@ -88,6 +97,7 @@ BluetoothAudioCtrlAck HfpTransport::StartRequest() { if (bta_ag_sco_is_open(cb)) { // Already started, ACK back immediately. + is_stream_active = true; return BluetoothAudioCtrlAck::SUCCESS_FINISHED; } @@ -105,11 +115,15 @@ BluetoothAudioCtrlAck HfpTransport::StartRequest() { if (ctrl_ack->second != BluetoothAudioCtrlAck::SUCCESS_FINISHED) { return ctrl_ack->second; } + is_stream_active = true; return BluetoothAudioCtrlAck::PENDING; } void HfpTransport::StopRequest() { log::info("handling"); + + is_stream_active = false; + RawAddress addr = bta_ag_get_active_device(); if (addr.IsEmpty()) { log::error("No active device found"); @@ -180,6 +194,13 @@ BluetoothAudioCtrlAck HfpDecodingTransport::StartRequest(bool is_low_latency) { } BluetoothAudioCtrlAck HfpDecodingTransport::SuspendRequest() { + transport_->SetStreamActive(false); + + if (HfpEncodingTransport::instance_ && HfpEncodingTransport::instance_->IsStreamActive()) { + log::info("SCO will suspend when encoding transport suspends."); + return BluetoothAudioCtrlAck::SUCCESS_FINISHED; + } + return transport_->SuspendRequest(); } @@ -212,6 +233,8 @@ uint8_t HfpDecodingTransport::GetPendingCmd() const { return transport_->GetPend void HfpDecodingTransport::ResetPendingCmd() { transport_->ResetPendingCmd(); } +bool HfpDecodingTransport::IsStreamActive() { return transport_->IsStreamActive(); } + void HfpDecodingTransport::StopRequest() { transport_->StopRequest(); } HfpEncodingTransport::HfpEncodingTransport(SessionType session_type) @@ -226,6 +249,13 @@ BluetoothAudioCtrlAck HfpEncodingTransport::StartRequest(bool is_low_latency) { } BluetoothAudioCtrlAck HfpEncodingTransport::SuspendRequest() { + transport_->SetStreamActive(false); + + if (HfpDecodingTransport::instance_ && HfpDecodingTransport::instance_->IsStreamActive()) { + log::info("SCO will suspend when decoding transport suspends."); + return BluetoothAudioCtrlAck::SUCCESS_FINISHED; + } + return transport_->SuspendRequest(); } @@ -260,6 +290,8 @@ uint8_t HfpEncodingTransport::GetPendingCmd() const { return transport_->GetPend void HfpEncodingTransport::ResetPendingCmd() { transport_->ResetPendingCmd(); } +bool HfpEncodingTransport::IsStreamActive() { return transport_->IsStreamActive(); } + } // namespace hfp } // namespace aidl } // namespace audio diff --git a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.h b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.h index 8a34b0e10bb..5dbf8ad5943 100644 --- a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.h +++ b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.h @@ -74,8 +74,14 @@ public: static std::unordered_map GetHfpScoConfig( SessionType sessionType); + bool IsStreamActive(); + + void SetStreamActive(bool active); + private: tHFP_CTRL_CMD hfp_pending_cmd_; + + bool is_stream_active; }; // Source transport implementation @@ -108,6 +114,8 @@ public: void ResetPendingCmd(); + bool IsStreamActive(); + static inline HfpDecodingTransport* instance_ = nullptr; static inline BluetoothAudioSourceClientInterface* software_hal_interface = nullptr; static inline BluetoothAudioSourceClientInterface* offloading_hal_interface = nullptr; @@ -146,6 +154,8 @@ public: void ResetPendingCmd(); + bool IsStreamActive(); + static inline HfpEncodingTransport* instance_ = nullptr; static inline BluetoothAudioSinkClientInterface* software_hal_interface = nullptr; static inline BluetoothAudioSinkClientInterface* offloading_hal_interface = nullptr; diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index 52963a11e3e..9b53a6ca447 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -188,7 +188,13 @@ size_t HfpClientInterface::Decode::Write(const uint8_t* p_buf, uint32_t len) { return 0; } log::verbose("decode"); - return get_decode_client_interface()->WriteAudioData(p_buf, len); + + auto instance = aidl::hfp::HfpDecodingTransport::instance_; + if (instance->IsStreamActive()) { + return get_decode_client_interface()->WriteAudioData(p_buf, len); + } + + return len; } void HfpClientInterface::Decode::ConfirmStreamingRequest() { @@ -349,7 +355,15 @@ size_t HfpClientInterface::Encode::Read(uint8_t* p_buf, uint32_t len) { return 0; } log::verbose("encode"); - return get_encode_client_interface()->ReadAudioData(p_buf, len); + + auto instance = aidl::hfp::HfpEncodingTransport::instance_; + if (instance->IsStreamActive()) { + return get_encode_client_interface()->ReadAudioData(p_buf, len); + } + + memset(p_buf, 0x00, len); + + return len; } void HfpClientInterface::Encode::ConfirmStreamingRequest() { diff --git a/system/audio_hal_interface/hfp_client_interface_unittest.cc b/system/audio_hal_interface/hfp_client_interface_unittest.cc index fa1d87a1a56..f3be28ec64a 100644 --- a/system/audio_hal_interface/hfp_client_interface_unittest.cc +++ b/system/audio_hal_interface/hfp_client_interface_unittest.cc @@ -131,6 +131,9 @@ std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) { r namespace hfp { +static bool encoding_transport_is_stream_active_ret; +static bool decoding_transport_is_stream_active_ret; + HfpTransport::HfpTransport() {} BluetoothAudioCtrlAck HfpTransport::StartRequest() { return BluetoothAudioCtrlAck::SUCCESS_FINISHED; @@ -180,6 +183,7 @@ void HfpDecodingTransport::LogBytesWritten(size_t bytes_written) {} uint8_t HfpDecodingTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; } void HfpDecodingTransport::ResetPendingCmd() {} void HfpDecodingTransport::StopRequest() {} +bool HfpDecodingTransport::IsStreamActive() { return decoding_transport_is_stream_active_ret; } HfpEncodingTransport::HfpEncodingTransport(SessionType session_type) : IBluetoothSinkTransportInstance(session_type, (AudioConfiguration){}) {} @@ -204,6 +208,7 @@ void HfpEncodingTransport::ResetPresentationPosition() {} void HfpEncodingTransport::LogBytesRead(size_t bytes_written) {} uint8_t HfpEncodingTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; } void HfpEncodingTransport::ResetPendingCmd() {} +bool HfpEncodingTransport::IsStreamActive() { return encoding_transport_is_stream_active_ret; } } // namespace hfp } // namespace aidl @@ -241,6 +246,8 @@ protected: init_message_loop_thread(); sink_client_read_called = false; source_client_write_called = false; + bluetooth::audio::aidl::hfp::encoding_transport_is_stream_active_ret = true; + bluetooth::audio::aidl::hfp::decoding_transport_is_stream_active_ret = true; } virtual void TearDown() override { cleanup_message_loop_thread(); } @@ -259,6 +266,24 @@ TEST_F(HfpClientInterfaceTest, InitEncodeInterfaceAndRead) { HfpClientInterface::Get()->ReleaseEncode(encode_); } +TEST_F(HfpClientInterfaceTest, InitEncodeInterfaceAndReadWhenStreamInactive) { + uint8_t data[48]; + data[0] = 0xab; + + HfpClientInterface::Encode* encode_ = nullptr; + + bluetooth::audio::aidl::hfp::encoding_transport_is_stream_active_ret = false; + + encode_ = HfpClientInterface::Get()->GetEncode(&message_loop_thread); + ASSERT_NE(nullptr, encode_); + + encode_->Read(data, 48); + ASSERT_EQ(0, sink_client_read_called); + ASSERT_EQ(0x00, data[0]); + + HfpClientInterface::Get()->ReleaseEncode(encode_); +} + TEST_F(HfpClientInterfaceTest, InitDecodeInterfaceAndWrite) { uint8_t data[48]; HfpClientInterface::Decode* decode_ = nullptr; @@ -272,4 +297,19 @@ TEST_F(HfpClientInterfaceTest, InitDecodeInterfaceAndWrite) { HfpClientInterface::Get()->ReleaseDecode(decode_); } +TEST_F(HfpClientInterfaceTest, InitDecodeInterfaceAndWriteWhenStreamInactive) { + uint8_t data[48]; + + HfpClientInterface::Decode* decode_ = nullptr; + + bluetooth::audio::aidl::hfp::decoding_transport_is_stream_active_ret = false; + + decode_ = HfpClientInterface::Get()->GetDecode(&message_loop_thread); + ASSERT_NE(nullptr, decode_); + + decode_->Write(data, 48); + ASSERT_EQ(0, source_client_write_called); + + HfpClientInterface::Get()->ReleaseDecode(decode_); +} } // namespace -- GitLab From 4c16fc6dcc86f621118f21136fcc877e2412e0b2 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Tue, 24 Sep 2024 18:13:31 +0800 Subject: [PATCH 042/875] hh: Don't send SET IDLE SET IDLE command is deprecated in HID spec v1.1.1 (adopted in 2015). Furthermore, this might race with the reply of GET REPORT or other commands from UHID. Therefore, let's not send this command. Bug: 307923455 Bug: 369310847 Test: m -j Test: Pair with a Keychron KB and plug in a security key. Verify the security key is usable. Flag: com.android.bluetooth.flags.dont_send_hid_set_idle Change-Id: I984a67a4203edb4564b48da3c74343bc86e65ebc --- system/btif/src/btif_hh.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index f7983d3c2db..3d3b169c906 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -637,10 +637,14 @@ static void hh_open_handler(tBTA_HH_CONN& conn) { p_dev->dev_status = BTHH_CONN_STATE_CONNECTED; } hh_connect_complete(conn, BTHH_CONN_STATE_CONNECTED); - // Send set_idle if the peer_device is a keyboard - if (check_cod_hid_major(conn.link_spec.addrt.bda, COD_HID_KEYBOARD) || - check_cod_hid_major(conn.link_spec.addrt.bda, COD_HID_COMBO)) { - BTA_HhSetIdle(conn.handle, 0); + + if (!com::android::bluetooth::flags::dont_send_hid_set_idle()) { + // Send set_idle if the peer_device is a keyboard + // TODO (b/307923455): clean this, set idle is deprecated in HID spec v1.1.1 + if (check_cod_hid_major(conn.link_spec.addrt.bda, COD_HID_KEYBOARD) || + check_cod_hid_major(conn.link_spec.addrt.bda, COD_HID_COMBO)) { + BTA_HhSetIdle(conn.handle, 0); + } } BTA_HhGetDscpInfo(conn.handle); } -- GitLab From 31eca2cc6273a50763bd0c96288f7a24bd87eeeb Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Fri, 20 Sep 2024 15:33:56 +0800 Subject: [PATCH 043/875] floss: Connect to newly discovered profiles if it is user initiated It's possible for some devices to announce a different subset of profiles on the inquiry result, advertisement, and SDP. Currently our "connect to all profiles" might not perform as expected because by the time we finish connecting to all profiles, a new profile might be discovered via another means. Therefore, update the connection logic to always connect to newly discovered profiles if "connect to all profiles" was invoked. Bug: 352632969 Test: m -j Test: autotest Flag: EXEMPT, floss only changes Change-Id: I68a12efab78af901eb1f5e35abeb9ac5da7db8ff --- system/gd/rust/linux/stack/src/bluetooth.rs | 360 +++++++++++--------- 1 file changed, 197 insertions(+), 163 deletions(-) diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index 2ac72988c38..d65c85458ce 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -316,6 +316,9 @@ pub enum DelayedActions { /// Connect to all supported profiles on target device. ConnectAllProfiles(BluetoothDevice), + /// Connect to the specified profiles on target device. + ConnectProfiles(Vec, BluetoothDevice), + /// Scanner for BLE discovery is registered with given status and scanner id. BleDiscoveryScannerRegistered(Uuid, u8, GattStatus), @@ -373,12 +376,9 @@ struct BluetoothDeviceContext { pub last_seen: Instant, pub properties: HashMap, - /// Keep track of whether services have been resolved. - pub services_resolved: bool, - - /// If supported UUIDs weren't available in EIR, wait for services to be - /// resolved to connect. - pub wait_to_connect: bool, + /// If user wants to connect to all profiles, when new profiles are discovered we will also try + /// to connect them. + pub connect_to_new_profiles: bool, } impl BluetoothDeviceContext { @@ -398,8 +398,7 @@ impl BluetoothDeviceContext { info, last_seen, properties: HashMap::new(), - services_resolved: false, - wait_to_connect: false, + connect_to_new_profiles: false, }; device.update_properties(&properties); device @@ -1104,6 +1103,10 @@ impl Bluetooth { self.connect_all_enabled_profiles(device); } + DelayedActions::ConnectProfiles(uuids, device) => { + self.connect_profiles_internal(&uuids, device); + } + DelayedActions::BleDiscoveryScannerRegistered(uuid, scanner_id, status) => { if let Some(app_uuid) = self.ble_scanner_uuid { if app_uuid == uuid { @@ -1140,6 +1143,10 @@ impl Bluetooth { }; let device_info = BluetoothDevice::from_properties(&properties); + self.check_new_property_and_potentially_connect_profiles( + result.address, + &properties, + ); self.remote_devices .entry(device_info.address) @@ -1285,6 +1292,177 @@ impl Bluetooth { || self.active_pairing_address.is_some() || self.pending_create_bond.is_some() } + + /// Checks whether the list of device properties contains some UUID we should connect now + /// This function also connects those UUIDs. + fn check_new_property_and_potentially_connect_profiles( + &self, + addr: RawAddress, + properties: &Vec, + ) { + // Return early if no need to connect new profiles + if !self.remote_devices.get(&addr).map_or(false, |d| d.connect_to_new_profiles) { + return; + } + + // Get the reported UUIDs, if any. Otherwise return early. + let mut new_uuids: Vec = vec![]; + for prop in properties.iter() { + if let BluetoothProperty::Uuids(value) = prop { + new_uuids.extend(value); + } + } + if new_uuids.is_empty() { + return; + } + + // Only connect if the UUID is not seen before and it's supported + let device = BluetoothDevice::new(addr, "".to_string()); + let current_uuids = self.get_remote_uuids(device.clone()); + new_uuids.retain(|uuid| !current_uuids.contains(uuid)); + + let profile_known_and_supported = new_uuids.iter().any(|uuid| { + if let Some(profile) = UuidHelper::is_known_profile(uuid) { + return UuidHelper::is_profile_supported(&profile); + } + return false; + }); + if !profile_known_and_supported { + return; + } + + log::info!("[{}]: Connecting to newly discovered profiles", DisplayAddress(&addr)); + let tx = self.tx.clone(); + tokio::spawn(async move { + let _ = tx + .send(Message::DelayedAdapterActions(DelayedActions::ConnectProfiles( + new_uuids, device, + ))) + .await; + }); + } + + /// Connect these profiles of a peripheral device + fn connect_profiles_internal(&mut self, uuids: &Vec, device: BluetoothDevice) { + let addr = device.address; + if !self.get_acl_state_by_addr(&addr) { + // log ACL connection attempt if it's not already connected. + metrics::acl_connect_attempt(addr, BtAclState::Connected); + // Pause discovery before connecting, or the ACL connection request may conflict with + // the ongoing inquiry. + self.pause_discovery(); + } + + let mut has_supported_profile = false; + let mut has_le_media_profile = false; + let mut has_classic_media_profile = false; + + for uuid in uuids.iter() { + match UuidHelper::is_known_profile(uuid) { + Some(p) => { + if UuidHelper::is_profile_supported(&p) { + match p { + Profile::Hid | Profile::Hogp => { + has_supported_profile = true; + // TODO(b/328675014): Use BtAddrType + // and BtTransport from + // BluetoothDevice instead of default + let status = self.hh.as_ref().unwrap().connect( + &mut addr.clone(), + BtAddrType::Public, + BtTransport::Auto, + ); + metrics::profile_connection_state_changed( + addr, + p as u32, + BtStatus::Success, + BthhConnectionState::Connecting as u32, + ); + + if status != BtStatus::Success { + metrics::profile_connection_state_changed( + addr, + p as u32, + status, + BthhConnectionState::Disconnected as u32, + ); + } + } + + // TODO(b/317682584): implement policy to connect to LEA, VC, and CSIS + Profile::LeAudio | Profile::VolumeControl | Profile::CoordinatedSet + if !has_le_media_profile => + { + has_le_media_profile = true; + let txl = self.tx.clone(); + topstack::get_runtime().spawn(async move { + let _ = txl + .send(Message::Media( + MediaActions::ConnectLeaGroupByMemberAddress(addr), + )) + .await; + }); + } + + Profile::A2dpSink | Profile::A2dpSource | Profile::Hfp + if !has_classic_media_profile => + { + has_supported_profile = true; + has_classic_media_profile = true; + let txl = self.tx.clone(); + topstack::get_runtime().spawn(async move { + let _ = + txl.send(Message::Media(MediaActions::Connect(addr))).await; + }); + } + + Profile::Bas => { + has_supported_profile = true; + let tx = self.tx.clone(); + let device_context = match self.remote_devices.get(&addr) { + Some(context) => context, + None => continue, + }; + + let acl_state = device_context.ble_acl_state.clone(); + let bond_state = device_context.bond_state.clone(); + let device_to_send = device.clone(); + + let transport = match self.get_remote_type(device.clone()) { + BtDeviceType::Bredr => BtTransport::Bredr, + BtDeviceType::Ble => BtTransport::Le, + _ => device_context.acl_reported_transport.clone(), + }; + topstack::get_runtime().spawn(async move { + let _ = tx + .send(Message::BatteryService( + BatteryServiceActions::Connect( + device_to_send, + acl_state, + bond_state, + transport, + ), + )) + .await; + }); + } + + // We don't connect most profiles + _ => (), + } + } + } + _ => {} + } + } + + // If the device does not have a profile that we are interested in connecting to, resume + // discovery now. Other cases will be handled in the ACL connection state or bond state + // callbacks. + if !has_supported_profile { + self.resume_discovery(); + } + } } #[btif_callbacks_dispatcher(dispatch_base_callbacks, BaseCallbacks)] @@ -1576,6 +1754,7 @@ impl BtifBluetoothCallbacks for Bluetooth { fn device_found(&mut self, _n: i32, properties: Vec) { let device_info = BluetoothDevice::from_properties(&properties); + self.check_new_property_and_potentially_connect_profiles(device_info.address, &properties); let device_info = self .remote_devices @@ -1760,7 +1939,6 @@ impl BtifBluetoothCallbacks for Bluetooth { let device_info = device.info.clone(); // Since this is a newly bonded device, we also need to trigger SDP on it. - device.services_resolved = false; self.fetch_remote_uuids(device_info.clone()); if self.get_wake_allowed_device_bonded() { self.create_uhid_for_suspend_wakesource(); @@ -1821,8 +1999,7 @@ impl BtifBluetoothCallbacks for Bluetooth { _num_properties: i32, properties: Vec, ) { - let txl = self.tx.clone(); - + self.check_new_property_and_potentially_connect_profiles(addr, &properties); let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtAclState::Disconnected, @@ -1839,30 +2016,6 @@ impl BtifBluetoothCallbacks for Bluetooth { let info = device.info.clone(); - if !device.services_resolved { - let has_uuids = properties.iter().any(|prop| match prop { - BluetoothProperty::Uuids(uu) => !uu.is_empty(), - _ => false, - }); - - // Services are resolved when uuids are fetched. - device.services_resolved |= has_uuids; - } - - if device.wait_to_connect && device.services_resolved { - device.wait_to_connect = false; - - let sent_info = info.clone(); - let tx = txl.clone(); - tokio::spawn(async move { - let _ = tx - .send(Message::DelayedAdapterActions(DelayedActions::ConnectAllProfiles( - sent_info, - ))) - .await; - }); - } - self.callbacks.for_all_callbacks(|callback| { callback.on_device_properties_changed( info.clone(), @@ -1971,6 +2124,7 @@ impl BtifBluetoothCallbacks for Bluetooth { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_disconnected(info.clone()); }); + device.connect_to_new_profiles = false; } tokio::spawn(async move { let _ = txl.send(Message::OnDeviceDisconnected(info)).await; @@ -2617,138 +2771,14 @@ impl IBluetooth for Bluetooth { if !self.profiles_ready { return BtStatus::NotReady; } - let addr = device.address; - - if !self.get_acl_state_by_addr(&addr) { - // log ACL connection attempt if it's not already connected. - metrics::acl_connect_attempt(addr, BtAclState::Connected); - // Pause discovery before connecting, or the ACL connection request may conflict with - // the ongoing inquiry. - self.pause_discovery(); - } // Check all remote uuids to see if they match enabled profiles and connect them. - let mut has_enabled_uuids = false; - let mut has_classic_media_profile = false; - let mut has_le_media_profile = false; - let mut has_supported_profile = false; let uuids = self.get_remote_uuids(device.clone()); - for uuid in uuids.iter() { - match UuidHelper::is_known_profile(uuid) { - Some(p) => { - if UuidHelper::is_profile_supported(&p) { - match p { - Profile::Hid | Profile::Hogp => { - has_supported_profile = true; - // TODO(b/328675014): Use BtAddrType - // and BtTransport from - // BluetoothDevice instead of default - let status = self.hh.as_ref().unwrap().connect( - &mut addr.clone(), - BtAddrType::Public, - BtTransport::Auto, - ); - metrics::profile_connection_state_changed( - addr, - p as u32, - BtStatus::Success, - BthhConnectionState::Connecting as u32, - ); + self.connect_profiles_internal(&uuids, device.clone()); - if status != BtStatus::Success { - metrics::profile_connection_state_changed( - addr, - p as u32, - status, - BthhConnectionState::Disconnected as u32, - ); - } - } - - // TODO(b/317682584): implement policy to connect to LEA, VC, and CSIS - Profile::LeAudio | Profile::VolumeControl | Profile::CoordinatedSet - if !has_le_media_profile => - { - has_le_media_profile = true; - let txl = self.tx.clone(); - topstack::get_runtime().spawn(async move { - let _ = txl - .send(Message::Media( - MediaActions::ConnectLeaGroupByMemberAddress(addr), - )) - .await; - }); - } - - Profile::A2dpSink | Profile::A2dpSource | Profile::Hfp - if !has_classic_media_profile => - { - has_supported_profile = true; - has_classic_media_profile = true; - let txl = self.tx.clone(); - topstack::get_runtime().spawn(async move { - let _ = - txl.send(Message::Media(MediaActions::Connect(addr))).await; - }); - } - - Profile::Bas => { - has_supported_profile = true; - let tx = self.tx.clone(); - let device_context = match self.remote_devices.get(&addr) { - Some(context) => context, - None => return BtStatus::RemoteDeviceDown, - }; - - let acl_state = device_context.ble_acl_state.clone(); - let bond_state = device_context.bond_state.clone(); - let device_to_send = device.clone(); - - let transport = match self.get_remote_type(device.clone()) { - BtDeviceType::Bredr => BtTransport::Bredr, - BtDeviceType::Ble => BtTransport::Le, - _ => device_context.acl_reported_transport.clone(), - }; - topstack::get_runtime().spawn(async move { - let _ = tx - .send(Message::BatteryService( - BatteryServiceActions::Connect( - device_to_send, - acl_state, - bond_state, - transport, - ), - )) - .await; - }); - } - - // We don't connect most profiles - _ => (), - } - } - has_enabled_uuids = true; - } - _ => {} - } - } - - // If SDP isn't completed yet, we wait for it to complete and retry the connection again. - // Otherwise, this connection request is done, no retry is required. - if !has_enabled_uuids { - warn!("[{}] SDP hasn't completed for device, wait to connect.", DisplayAddress(&addr)); - if let Some(d) = self.remote_devices.get_mut(&addr) { - if uuids.is_empty() || !d.services_resolved { - d.wait_to_connect = true; - } - } - } - - // If the SDP has not been completed or the device does not have a profile that we are - // interested in connecting to, resume discovery now. Other cases will be handled in the - // ACL connection state or bond state callbacks. - if !has_enabled_uuids || !has_supported_profile { - self.resume_discovery(); + // Also connect to profiles discovered in the future. + if let Some(d) = self.remote_devices.get_mut(&device.address) { + d.connect_to_new_profiles = true; } BtStatus::Success @@ -2853,6 +2883,10 @@ impl IBluetooth for Bluetooth { let _ = txl.send(Message::GattActions(GattActions::Disconnect(device))).await; }); + if let Some(d) = self.remote_devices.get_mut(&addr) { + d.connect_to_new_profiles = false; + } + true } -- GitLab From a5220ba2c458731df40b6831e357b0b02cb98ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Ko=C5=82odziejczyk?= Date: Wed, 25 Sep 2024 12:42:55 +0000 Subject: [PATCH 044/875] broadcaster: Update terminate BIG reason Exposed termination reason should represent broadcast sink perspective. Bug: 367986627 Test: atest bluetooth_test_broadcaster Flag: Exempt; trivial change Change-Id: Ied8d4d0de404c1f62605c9e2c61386ec238f6fab --- system/bta/le_audio/broadcaster/state_machine.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/bta/le_audio/broadcaster/state_machine.cc b/system/bta/le_audio/broadcaster/state_machine.cc index d4176e26f81..07c258683a2 100644 --- a/system/bta/le_audio/broadcaster/state_machine.cc +++ b/system/bta/le_audio/broadcaster/state_machine.cc @@ -422,8 +422,8 @@ private: void TerminateBig() { log::info("disabling={}", GetState() == BroadcastStateMachine::State::DISABLING); - /* Terminate with reason: Connection Terminated By Local Host */ - IsoManager::GetInstance()->TerminateBig(GetAdvertisingSid(), 0x16); + /* Terminate with reason: Remote User Terminated Connection */ + IsoManager::GetInstance()->TerminateBig(GetAdvertisingSid(), 0x13); } void OnSetupIsoDataPath(uint8_t status, uint16_t conn_hdl) override { -- GitLab From 59f1cf2744c58a13b1dfdcd58e4647c444a0e65a Mon Sep 17 00:00:00 2001 From: shihchienc Date: Wed, 25 Sep 2024 03:43:35 +0000 Subject: [PATCH 045/875] leaudio: replace magic number use GetBitsPerSample() instead of 16 Bug: 369469066 Test: atest bluetooth_le_audio_client_test bluetooth_le_audio_test bluetooth_le_audio_codec_manager_test Flag: EXEMPT, no-op change Change-Id: I0eaaccfd5c5481e7018dc3a65253976bccf1ee0d --- system/bta/le_audio/codec_manager.cc | 4 ++-- system/bta/le_audio/le_audio_types_test.cc | 18 ++++++++++++++++++ system/bta/le_audio/le_audio_utils.cc | 3 ++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index aedf5f244d6..d59ed996e4d 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -926,7 +926,6 @@ private: conf.codec.id.coding_format, conf.codec.GetSamplingFrequencyHz(), conf.codec.GetDataIntervalUs(), conf.codec.GetChannelCountPerIsoStream()); - /* TODO: How to get bits_per_sample ? */ btle_audio_codec_config_t capa_to_add = { .codec_type = (conf.codec.id.coding_format == types::kLeAudioCodingFormatLC3) @@ -934,7 +933,8 @@ private: : btle_audio_codec_index_t::LE_AUDIO_CODEC_INDEX_SOURCE_INVALID, .sample_rate = utils::translateToBtLeAudioCodecConfigSampleRate( conf.codec.GetSamplingFrequencyHz()), - .bits_per_sample = utils::translateToBtLeAudioCodecConfigBitPerSample(16), + .bits_per_sample = utils::translateToBtLeAudioCodecConfigBitPerSample( + conf.codec.GetBitsPerSample()), .channel_count = utils::translateToBtLeAudioCodecConfigChannelCount( conf.codec.GetChannelCountPerIsoStream()), .frame_duration = utils::translateToBtLeAudioCodecConfigFrameDuration( diff --git a/system/bta/le_audio/le_audio_types_test.cc b/system/bta/le_audio/le_audio_types_test.cc index f46da64e26f..70c29426ef9 100644 --- a/system/bta/le_audio/le_audio_types_test.cc +++ b/system/bta/le_audio/le_audio_types_test.cc @@ -22,6 +22,8 @@ #include +#include "le_audio_utils.h" + namespace bluetooth::le_audio { namespace types { @@ -822,5 +824,21 @@ TEST(CodecSpecTest, test_channel_count_transition) { codec_spec_caps::kLeAudioCodecChannelCountEightChannel); } +TEST(CodecConfigTest, test_lc3_bits_per_sample) { + set_configurations::CodecConfigSetting lc3_codec_config = { + .id = {.coding_format = types::kLeAudioCodingFormatLC3}, + }; + ASSERT_EQ(utils::translateToBtLeAudioCodecConfigBitPerSample(lc3_codec_config.GetBitsPerSample()), + LE_AUDIO_BITS_PER_SAMPLE_INDEX_16); +} + +TEST(CodecConfigTest, test_invalid_codec_bits_per_sample) { + set_configurations::CodecConfigSetting invalid_codec_config = { + .id = {.coding_format = types::kLeAudioCodingFormatVendorSpecific}}; + ASSERT_EQ(utils::translateToBtLeAudioCodecConfigBitPerSample( + invalid_codec_config.GetBitsPerSample()), + LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE); +} + } // namespace types } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/le_audio_utils.cc b/system/bta/le_audio/le_audio_utils.cc index 80adf4b87e5..2e29fd1e030 100644 --- a/system/bta/le_audio/le_audio_utils.cc +++ b/system/bta/le_audio/le_audio_utils.cc @@ -334,7 +334,8 @@ void fillStreamParamsToBtLeAudioCodecConfig( out_config.sample_rate = translateToBtLeAudioCodecConfigSampleRate(config.GetSamplingFrequencyHz()); - out_config.bits_per_sample = translateToBtLeAudioCodecConfigBitPerSample(16); + out_config.bits_per_sample = + translateToBtLeAudioCodecConfigBitPerSample(config.GetBitsPerSample()); out_config.frame_duration = translateToBtLeAudioCodecConfigFrameDuration(config.GetDataIntervalUs()); out_config.octets_per_frame = config.GetOctetsPerFrame(); -- GitLab From bee0353c2995a6197a85e3eeb1e10cde3aab643f Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 25 Sep 2024 11:32:46 -0700 Subject: [PATCH 046/875] Relax the check for the error code in bta_av_setconfig_rej Use the default error code AVDT_ERR_UNSUP_CFG when not set, rather than assert. Bug: 365696112 Bug: 338139069 Flag: com.android.bluetooth.flags.avdtp_error_codes Test: m com.android.btservices Change-Id: Iadae28ae7a4debb808f344cde31c7b66f26648b7 --- system/bta/av/bta_av_aact.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index b6ade3ff1d7..7cbd091f1d7 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -1766,9 +1766,11 @@ void bta_av_setconfig_rej(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { err_code = AVDT_ERR_UNSUP_CFG; } - // The error code must be set by the caller, otherwise - // AVDT_ConfigRsp will interpret the event as RSP instead of REJ. - log::assert_that(err_code != 0, "err_code != 0"); + // The error code might not be set when the configuration is rejected + // based on the current AVDTP state. + if (err_code == AVDT_SUCCESS) { + err_code = AVDT_ERR_UNSUP_CFG; + } AVDT_ConfigRsp(avdt_handle, p_scb->avdt_label, err_code, 0); -- GitLab From 22f5e11b2ef10ec011d7c290ddda8f9550abe648 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Sat, 21 Sep 2024 01:20:25 +0000 Subject: [PATCH 047/875] Enforce -Wmissing-prototypes This lint check will raise an error if a function is implemented without a corresponding prototype declaration included in scope. The main use case will be to ensure mock functions do not become out of sync causing the original function to be linked instead. Because of the large amount of errors, this change suppresses errors in all locations, to be cleaned up gradually. Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, lint fixes Change-Id: I888b5e284e237d8a6e2864bdde55c0a7fc0c348d --- Android.bp | 1 + android/app/Android.bp | 7 ++---- .../com_android_bluetooth_avrcp_target.cpp | 3 +++ ...oid_bluetooth_btservice_AdapterService.cpp | 3 +++ .../app/jni/com_android_bluetooth_gatt.cpp | 3 +++ .../jni/com_android_bluetooth_le_audio.cpp | 3 +++ system/audio/asrc/asrc_resampler_test.cc | 3 +++ system/audio_hal_interface/Android.bp | 1 + .../aidl/hfp_client_interface_aidl.cc | 3 +++ .../aidl/le_audio_software_aidl.cc | 3 +++ .../aidl/le_audio_utils.cc | 3 +++ .../audio_hal_interface/aidl/provider_info.cc | 3 +++ .../hal_version_manager.cc | 3 +++ .../hfp_client_interface.cc | 3 +++ .../hfp_client_interface_unittest.cc | 4 +++ .../hidl/client_interface_hidl_unittest.cc | 3 +++ .../audio_hal_interface/le_audio_software.cc | 3 +++ .../le_audio_software_host.cc | 3 +++ .../le_audio_software_unittest.cc | 4 +++ .../src/audio_hearing_aid_hw_utils.cc | 3 +++ system/bta/ag/bta_ag_at.cc | 3 +++ system/bta/ag/bta_ag_rfc.cc | 3 +++ system/bta/ar/bta_ar.cc | 3 +++ system/bta/av/bta_av_aact.cc | 3 +++ system/bta/av/bta_av_act.cc | 3 +++ system/bta/av/bta_av_cfg.cc | 3 +++ system/bta/av/bta_av_ci.cc | 3 +++ system/bta/csis/csis_client_test.cc | 3 +++ system/bta/dm/bta_dm_act.cc | 3 +++ system/bta/dm/bta_dm_ci.cc | 3 +++ system/bta/dm/bta_dm_device_search.cc | 3 +++ system/bta/dm/bta_dm_disc.cc | 3 +++ system/bta/dm/bta_dm_disc_sdp.cc | 3 +++ system/bta/dm/bta_dm_gatt_client.cc | 3 +++ system/bta/dm/bta_dm_pm.cc | 3 +++ system/bta/dm/bta_dm_sec.cc | 3 +++ system/bta/gatt/bta_gattc_act.cc | 3 +++ system/bta/gatt/bta_gattc_cache.cc | 3 +++ system/bta/gatt/bta_gattc_utils.cc | 3 +++ system/bta/gatt/bta_gatts_act.cc | 3 +++ system/bta/gatt/bta_gatts_api.cc | 3 +++ system/bta/gatt/database_builder.cc | 3 +++ system/bta/groups/groups_test.cc | 3 +++ system/bta/has/has_client_test.cc | 3 +++ system/bta/hf_client/bta_hf_client_at.cc | 3 +++ system/bta/hh/bta_hh_main.cc | 3 +++ system/bta/jv/bta_jv_act.cc | 3 +++ .../audio_hal_client/audio_hal_client_test.cc | 3 +++ .../le_audio/broadcaster/broadcaster_test.cc | 3 +++ .../broadcaster/state_machine_test.cc | 3 +++ system/bta/le_audio/client.cc | 3 +++ system/bta/le_audio/codec_manager_test.cc | 3 +++ system/bta/le_audio/device_groups.cc | 3 +++ system/bta/le_audio/devices.cc | 3 +++ system/bta/le_audio/devices_test.cc | 3 +++ system/bta/le_audio/le_audio_client_test.cc | 3 +++ .../le_audio/le_audio_health_status_test.cc | 3 +++ system/bta/le_audio/le_audio_types.cc | 3 +++ system/bta/le_audio/metrics_collector_test.cc | 3 +++ system/bta/le_audio/state_machine_test.cc | 3 +++ system/bta/le_audio/storage_helper.cc | 3 +++ system/bta/le_audio/storage_helper_test.cc | 3 +++ system/bta/pan/bta_pan_ci.cc | 3 +++ system/bta/pan/bta_pan_main.cc | 3 +++ system/bta/sdp/bta_sdp_act.cc | 3 +++ system/bta/test/bta_ag_sco_test.cc | 3 +++ system/bta/test/bta_av_test.cc | 3 +++ system/bta/test/bta_gatt_test.cc | 3 +++ system/bta/test/common/btif_storage_mock.cc | 3 +++ system/bta/test/common/btm_api_mock.cc | 3 +++ system/bta/vc/devices_test.cc | 3 +++ system/bta/vc/vc_test.cc | 3 +++ system/btcore/src/osi_module.cc | 3 +++ system/btcore/test/device_class_test.cc | 3 +++ system/btif/co/bta_av_co.cc | 3 +++ system/btif/co/bta_gatts_co.cc | 3 +++ system/btif/co/bta_hh_co.cc | 3 +++ system/btif/src/bluetooth.cc | 3 +++ system/btif/src/btif_a2dp_source.cc | 3 +++ system/btif/src/btif_av.cc | 3 +++ system/btif/src/btif_avrcp_audio_track.cc | 3 +++ system/btif/src/btif_ble_scanner.cc | 3 +++ system/btif/src/btif_bqr.cc | 3 +++ system/btif/src/btif_core.cc | 3 +++ system/btif/src/btif_csis_client.cc | 3 +++ system/btif/src/btif_dm.cc | 3 +++ system/btif/src/btif_gatt.cc | 3 +++ system/btif/src/btif_has_client.cc | 3 +++ system/btif/src/btif_hd.cc | 3 +++ system/btif/src/btif_hearing_aid.cc | 3 +++ system/btif/src/btif_hf.cc | 3 +++ system/btif/src/btif_hf_client.cc | 3 +++ system/btif/src/btif_hh.cc | 3 +++ system/btif/src/btif_iot_config.cc | 3 +++ system/btif/src/btif_le_audio.cc | 3 +++ system/btif/src/btif_le_audio_broadcaster.cc | 3 +++ system/btif/src/btif_pan.cc | 3 +++ system/btif/src/btif_profile_storage.cc | 3 +++ system/btif/src/btif_rc.cc | 3 +++ system/btif/src/btif_sdp.cc | 3 +++ system/btif/src/btif_sdp_server.cc | 3 +++ system/btif/src/btif_sock_l2cap.cc | 3 +++ system/btif/src/btif_sock_rfc.cc | 3 +++ system/btif/src/btif_sock_sco.cc | 3 +++ system/btif/src/btif_storage.cc | 3 +++ system/btif/src/btif_vc.cc | 3 +++ system/btif/src/stack_manager.cc | 3 +++ system/btif/test/btif_core_test.cc | 3 +++ system/btif/test/btif_profile_queue_test.cc | 3 +++ .../benchmark/thread_performance_benchmark.cc | 3 +++ system/common/metric_id_allocator_unittest.cc | 3 +++ system/common/metrics_linux.cc | 3 +++ system/common/metrics_unittest.cc | 3 +++ system/common/os_utils.cc | 3 +++ system/common/test/thread_performance_test.cc | 3 +++ system/device/fuzzer/btdevice_esco_fuzzer.cpp | 3 +++ system/device/src/interop.cc | 3 +++ system/embdrv/sbc/decoder/Android.bp | 3 +++ system/embdrv/sbc/encoder/Android.bp | 3 +++ system/gd/Android.bp | 4 +++ .../gd/common/metric_id_manager_unittest.cc | 3 +++ system/gd/common/strings_test.cc | 3 +++ system/gd/dumpsys/bundler/bundler.cc | 3 +++ system/gd/fuzz_test.cc | 3 +++ system/gd/hal/snoop_logger_test.cc | 3 +++ .../gd/hci/acl_manager/classic_impl_test.cc | 3 +++ system/gd/hci/controller_test.cc | 3 +++ .../facade/le_advertising_manager_facade.cc | 3 +++ system/gd/hci/fuzz/acl_manager_fuzz_test.cc | 3 +++ system/gd/hci/fuzz/hci_layer_fuzz_test.cc | 3 +++ system/gd/hci/hci_layer_unittest.cc | 3 +++ system/gd/hci/hci_packets_fuzz_test.cc | 3 +++ system/gd/hci/le_address_manager.cc | 3 +++ system/gd/hci/le_advertising_manager.cc | 3 +++ system/gd/metrics/bluetooth_event.cc | 3 +++ system/gd/module_gdx_unittest.cc | 3 +++ system/gd/module_jniloop_unittest.cc | 3 +++ system/gd/module_mainloop_unittest.cc | 3 +++ .../linux_generic/alarm_timerfd_unittest.cc | 3 +++ .../gd/os/linux_generic/wakelock_manager.cc | 3 +++ system/main/shim/acl.cc | 3 +++ system/main/shim/hci_layer.cc | 3 +++ system/main/test/main_shim_test.cc | 3 +++ system/osi/src/list.cc | 3 +++ system/osi/src/stack_power_telemetry.cc | 3 +++ system/osi/src/thread_scheduler.cc | 3 +++ system/osi/test/alarm_test.cc | 3 +++ system/osi/test/fuzzers/Android.bp | 3 +++ system/packet/tests/fuzzers/Android.bp | 25 +++++++++++++++++++ .../tests/fuzzers/reject_packet_fuzzer.cc | 3 +++ system/profile/avrcp/connection_handler.cc | 3 +++ system/profile/avrcp/device.cc | 3 +++ .../tests/avrcp_connection_handler_test.cc | 3 +++ .../avrcp_device_fuzz/avrcp_device_fuzz.cc | 3 +++ .../profile/avrcp/tests/avrcp_device_test.cc | 3 +++ .../common/test/data_element_reader_test.cc | 3 +++ system/rust/Android.bp | 4 +++ system/stack/Android.bp | 11 +++----- system/stack/acl/ble_acl.cc | 3 +++ system/stack/acl/btm_acl.cc | 3 +++ system/stack/acl/btm_pm.cc | 3 +++ system/stack/ais/ais_ble.cc | 3 +++ system/stack/avdt/avdt_msg.cc | 3 +++ system/stack/avdt/avdt_scb_act.cc | 3 +++ system/stack/avrc/avrc_api.cc | 3 +++ system/stack/avrc/avrc_bld_tg.cc | 3 +++ system/stack/avrc/avrc_pars_ct.cc | 3 +++ system/stack/bnep/bnep_utils.cc | 3 +++ system/stack/btm/btm_ble.cc | 3 +++ system/stack/btm/btm_ble_gap.cc | 3 +++ system/stack/btm/btm_ble_privacy.cc | 3 +++ system/stack/btm/btm_ble_sec.cc | 3 +++ system/stack/btm/btm_dev.cc | 3 +++ system/stack/btm/btm_devctl.cc | 3 +++ system/stack/btm/btm_inq.cc | 3 +++ system/stack/btm/btm_iot_config.cc | 3 +++ system/stack/btm/btm_main.cc | 3 +++ system/stack/btm/btm_sco.cc | 3 +++ system/stack/btm/btm_sec.cc | 3 +++ system/stack/btu/btu_event.cc | 3 +++ system/stack/btu/btu_hcif.cc | 3 +++ system/stack/fuzzers/avrc_fuzzer.cc | 3 +++ system/stack/fuzzers/bnep_fuzzer.cc | 3 +++ system/stack/fuzzers/gatt_fuzzer.cc | 3 +++ system/stack/fuzzers/l2cap_fuzzer.cc | 3 +++ system/stack/fuzzers/rfcomm_fuzzer.cc | 3 +++ system/stack/fuzzers/sdp_fuzzer.cc | 3 +++ system/stack/fuzzers/smp_fuzzer.cc | 3 +++ system/stack/gap/gap_ble.cc | 3 +++ system/stack/gap/gap_conn.cc | 3 +++ system/stack/gatt/att_protocol.cc | 3 +++ system/stack/gatt/connection_manager.cc | 3 +++ system/stack/gatt/gatt_api.cc | 3 +++ system/stack/gatt/gatt_attr.cc | 3 +++ system/stack/gatt/gatt_auth.cc | 3 +++ system/stack/gatt/gatt_cl.cc | 3 +++ system/stack/gatt/gatt_db.cc | 3 +++ system/stack/gatt/gatt_main.cc | 3 +++ system/stack/gatt/gatt_sr.cc | 3 +++ system/stack/gatt/gatt_utils.cc | 3 +++ system/stack/hid/hidh_api.cc | 3 +++ system/stack/l2cap/l2c_api.cc | 3 +++ system/stack/l2cap/l2c_ble.cc | 3 +++ system/stack/l2cap/l2c_ble_conn_params.cc | 3 +++ system/stack/l2cap/l2c_link.cc | 3 +++ system/stack/l2cap/l2c_main.cc | 3 +++ system/stack/l2cap/l2c_utils.cc | 3 +++ system/stack/rfcomm/rfc_ts_frames.cc | 3 +++ system/stack/rnr/remote_name_request.cc | 3 +++ system/stack/sdp/sdp_db.cc | 3 +++ system/stack/sdp/sdp_discovery.cc | 3 +++ system/stack/sdp/sdp_server.cc | 3 +++ system/stack/smp/smp_act.cc | 3 +++ system/stack/smp/smp_keys.cc | 3 +++ system/stack/smp/smp_utils.cc | 3 +++ system/stack/srvc/srvc_dis.cc | 3 +++ system/stack/test/a2dp/mock_bta_av_codec.cc | 3 +++ system/stack/test/btm/stack_btm_inq_test.cc | 3 +++ system/stack/test/btm/stack_btm_test.cc | 3 +++ system/stack/test/btm_iso_test.cc | 3 +++ system/stack/test/common/mock_btif_storage.cc | 3 +++ .../stack/test/common/mock_btm_api_layer.cc | 5 +++- system/stack/test/common/mock_btm_layer.cc | 3 +++ system/stack/test/common/mock_btu_layer.cc | 3 +++ system/stack/test/common/mock_l2cap_layer.cc | 3 +++ .../stack/test/common/mock_stack_avdt_msg.cc | 3 +++ system/stack/test/eatt/eatt_test.cc | 3 +++ system/stack/test/fuzzers/Android.bp | 4 +++ system/stack/test/gatt/mock_gatt_utils_ref.cc | 3 +++ .../test/gatt_connection_manager_test.cc | 3 +++ system/stack/test/hid/stack_hid_test.cc | 3 +++ system/stack/test/rfcomm/stack_rfcomm_test.cc | 3 +++ .../test/rfcomm/stack_rfcomm_test_utils.cc | 3 +++ system/stack/test/sdp/stack_sdp_test.cc | 3 +++ system/stack/test/sdp/stack_sdp_utils_test.cc | 3 +++ system/stack/test/stack_rnr_test.cc | 3 +++ system/stack/test/stack_smp_test.cc | 3 +++ system/test/common/jni_thread.cc | 3 +++ system/test/common/main_handler.cc | 3 +++ system/test/common/stack_config.cc | 3 +++ system/test/common/sync_main_handler.cc | 3 +++ system/test/fake/fake_looper.cc | 3 +++ system/test/headless/Android.bp | 3 --- system/test/headless/headless.cc | 3 +++ system/test/headless/log.cc | 3 +++ system/test/headless/messenger.cc | 3 +++ system/test/headless/read/name.cc | 3 +++ system/test/headless/util.cc | 3 +++ .../mock_audio_hal_interface_a2dp_encoding.cc | 3 +++ system/test/mock/mock_bluetooth_interface.cc | 3 +++ system/test/mock/mock_bta_ag_api.cc | 3 +++ system/test/mock/mock_bta_ag_sco.cc | 3 +++ system/test/mock/mock_bta_ar.cc | 3 +++ system/test/mock/mock_bta_av_ci.cc | 3 +++ system/test/mock/mock_bta_dm_act.cc | 3 +++ system/test/mock/mock_bta_dm_api.cc | 3 +++ system/test/mock/mock_bta_dm_main.cc | 3 +++ system/test/mock/mock_bta_gattc_api.cc | 3 +++ system/test/mock/mock_bta_gatts_api.cc | 3 +++ system/test/mock/mock_bta_hh_utils.cc | 3 +++ system/test/mock/mock_bta_pan_api.cc | 3 +++ system/test/mock/mock_bta_pan_ci.cc | 3 +++ system/test/mock/mock_bta_sdp_api.cc | 3 +++ system/test/mock/mock_bta_sys_conn.cc | 3 +++ system/test/mock/mock_bta_sys_main.cc | 3 +++ system/test/mock/mock_btif_av.cc | 3 +++ system/test/mock/mock_btif_bluetooth.cc | 3 +++ system/test/mock/mock_btif_bqr.cc | 3 +++ system/test/mock/mock_btif_bta_pan_co_rx.cc | 3 +++ system/test/mock/mock_btif_co_bta_av_co.cc | 3 +++ system/test/mock/mock_btif_co_bta_dm_co.cc | 3 +++ system/test/mock/mock_btif_co_bta_hh_co.cc | 3 +++ system/test/mock/mock_btif_config.cc | 3 +++ system/test/mock/mock_btif_core.cc | 3 +++ system/test/mock/mock_btif_dm.cc | 3 +++ system/test/mock/mock_btif_hf.cc | 3 +++ system/test/mock/mock_btif_profile_storage.cc | 3 +++ system/test/mock/mock_btif_sock_rfc.cc | 3 +++ system/test/mock/mock_btif_stack_manager.cc | 3 +++ system/test/mock/mock_btif_storage.cc | 3 +++ system/test/mock/mock_btif_util.cc | 3 +++ system/test/mock/mock_btu_task.cc | 3 +++ .../test/mock/mock_device_esco_parameters.cc | 3 +++ system/test/mock/mock_device_interop.cc | 3 +++ system/test/mock/mock_device_iot_config.cc | 3 +++ system/test/mock/mock_jni_thread.cc | 3 +++ system/test/mock/mock_main_shim_acl.cc | 3 +++ .../test/mock/mock_main_shim_acl_interface.cc | 3 +++ system/test/mock/mock_main_shim_hci_layer.cc | 3 +++ system/test/mock/mock_osi_future.cc | 3 +++ system/test/mock/mock_osi_list.cc | 3 +++ system/test/mock/mock_osi_mutex.cc | 3 +++ system/test/mock/mock_osi_properties.cc | 3 +++ system/test/mock/mock_osi_socket.cc | 3 +++ system/test/mock/mock_osi_thread_scheduler.cc | 3 +++ system/test/mock/mock_osi_wakelock.cc | 3 +++ system/test/mock/mock_stack_a2dp_sbc.cc | 3 +++ system/test/mock/mock_stack_acl.cc | 3 +++ system/test/mock/mock_stack_acl_ble.cc | 3 +++ system/test/mock/mock_stack_acl_btm_pm.cc | 3 +++ system/test/mock/mock_stack_avrc_api.cc | 3 +++ system/test/mock/mock_stack_avrc_apt.cc | 3 +++ system/test/mock/mock_stack_avrc_bld_tg.cc | 3 +++ system/test/mock/mock_stack_avrc_pars.ct.cc | 3 +++ system/test/mock/mock_stack_avrc_utils.cc | 3 +++ system/test/mock/mock_stack_btm_ble.cc | 7 ++++++ system/test/mock/mock_stack_btm_ble.h | 4 --- system/test/mock/mock_stack_btm_ble_addr.cc | 3 +++ system/test/mock/mock_stack_btm_ble_bgconn.cc | 3 +++ system/test/mock/mock_stack_btm_ble_gap.cc | 3 +++ .../test/mock/mock_stack_btm_ble_privacy.cc | 3 +++ system/test/mock/mock_stack_btm_dev.cc | 3 +++ system/test/mock/mock_stack_btm_devctl.cc | 3 +++ .../mock/mock_stack_btm_hfp_lc3_encoder.cc | 3 +++ .../mock/mock_stack_btm_hfp_msbc_decoder.cc | 3 +++ .../mock/mock_stack_btm_hfp_msbc_encoder.cc | 3 +++ system/test/mock/mock_stack_btm_inq.cc | 3 +++ system/test/mock/mock_stack_btm_interface.cc | 3 +++ system/test/mock/mock_stack_btm_main.cc | 3 +++ system/test/mock/mock_stack_btm_sco.cc | 3 +++ system/test/mock/mock_stack_btm_sec.cc | 3 +++ system/test/mock/mock_stack_btu_hcif.cc | 3 +++ system/test/mock/mock_stack_gap_ble.cc | 3 +++ system/test/mock/mock_stack_gap_conn.cc | 3 +++ system/test/mock/mock_stack_gatt.cc | 3 +++ system/test/mock/mock_stack_gatt_api.cc | 3 +++ system/test/mock/mock_stack_gatt_attr.cc | 3 +++ system/test/mock/mock_stack_gatt_auth.cc | 3 +++ system/test/mock/mock_stack_gatt_main.cc | 3 +++ .../test/mock/mock_stack_hcic_hciblecmds.cc | 3 +++ system/test/mock/mock_stack_hidh.cc | 3 +++ system/test/mock/mock_stack_l2cap_api.cc | 3 +++ system/test/mock/mock_stack_l2cap_ble.cc | 3 +++ system/test/mock/mock_stack_l2cap_link.cc | 3 +++ system/test/mock/mock_stack_l2cap_main.cc | 3 +++ system/test/mock/mock_stack_l2cap_utils.cc | 3 +++ .../test/mock/mock_stack_metrics_logging.cc | 3 +++ system/test/mock/mock_stack_sdp_api.cc | 3 +++ system/test/mock/mock_stack_sdp_db.cc | 3 +++ system/test/mock/mock_stack_sdp_main.cc | 3 +++ system/test/mock/mock_stack_sdp_server.cc | 3 +++ .../mock_stack_security_client_interface.cc | 3 +++ system/test/mock/mock_stack_smp_act.cc | 3 +++ system/test/mock/mock_stack_srvc_dis.cc | 3 +++ system/test/mock/mock_udrv_ulinux_uipc.cc | 3 +++ system/test/stub/osi.cc | 3 +++ system/udrv/ulinux/uipc.cc | 3 +++ 347 files changed, 1063 insertions(+), 20 deletions(-) diff --git a/Android.bp b/Android.bp index e88d6ab5506..9fbf29d0dfb 100644 --- a/Android.bp +++ b/Android.bp @@ -66,6 +66,7 @@ cc_defaults { "-Wall", "-Werror", "-Wextra", + "-Wmissing-prototypes", // Override global.go that demote the error to a warning "-Werror=format", "-Werror=reorder-init-list", diff --git a/android/app/Android.bp b/android/app/Android.bp index cd9465e6c7a..b80bd4057c5 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -199,11 +199,8 @@ cc_library { "libbluetooth-types", ], cflags: [ - /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ - "-Wall", - "-Werror", - "-Wextra", - "-Wno-unused-parameter", + // we export all classes, so change default visibility, + // instead of having EXPORT_SYMBOL on each class "-fvisibility=default", ], sanitize: { diff --git a/android/app/jni/com_android_bluetooth_avrcp_target.cpp b/android/app/jni/com_android_bluetooth_avrcp_target.cpp index d717ad0d8df..22f11e43458 100644 --- a/android/app/jni/com_android_bluetooth_avrcp_target.cpp +++ b/android/app/jni/com_android_bluetooth_avrcp_target.cpp @@ -27,6 +27,9 @@ #include "./com_android_bluetooth.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::avrcp::Attribute; using bluetooth::avrcp::AttributeEntry; using bluetooth::avrcp::FolderInfo; diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index 0d69e449398..e9d2ebe862b 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -33,6 +33,9 @@ #include "hardware/bt_sock.h" #include "types/bt_transport.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; extern bt_interface_t bluetoothInterface; diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index 9c27527fa5e..e164923de84 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -33,6 +33,9 @@ #include "rust/src/gatt/ffi/gatt_shim.h" #include "src/gatt/ffi.rs.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; #define UUID_PARAMS(uuid) uuid_lsb(uuid), uuid_msb(uuid) diff --git a/android/app/jni/com_android_bluetooth_le_audio.cpp b/android/app/jni/com_android_bluetooth_le_audio.cpp index 343beaf9c13..69c25d99b39 100644 --- a/android/app/jni/com_android_bluetooth_le_audio.cpp +++ b/android/app/jni/com_android_bluetooth_le_audio.cpp @@ -25,6 +25,9 @@ #include "com_android_bluetooth.h" #include "hardware/bt_le_audio.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::le_audio::BroadcastId; using bluetooth::le_audio::BroadcastState; using bluetooth::le_audio::btle_audio_bits_per_sample_index_t; diff --git a/system/audio/asrc/asrc_resampler_test.cc b/system/audio/asrc/asrc_resampler_test.cc index f631a16ac67..19ea04df0fe 100644 --- a/system/audio/asrc/asrc_resampler_test.cc +++ b/system/audio/asrc/asrc_resampler_test.cc @@ -19,6 +19,9 @@ #include #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bluetooth::common::MessageLoopThread message_loop_thread("main message loop"); bluetooth::common::MessageLoopThread* get_main_thread() { return &message_loop_thread; } diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index db1ee44d421..9704c1589bd 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -206,6 +206,7 @@ cc_defaults { ], defaults: [ "aconfig_lib_cc_shared_link.defaults", + "bluetooth_cflags", "latest_android_hardware_audio_common_ndk_static", "latest_android_hardware_bluetooth_audio_ndk_static", "latest_android_media_audio_common_types_ndk_static", diff --git a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc index 67082b85de6..c6f9091ac03 100644 --- a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc @@ -31,6 +31,9 @@ #include "provider_info.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace audio { namespace aidl { 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 fc685a56a97..304f2908988 100644 --- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc +++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc @@ -31,6 +31,9 @@ #include "hal_version_manager.h" #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace audio { namespace aidl { diff --git a/system/audio_hal_interface/aidl/le_audio_utils.cc b/system/audio_hal_interface/aidl/le_audio_utils.cc index dc9fbd56380..cd1b2964a7d 100644 --- a/system/audio_hal_interface/aidl/le_audio_utils.cc +++ b/system/audio_hal_interface/aidl/le_audio_utils.cc @@ -22,6 +22,9 @@ #include "hardware/bt_le_audio.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace audio { namespace aidl { diff --git a/system/audio_hal_interface/aidl/provider_info.cc b/system/audio_hal_interface/aidl/provider_info.cc index 60f6869b8b3..c93e545b09e 100644 --- a/system/audio_hal_interface/aidl/provider_info.cc +++ b/system/audio_hal_interface/aidl/provider_info.cc @@ -25,6 +25,9 @@ #include "client_interface_aidl.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth::audio::aidl { using ::aidl::android::hardware::bluetooth::audio::CodecId; using ::aidl::android::hardware::bluetooth::audio::CodecInfo; diff --git a/system/audio_hal_interface/hal_version_manager.cc b/system/audio_hal_interface/hal_version_manager.cc index 19c48c58da2..a085d21ce1d 100644 --- a/system/audio_hal_interface/hal_version_manager.cc +++ b/system/audio_hal_interface/hal_version_manager.cc @@ -26,6 +26,9 @@ #include "aidl/audio_aidl_interfaces.h" #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace audio { diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index 51c80efab8f..9a41e462c2c 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -27,6 +27,9 @@ #include "os/log.h" #include "osi/include/properties.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::bluetooth::audio::aidl::hfp::HfpDecodingTransport; using ::bluetooth::audio::aidl::hfp::HfpEncodingTransport; using AudioConfiguration = ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; diff --git a/system/audio_hal_interface/hfp_client_interface_unittest.cc b/system/audio_hal_interface/hfp_client_interface_unittest.cc index fa1d87a1a56..6ea503161d4 100644 --- a/system/audio_hal_interface/hfp_client_interface_unittest.cc +++ b/system/audio_hal_interface/hfp_client_interface_unittest.cc @@ -26,6 +26,10 @@ #include "aidl/transport_instance.h" #include "audio_hal_interface/hal_version_manager.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-private-field" + using testing::Test; using bluetooth::audio::hfp::HfpClientInterface; diff --git a/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc b/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc index e29f543b590..295ca5f2a64 100644 --- a/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc +++ b/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc @@ -24,6 +24,9 @@ #include "codec_status_hidl.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { using ::android::hardware::bluetooth::audio::V2_0::AacObjectType; diff --git a/system/audio_hal_interface/le_audio_software.cc b/system/audio_hal_interface/le_audio_software.cc index 87d8083759e..bc16ae1352b 100644 --- a/system/audio_hal_interface/le_audio_software.cc +++ b/system/audio_hal_interface/le_audio_software.cc @@ -34,6 +34,9 @@ #include "os/log.h" #include "osi/include/properties.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace audio { diff --git a/system/audio_hal_interface/le_audio_software_host.cc b/system/audio_hal_interface/le_audio_software_host.cc index 8907da08d1a..268e3841576 100644 --- a/system/audio_hal_interface/le_audio_software_host.cc +++ b/system/audio_hal_interface/le_audio_software_host.cc @@ -33,6 +33,9 @@ // TODO(b/198260375): Make LEA data owner group configurable. #define LEA_HOST_DATA_GROUP "bluetooth-audio" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/audio_hal_interface/le_audio_software_unittest.cc b/system/audio_hal_interface/le_audio_software_unittest.cc index 02ba88f2ed2..dec62e6a5cd 100644 --- a/system/audio_hal_interface/le_audio_software_unittest.cc +++ b/system/audio_hal_interface/le_audio_software_unittest.cc @@ -31,6 +31,10 @@ #include "gmock/gmock.h" #include "hidl/le_audio_software_hidl.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-private-field" + using testing::Return; using testing::Test; diff --git a/system/audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc b/system/audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc index cb1eee77203..1553b05d3e6 100644 --- a/system/audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc +++ b/system/audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc @@ -22,6 +22,9 @@ case const: \ return #const; +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event) { switch (event) { CASE_RETURN_STR(HEARING_AID_CTRL_CMD_NONE) diff --git a/system/bta/ag/bta_ag_at.cc b/system/bta/ag/bta_ag_at.cc index e5fee21d8b7..36d57a70f9b 100644 --- a/system/bta/ag/bta_ag_at.cc +++ b/system/bta/ag/bta_ag_at.cc @@ -37,6 +37,9 @@ #include "os/log.h" #include "osi/include/allocator.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/bta/ag/bta_ag_rfc.cc b/system/bta/ag/bta_ag_rfc.cc index 72ce9067651..12ecc304c36 100644 --- a/system/bta/ag/bta_ag_rfc.cc +++ b/system/bta/ag/bta_ag_rfc.cc @@ -36,6 +36,9 @@ /* Event mask for RfCOMM port callback */ #define BTA_AG_PORT_EV_MASK PORT_EV_RXCHAR +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /* each scb has its own rfcomm callbacks */ diff --git a/system/bta/ar/bta_ar.cc b/system/bta/ar/bta_ar.cc index 86b37adb2f1..6d82b2b78c3 100644 --- a/system/bta/ar/bta_ar.cc +++ b/system/bta/ar/bta_ar.cc @@ -37,6 +37,9 @@ #include "stack/include/sdp_api.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth::avrcp; using namespace bluetooth; diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index b6ade3ff1d7..006c01fe91f 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -61,6 +61,9 @@ #include "types/hci_role.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc index 7abd1de07a7..a82211fd47a 100644 --- a/system/bta/av/bta_av_act.cc +++ b/system/bta/av/bta_av_act.cc @@ -49,6 +49,9 @@ #include "stack/include/sdp_status.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/bta/av/bta_av_cfg.cc b/system/bta/av/bta_av_cfg.cc index 76aee2d45e1..87ecee4568e 100644 --- a/system/bta/av/bta_av_cfg.cc +++ b/system/bta/av/bta_av_cfg.cc @@ -39,6 +39,9 @@ #define BTA_AV_RC_PASS_RSP_CODE AVRC_RSP_NOT_IMPL #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; const uint32_t bta_av_meta_caps_co_ids[] = {AVRC_CO_METADATA, AVRC_CO_BROADCOM}; diff --git a/system/bta/av/bta_av_ci.cc b/system/bta/av/bta_av_ci.cc index 7abaca623de..e7bddf4b1f4 100644 --- a/system/bta/av/bta_av_ci.cc +++ b/system/bta/av/bta_av_ci.cc @@ -32,6 +32,9 @@ #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************* diff --git a/system/bta/csis/csis_client_test.cc b/system/bta/csis/csis_client_test.cc index 56a4f8f336e..fcb7467c1fa 100644 --- a/system/bta/csis/csis_client_test.cc +++ b/system/bta/csis/csis_client_test.cc @@ -36,6 +36,9 @@ #include "stack/include/bt_uuid16.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool gatt_cl_read_sirk_req(const RawAddress& peer_bda, base::OnceCallback diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 268bd9add91..f908268bdcf 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -66,6 +66,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/bta/dm/bta_dm_ci.cc b/system/bta/dm/bta_dm_ci.cc index 184a9de802f..16f6eb50c73 100644 --- a/system/bta/dm/bta_dm_ci.cc +++ b/system/bta/dm/bta_dm_ci.cc @@ -29,6 +29,9 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + /******************************************************************************* * * Function bta_dm_ci_rmt_oob diff --git a/system/bta/dm/bta_dm_device_search.cc b/system/bta/dm/bta_dm_device_search.cc index bc3fde0d919..a5428dc9837 100644 --- a/system/bta/dm/bta_dm_device_search.cc +++ b/system/bta/dm/bta_dm_device_search.cc @@ -47,6 +47,9 @@ #include "stack/include/rnr_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc index ae33b0059e8..441a938a310 100644 --- a/system/bta/dm/bta_dm_disc.cc +++ b/system/bta/dm/bta_dm_disc.cc @@ -52,6 +52,9 @@ #include "stack/include/srvc_api.h" #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/bta/dm/bta_dm_disc_sdp.cc b/system/bta/dm/bta_dm_disc_sdp.cc index bd3a62492e7..8bdbc9ee8a6 100644 --- a/system/bta/dm/bta_dm_disc_sdp.cc +++ b/system/bta/dm/bta_dm_disc_sdp.cc @@ -44,6 +44,9 @@ #include "stack/include/srvc_api.h" #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/bta/dm/bta_dm_gatt_client.cc b/system/bta/dm/bta_dm_gatt_client.cc index 36d53fe4569..c9d7ba8e115 100644 --- a/system/bta/dm/bta_dm_gatt_client.cc +++ b/system/bta/dm/bta_dm_gatt_client.cc @@ -31,6 +31,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { TimestampedStringCircularBuffer gatt_history_{50}; constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S"; diff --git a/system/bta/dm/bta_dm_pm.cc b/system/bta/dm/bta_dm_pm.cc index 141b1c78b36..dfd93ca2dc9 100644 --- a/system/bta/dm/bta_dm_pm.cc +++ b/system/bta/dm/bta_dm_pm.cc @@ -47,6 +47,9 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, const tBTA_SYS_ID id, uint8_t app_id, diff --git a/system/bta/dm/bta_dm_sec.cc b/system/bta/dm/bta_dm_sec.cc index 0e5eaf97ac1..c7d2163c2a5 100644 --- a/system/bta/dm/bta_dm_sec.cc +++ b/system/bta/dm/bta_dm_sec.cc @@ -37,6 +37,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static tBTM_STATUS bta_dm_sp_cback(tBTM_SP_EVT event, tBTM_SP_EVT_DATA* p_data); diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index 0590d973384..3064e39d97c 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -46,6 +46,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::StringPrintf; using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/bta/gatt/bta_gattc_cache.cc b/system/bta/gatt/bta_gattc_cache.cc index 28672593c27..600cfa9edc6 100644 --- a/system/bta/gatt/bta_gattc_cache.cc +++ b/system/bta/gatt/bta_gattc_cache.cc @@ -49,6 +49,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc index 994411e0391..11e696bc76b 100644 --- a/system/bta/gatt/bta_gattc_utils.cc +++ b/system/bta/gatt/bta_gattc_utils.cc @@ -39,6 +39,9 @@ #include "types/hci_role.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static uint8_t ble_acceptlist_size() { diff --git a/system/bta/gatt/bta_gatts_act.cc b/system/bta/gatt/bta_gatts_act.cc index 8d951ad3c2f..47abf7106d1 100644 --- a/system/bta/gatt/bta_gatts_act.cc +++ b/system/bta/gatt/bta_gatts_act.cc @@ -38,6 +38,9 @@ #include "stack/include/gatt_api.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static void bta_gatts_nv_save_cback(bool is_saved, tGATTS_HNDL_RANGE* p_hndl_range); diff --git a/system/bta/gatt/bta_gatts_api.cc b/system/bta/gatt/bta_gatts_api.cc index 4ceb8fe72ab..5b34fb047a7 100644 --- a/system/bta/gatt/bta_gatts_api.cc +++ b/system/bta/gatt/bta_gatts_api.cc @@ -39,6 +39,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/bta/gatt/database_builder.cc b/system/bta/gatt/database_builder.cc index 878e2f6982b..bda546c9d97 100644 --- a/system/bta/gatt/database_builder.cc +++ b/system/bta/gatt/database_builder.cc @@ -33,6 +33,9 @@ #include "stack/include/gattdefs.h" #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/bta/groups/groups_test.cc b/system/bta/groups/groups_test.cc index ea11e169b16..469da52a5d6 100644 --- a/system/bta/groups/groups_test.cc +++ b/system/bta/groups/groups_test.cc @@ -24,6 +24,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace groups { diff --git a/system/bta/has/has_client_test.cc b/system/bta/has/has_client_test.cc index 341b6cff51f..df98b10a427 100644 --- a/system/bta/has/has_client_test.cc +++ b/system/bta/has/has_client_test.cc @@ -42,6 +42,9 @@ #include "test/common/mock_functions.h" #include "types/bt_transport.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool gatt_profile_get_eatt_support(const RawAddress& addr) { return true; } void osi_property_set_bool(const char* key, bool value); diff --git a/system/bta/hf_client/bta_hf_client_at.cc b/system/bta/hf_client/bta_hf_client_at.cc index 3494a89c37a..f3494e215a5 100644 --- a/system/bta/hf_client/bta_hf_client_at.cc +++ b/system/bta/hf_client/bta_hf_client_at.cc @@ -42,6 +42,9 @@ /* timeout (in milliseconds) for AT hold timer */ #define BTA_HF_CLIENT_AT_HOLD_TIMEOUT 41 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static constexpr char kPropertyEnhancedDrivingIndicatorEnabled[] = diff --git a/system/bta/hh/bta_hh_main.cc b/system/bta/hh/bta_hh_main.cc index e28f24341c0..a4dd1444b4d 100644 --- a/system/bta/hh/bta_hh_main.cc +++ b/system/bta/hh/bta_hh_main.cc @@ -35,6 +35,9 @@ #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc index 5d01fdc6acd..2a3ffaea4b0 100644 --- a/system/bta/jv/bta_jv_act.cc +++ b/system/bta/jv/bta_jv_act.cc @@ -54,6 +54,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc b/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc index 793522565eb..dac6c9dbd16 100644 --- a/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc +++ b/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc @@ -31,6 +31,9 @@ #include "hardware/bluetooth.h" #include "osi/include/wakelock.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::testing::_; using ::testing::Assign; using ::testing::AtLeast; diff --git a/system/bta/le_audio/broadcaster/broadcaster_test.cc b/system/bta/le_audio/broadcaster/broadcaster_test.cc index c69a0745349..d7babbb2d03 100644 --- a/system/bta/le_audio/broadcaster/broadcaster_test.cc +++ b/system/bta/le_audio/broadcaster/broadcaster_test.cc @@ -41,6 +41,9 @@ #define TEST_BT com::android::bluetooth::flags +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace std::chrono_literals; using bluetooth::le_audio::types::AudioContexts; diff --git a/system/bta/le_audio/broadcaster/state_machine_test.cc b/system/bta/le_audio/broadcaster/state_machine_test.cc index 3cadd15fb6d..2dca7c5bee4 100644 --- a/system/bta/le_audio/broadcaster/state_machine_test.cc +++ b/system/bta/le_audio/broadcaster/state_machine_test.cc @@ -35,6 +35,9 @@ #define TEST_BT com::android::bluetooth::flags +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::hci::iso_manager; using bluetooth::hci::IsoManager; diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index e958b6e5159..448ad8beda2 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -66,6 +66,9 @@ #include "state_machine.h" #include "storage_helper.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Closure; using bluetooth::Uuid; using bluetooth::common::ToString; diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc index 8d0a1f6aa4f..13d9afc2188 100644 --- a/system/bta/le_audio/codec_manager_test.cc +++ b/system/bta/le_audio/codec_manager_test.cc @@ -30,6 +30,9 @@ #include "test/mock/mock_legacy_hci_interface.h" #include "test/mock/mock_main_shim_entry.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::testing::_; using ::testing::Mock; using ::testing::NiceMock; diff --git a/system/bta/le_audio/device_groups.cc b/system/bta/le_audio/device_groups.cc index b4218cec44a..2eda1feee23 100644 --- a/system/bta/le_audio/device_groups.cc +++ b/system/bta/le_audio/device_groups.cc @@ -37,6 +37,9 @@ #include "metrics_collector.h" #include "stack/include/btm_client_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth::le_audio { using bluetooth::le_audio::types::ase; diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc index 939fe96fc4d..28b9be0eede 100644 --- a/system/bta/le_audio/devices.cc +++ b/system/bta/le_audio/devices.cc @@ -35,6 +35,9 @@ #include "osi/include/properties.h" #include "stack/include/btm_client_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::hci::kIsoCigPhy1M; using bluetooth::hci::kIsoCigPhy2M; using bluetooth::le_audio::DeviceConnectState; diff --git a/system/bta/le_audio/devices_test.cc b/system/bta/le_audio/devices_test.cc index 5136834f700..d9845b2deb4 100644 --- a/system/bta/le_audio/devices_test.cc +++ b/system/bta/le_audio/devices_test.cc @@ -36,6 +36,9 @@ #include "stack/btm/btm_int_types.h" #include "test/mock/mock_main_shim_entry.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tACL_CONN* btm_bda_to_acl(const RawAddress& bda, tBT_TRANSPORT transport) { return nullptr; } namespace bluetooth { diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index ebda915932b..995aff27816 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -57,6 +57,9 @@ #define TEST_BT com::android::bluetooth::flags +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using testing::_; using testing::AnyNumber; using testing::AtLeast; diff --git a/system/bta/le_audio/le_audio_health_status_test.cc b/system/bta/le_audio/le_audio_health_status_test.cc index cf32279b9f4..0ec96d2f37f 100644 --- a/system/bta/le_audio/le_audio_health_status_test.cc +++ b/system/bta/le_audio/le_audio_health_status_test.cc @@ -27,6 +27,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::groups::kGroupUnknown; using bluetooth::le_audio::DeviceConnectState; using bluetooth::le_audio::LeAudioDevice; diff --git a/system/bta/le_audio/le_audio_types.cc b/system/bta/le_audio/le_audio_types.cc index 282a794ad39..aecdc97d6b6 100644 --- a/system/bta/le_audio/le_audio_types.cc +++ b/system/bta/le_audio/le_audio_types.cc @@ -31,6 +31,9 @@ #include "le_audio_utils.h" #include "stack/include/bt_types.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth::le_audio { using types::acs_ac_record; using types::LeAudioContextType; diff --git a/system/bta/le_audio/metrics_collector_test.cc b/system/bta/le_audio/metrics_collector_test.cc index e17d23db2e6..6110f82fdc0 100644 --- a/system/bta/le_audio/metrics_collector_test.cc +++ b/system/bta/le_audio/metrics_collector_test.cc @@ -25,6 +25,9 @@ #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using testing::_; using testing::AnyNumber; using testing::AtLeast; diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index 28bed96e55e..bfa0aa507ac 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -42,6 +42,9 @@ #include "test/mock/mock_stack_btm_iso.h" #include "types/bt_transport.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::bluetooth::le_audio::DeviceConnectState; using ::bluetooth::le_audio::codec_spec_caps::kLeAudioCodecChannelCountSingleChannel; using ::bluetooth::le_audio::codec_spec_caps::kLeAudioCodecChannelCountTwoChannel; diff --git a/system/bta/le_audio/storage_helper.cc b/system/bta/le_audio/storage_helper.cc index 92f85e37d42..b9f24233c38 100644 --- a/system/bta/le_audio/storage_helper.cc +++ b/system/bta/le_audio/storage_helper.cc @@ -26,6 +26,9 @@ #include "os/log.h" #include "stack/include/bt_types.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::le_audio::types::hdl_pair; namespace bluetooth::le_audio { diff --git a/system/bta/le_audio/storage_helper_test.cc b/system/bta/le_audio/storage_helper_test.cc index 7e656feaac5..07dbb6859d3 100644 --- a/system/bta/le_audio/storage_helper_test.cc +++ b/system/bta/le_audio/storage_helper_test.cc @@ -18,6 +18,9 @@ #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::le_audio::LeAudioDevice; namespace bluetooth::le_audio { diff --git a/system/bta/pan/bta_pan_ci.cc b/system/bta/pan/bta_pan_ci.cc index 833216aa52d..abd60b01450 100644 --- a/system/bta/pan/bta_pan_ci.cc +++ b/system/bta/pan/bta_pan_ci.cc @@ -28,6 +28,9 @@ #include "stack/include/bt_hdr.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event, tBTA_PAN_DATA* p_data); /******************************************************************************* diff --git a/system/bta/pan/bta_pan_main.cc b/system/bta/pan/bta_pan_main.cc index 57c87e9d503..1f2dc9d2e0b 100644 --- a/system/bta/pan/bta_pan_main.cc +++ b/system/bta/pan/bta_pan_main.cc @@ -29,6 +29,9 @@ #include "internal_include/bt_target.h" #include "stack/include/bt_hdr.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/bta/sdp/bta_sdp_act.cc b/system/bta/sdp/bta_sdp_act.cc index 364930d8c56..ab2f120d17c 100644 --- a/system/bta/sdp/bta_sdp_act.cc +++ b/system/bta/sdp/bta_sdp_act.cc @@ -39,6 +39,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/bta/test/bta_ag_sco_test.cc b/system/bta/test/bta_ag_sco_test.cc index 78c7902966f..16da3830214 100644 --- a/system/bta/test/bta_ag_sco_test.cc +++ b/system/bta/test/bta_ag_sco_test.cc @@ -27,6 +27,9 @@ #include "test/mock/mock_device_esco_parameters.h" #include "test/mock/mock_main_shim_entry.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool btm_peer_supports_esco_ev3(const RawAddress& remote_bda) { return true; } tBTM_CB btm_cb; LeAudioClient* LeAudioClient::Get() { return nullptr; } diff --git a/system/bta/test/bta_av_test.cc b/system/bta/test/bta_av_test.cc index aecf5a916a5..0775b7c54b9 100644 --- a/system/bta/test/bta_av_test.cc +++ b/system/bta/test/bta_av_test.cc @@ -24,6 +24,9 @@ #include "test/mock/mock_osi_alarm.h" #include "test/mock/mock_stack_acl.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace std::chrono_literals; bool btif_av_both_enable(void) { return true; } diff --git a/system/bta/test/bta_gatt_test.cc b/system/bta/test/bta_gatt_test.cc index b867948a34d..2a7909657ce 100644 --- a/system/bta/test/bta_gatt_test.cc +++ b/system/bta/test/bta_gatt_test.cc @@ -28,6 +28,9 @@ #include "stack/gatt/gatt_int.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace param { struct { uint16_t conn_id; diff --git a/system/bta/test/common/btif_storage_mock.cc b/system/bta/test/common/btif_storage_mock.cc index d52b8e6369b..b74b7678ead 100644 --- a/system/bta/test/common/btif_storage_mock.cc +++ b/system/bta/test/common/btif_storage_mock.cc @@ -19,6 +19,9 @@ #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static bluetooth::storage::MockBtifStorageInterface* btif_storage_interface = nullptr; diff --git a/system/bta/test/common/btm_api_mock.cc b/system/bta/test/common/btm_api_mock.cc index d32e40ebc59..6c2f30797e5 100644 --- a/system/bta/test/common/btm_api_mock.cc +++ b/system/bta/test/common/btm_api_mock.cc @@ -26,6 +26,9 @@ #include "test/mock/mock_stack_btm_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static bluetooth::manager::MockBtmInterface* btm_interface = nullptr; diff --git a/system/bta/vc/devices_test.cc b/system/bta/vc/devices_test.cc index 984e7af608d..8d951ea7fb5 100644 --- a/system/bta/vc/devices_test.cc +++ b/system/bta/vc/devices_test.cc @@ -33,6 +33,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace vc { namespace internal { diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index 3a2d683f89a..af4ae2bb27d 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -37,6 +37,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void btif_storage_add_volume_control(const RawAddress& addr, bool auto_conn) {} struct alarm_t { diff --git a/system/btcore/src/osi_module.cc b/system/btcore/src/osi_module.cc index 77c75fa795a..22d8f05398a 100644 --- a/system/btcore/src/osi_module.cc +++ b/system/btcore/src/osi_module.cc @@ -27,6 +27,9 @@ #include "osi/include/osi.h" #include "osi/include/wakelock.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + future_t* osi_init(void) { return future_new_immediate(FUTURE_SUCCESS); } future_t* osi_clean_up(void) { diff --git a/system/btcore/test/device_class_test.cc b/system/btcore/test/device_class_test.cc index bdd6c69ce2b..af114ffed5d 100644 --- a/system/btcore/test/device_class_test.cc +++ b/system/btcore/test/device_class_test.cc @@ -21,6 +21,9 @@ #include #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + ::testing::AssertionResult check_bitfield(const char* m_expr, const char* n_expr, int m, int n) { if (m == n) { return ::testing::AssertionSuccess(); diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index 75f42cb1d31..1364631d26b 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -53,6 +53,9 @@ #include "stack/include/bt_uuid16.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; // SCMS-T protect info diff --git a/system/btif/co/bta_gatts_co.cc b/system/btif/co/bta_gatts_co.cc index b0056d603ee..28a24ad17ae 100644 --- a/system/btif/co/bta_gatts_co.cc +++ b/system/btif/co/bta_gatts_co.cc @@ -25,6 +25,9 @@ #include "stack/include/gatt_api.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + /***************************************************************************** * Local type definitions ****************************************************************************/ diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index 0b0141c04ef..f43363e3bac 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -41,6 +41,9 @@ #include "storage/config_keys.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + const char* dev_path = "/dev/uhid"; #include "btif_config.h" diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index ba8f77acfea..b2f554e9107 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -115,6 +115,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::csis::CsisClientInterface; using bluetooth::has::HasClientInterface; using bluetooth::hearing_aid::HearingAidInterface; diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index f67527da8bd..6f925864199 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -54,6 +54,9 @@ #include "stack/include/btm_status.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::audio::a2dp::BluetoothAudioStatus; using bluetooth::common::A2dpSessionMetrics; using bluetooth::common::BluetoothMetricsLogger; diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 96956b1dc7e..57fb6dd073c 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -67,6 +67,9 @@ #include #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/btif/src/btif_avrcp_audio_track.cc b/system/btif/src/btif_avrcp_audio_track.cc index 6b825e5bc12..7a3d27f6a54 100644 --- a/system/btif/src/btif_avrcp_audio_track.cc +++ b/system/btif/src/btif_avrcp_audio_track.cc @@ -32,6 +32,9 @@ #include "internal_include/bt_target.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace android; using namespace bluetooth; diff --git a/system/btif/src/btif_ble_scanner.cc b/system/btif/src/btif_ble_scanner.cc index 1892ba133c5..3bfac0c3052 100644 --- a/system/btif/src/btif_ble_scanner.cc +++ b/system/btif/src/btif_ble_scanner.cc @@ -20,6 +20,9 @@ #include "main/shim/le_scanning_manager.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + BleScannerInterface* get_ble_scanner_instance() { return bluetooth::shim::get_ble_scanner_instance(); } diff --git a/system/btif/src/btif_bqr.cc b/system/btif/src/btif_bqr.cc index 8aa1e6016f4..5d65920f47e 100644 --- a/system/btif/src/btif_bqr.cc +++ b/system/btif/src/btif_bqr.cc @@ -45,6 +45,9 @@ #include "stack/include/btm_client_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace bqr { diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index 2bde8db29ac..c73a5cea06a 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -64,6 +64,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::PlatformThread; using bluetooth::Uuid; using bluetooth::common::MessageLoopThread; diff --git a/system/btif/src/btif_csis_client.cc b/system/btif/src/btif_csis_client.cc index a7aef9f57b9..2a745ca109e 100644 --- a/system/btif/src/btif_csis_client.cc +++ b/system/btif/src/btif_csis_client.cc @@ -27,6 +27,9 @@ #include "btif_profile_storage.h" #include "stack/include/main_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using base::Owned; using base::Passed; diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 97696a1600e..a3bfb1a6f88 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -105,6 +105,9 @@ #include #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool btif_get_address_type(const RawAddress& bda, tBLE_ADDR_TYPE* p_addr_type); bool btif_get_device_type(const RawAddress& bda, int* p_device_type); diff --git a/system/btif/src/btif_gatt.cc b/system/btif/src/btif_gatt.cc index ed20db48212..9bd0eba6098 100644 --- a/system/btif/src/btif_gatt.cc +++ b/system/btif/src/btif_gatt.cc @@ -39,6 +39,9 @@ #include "main/shim/distance_measurement_manager.h" #include "main/shim/le_advertising_manager.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + const btgatt_callbacks_t* bt_gatt_callbacks = NULL; /******************************************************************************* diff --git a/system/btif/src/btif_has_client.cc b/system/btif/src/btif_has_client.cc index 1f5f8f72f2c..18ae5478cd0 100644 --- a/system/btif/src/btif_has_client.cc +++ b/system/btif/src/btif_has_client.cc @@ -28,6 +28,9 @@ #include "btif_profile_storage.h" #include "stack/include/main_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using base::Owned; using base::Passed; diff --git a/system/btif/src/btif_hd.cc b/system/btif/src/btif_hd.cc index fa353f87df2..742e9fd87e3 100644 --- a/system/btif/src/btif_hd.cc +++ b/system/btif/src/btif_hd.cc @@ -55,6 +55,9 @@ #define COD_HID_COMBO 0x05C0 #define COD_HID_MAJOR 0x0500 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; bool bta_dm_check_if_only_hd_connected(const RawAddress& peer_addr); diff --git a/system/btif/src/btif_hearing_aid.cc b/system/btif/src/btif_hearing_aid.cc index 6ff13d02ac0..6c8a689c49a 100644 --- a/system/btif/src/btif_hearing_aid.cc +++ b/system/btif/src/btif_hearing_aid.cc @@ -29,6 +29,9 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using base::Unretained; using bluetooth::hearing_aid::ConnectionState; diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index 35408361844..9ab0745cfeb 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -55,6 +55,9 @@ #include "stack/include/btm_log_history.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { constexpr char kBtmLogTag[] = "HFP"; } diff --git a/system/btif/src/btif_hf_client.cc b/system/btif/src/btif_hf_client.cc index 1b76260a44c..9a6eb128e35 100644 --- a/system/btif/src/btif_hf_client.cc +++ b/system/btif/src/btif_hf_client.cc @@ -68,6 +68,9 @@ #define BTIF_HF_CLIENT_SERVICE_NAME ("Handsfree") #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************* diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index f7983d3c2db..578f4f93156 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -66,6 +66,9 @@ #define LOGITECH_KB_MX5500_VENDOR_ID 0x046D #define LOGITECH_KB_MX5500_PRODUCT_ID 0xB30B +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static int btif_hh_keylockstates = 0; // The current key state of each key diff --git a/system/btif/src/btif_iot_config.cc b/system/btif/src/btif_iot_config.cc index 293d8a7bc20..1e70657b2a2 100644 --- a/system/btif/src/btif_iot_config.cc +++ b/system/btif/src/btif_iot_config.cc @@ -24,6 +24,9 @@ #include "stack/include/btm_ble_api.h" #include "stack/include/btm_client_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************* diff --git a/system/btif/src/btif_le_audio.cc b/system/btif/src/btif_le_audio.cc index e3dd8e52164..0e4ab09e418 100644 --- a/system/btif/src/btif_le_audio.cc +++ b/system/btif/src/btif_le_audio.cc @@ -26,6 +26,9 @@ #include "btif_profile_storage.h" #include "stack/include/main_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using base::Unretained; using bluetooth::le_audio::btle_audio_codec_config_t; diff --git a/system/btif/src/btif_le_audio_broadcaster.cc b/system/btif/src/btif_le_audio_broadcaster.cc index 199ba63f777..45c4b5b52d9 100644 --- a/system/btif/src/btif_le_audio_broadcaster.cc +++ b/system/btif/src/btif_le_audio_broadcaster.cc @@ -24,6 +24,9 @@ #include "btif_common.h" #include "stack/include/main_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using base::Unretained; using bluetooth::le_audio::BroadcastId; diff --git a/system/btif/src/btif_pan.cc b/system/btif/src/btif_pan.cc index 804c5d9fca3..f4705f99eba 100644 --- a/system/btif/src/btif_pan.cc +++ b/system/btif/src/btif_pan.cc @@ -73,6 +73,9 @@ #define MIN(x, y) (((x) < (y)) ? (x) : (y)) +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; btpan_cb_t btpan_cb; diff --git a/system/btif/src/btif_profile_storage.cc b/system/btif/src/btif_profile_storage.cc index ab31a63afbc..4c5fad6734e 100644 --- a/system/btif/src/btif_profile_storage.cc +++ b/system/btif/src/btif_profile_storage.cc @@ -47,6 +47,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using bluetooth::Uuid; using bluetooth::csis::CsisClient; diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index e213b7886ae..4eaf0e61e8a 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -108,6 +108,9 @@ } \ } while (0) +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/btif/src/btif_sdp.cc b/system/btif/src/btif_sdp.cc index bc336acbf65..db75f5eac1b 100644 --- a/system/btif/src/btif_sdp.cc +++ b/system/btif/src/btif_sdp.cc @@ -40,6 +40,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/btif/src/btif_sdp_server.cc b/system/btif/src/btif_sdp_server.cc index cd4b9404dd4..c7c29188dd2 100644 --- a/system/btif/src/btif_sdp_server.cc +++ b/system/btif/src/btif_sdp_server.cc @@ -48,6 +48,9 @@ #include "types/bluetooth/uuid.h" #include "utl.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/btif/src/btif_sock_l2cap.cc b/system/btif/src/btif_sock_l2cap.cc index 285338f17be..f864dda287a 100644 --- a/system/btif/src/btif_sock_l2cap.cc +++ b/system/btif/src/btif_sock_l2cap.cc @@ -42,6 +42,9 @@ #include "stack/include/l2cdefs.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; struct packet { diff --git a/system/btif/src/btif_sock_rfc.cc b/system/btif/src/btif_sock_rfc.cc index 69b0889ed3c..2f5d60415bb 100644 --- a/system/btif/src/btif_sock_rfc.cc +++ b/system/btif/src/btif_sock_rfc.cc @@ -45,6 +45,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/btif/src/btif_sock_sco.cc b/system/btif/src/btif_sock_sco.cc index a7e08cc2f2d..a03d176e6f6 100644 --- a/system/btif/src/btif_sock_sco.cc +++ b/system/btif/src/btif_sock_sco.cc @@ -54,6 +54,9 @@ // socket_read_ready_cb() - local host closed SCO socket // disconnect_completed_cb() - connection terminated +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; typedef struct { diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc index 5ff0d89de3e..1c30c76d49a 100644 --- a/system/btif/src/btif_storage.cc +++ b/system/btif/src/btif_storage.cc @@ -60,6 +60,9 @@ /* This is a local property to add a device found */ #define BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP 0xFF +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc index fb41e40730b..e106aed5165 100644 --- a/system/btif/src/btif_vc.cc +++ b/system/btif/src/btif_vc.cc @@ -29,6 +29,9 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Bind; using base::Unretained; using bluetooth::vc::ConnectionState; diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc index fadb09658f5..e3e4f3ba0b6 100644 --- a/system/btif/src/stack_manager.cc +++ b/system/btif/src/stack_manager.cc @@ -99,6 +99,9 @@ static_assert(BTA_HH_INCLUDED, " Host interface device profile is always enabled in the bluetooth stack" "*** Conditional Compilation Directive error"); +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void BTA_dm_on_hw_on(); void BTA_dm_on_hw_off(); diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc index 8044296b9fc..16125b4e803 100644 --- a/system/btif/test/btif_core_test.cc +++ b/system/btif/test/btif_core_test.cc @@ -57,6 +57,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth::testing { void set_hal_cbacks(bt_callbacks_t* callbacks); } // namespace bluetooth::testing diff --git a/system/btif/test/btif_profile_queue_test.cc b/system/btif/test/btif_profile_queue_test.cc index d39164b36b6..489ba796609 100644 --- a/system/btif/test/btif_profile_queue_test.cc +++ b/system/btif/test/btif_profile_queue_test.cc @@ -26,6 +26,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + typedef void(tBTIF_CBACK)(uint16_t event, char* p_param); typedef void(tBTIF_COPY_CBACK)(uint16_t event, char* p_dest, const char* p_src); diff --git a/system/common/benchmark/thread_performance_benchmark.cc b/system/common/benchmark/thread_performance_benchmark.cc index cfad3627b95..97f0c93b2d2 100644 --- a/system/common/benchmark/thread_performance_benchmark.cc +++ b/system/common/benchmark/thread_performance_benchmark.cc @@ -30,6 +30,9 @@ #include "osi/include/fixed_queue.h" #include "osi/include/thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::benchmark::State; using bluetooth::common::MessageLoopThread; diff --git a/system/common/metric_id_allocator_unittest.cc b/system/common/metric_id_allocator_unittest.cc index 028540a94e6..778163c62d4 100644 --- a/system/common/metric_id_allocator_unittest.cc +++ b/system/common/metric_id_allocator_unittest.cc @@ -25,6 +25,9 @@ #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace testing { using bluetooth::common::MetricIdAllocator; diff --git a/system/common/metrics_linux.cc b/system/common/metrics_linux.cc index 13795f764d0..bbd411b11ef 100644 --- a/system/common/metrics_linux.cc +++ b/system/common/metrics_linux.cc @@ -21,6 +21,9 @@ #include "common/metrics.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace common { diff --git a/system/common/metrics_unittest.cc b/system/common/metrics_unittest.cc index b2a300f911c..86e2ec7a133 100644 --- a/system/common/metrics_unittest.cc +++ b/system/common/metrics_unittest.cc @@ -32,6 +32,9 @@ #define BTM_COD_MAJOR_AUDIO_TEST 0x04 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace testing { using bluetooth::common::A2dpSessionMetrics; diff --git a/system/common/os_utils.cc b/system/common/os_utils.cc index f8fda269154..a4bf8ea314c 100644 --- a/system/common/os_utils.cc +++ b/system/common/os_utils.cc @@ -19,6 +19,9 @@ #include #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool is_bluetooth_uid() { #ifdef __ANDROID__ return getuid() == AID_BLUETOOTH; diff --git a/system/common/test/thread_performance_test.cc b/system/common/test/thread_performance_test.cc index 4eed2fdf103..d6a0ea32ecb 100644 --- a/system/common/test/thread_performance_test.cc +++ b/system/common/test/thread_performance_test.cc @@ -31,6 +31,9 @@ #include "osi/include/fixed_queue.h" #include "osi/include/thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::common::MessageLoopThread; using namespace bluetooth; diff --git a/system/device/fuzzer/btdevice_esco_fuzzer.cpp b/system/device/fuzzer/btdevice_esco_fuzzer.cpp index 821d3492981..aa06d1fec97 100644 --- a/system/device/fuzzer/btdevice_esco_fuzzer.cpp +++ b/system/device/fuzzer/btdevice_esco_fuzzer.cpp @@ -23,6 +23,9 @@ #include "interop.h" #include "interop_config.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace std; constexpr size_t kNumAddressOctets = 6; constexpr size_t kMaxStringLength = 10; diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc index 2a400e30791..bcb491f33f1 100644 --- a/system/device/src/interop.cc +++ b/system/device/src/interop.cc @@ -48,6 +48,9 @@ #include "osi/include/osi.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; #ifdef __ANDROID__ diff --git a/system/embdrv/sbc/decoder/Android.bp b/system/embdrv/sbc/decoder/Android.bp index e13cec2c3de..84184fece78 100644 --- a/system/embdrv/sbc/decoder/Android.bp +++ b/system/embdrv/sbc/decoder/Android.bp @@ -11,6 +11,9 @@ package { cc_library_static { name: "libbt-sbc-decoder", defaults: ["fluoride_defaults"], + cflags: [ + "-Wno-missing-prototypes", + ], srcs: [ "srce/alloc.c", "srce/bitalloc-sbc.c", diff --git a/system/embdrv/sbc/encoder/Android.bp b/system/embdrv/sbc/encoder/Android.bp index 5a4cc5d80cf..74fe1ec965e 100644 --- a/system/embdrv/sbc/encoder/Android.bp +++ b/system/embdrv/sbc/encoder/Android.bp @@ -10,6 +10,9 @@ package { cc_library_static { name: "libbt-sbc-encoder", defaults: ["fluoride_defaults"], + cflags: [ + "-Wno-missing-prototypes", + ], srcs: [ "srce/sbc_analysis.c", "srce/sbc_dct.c", diff --git a/system/gd/Android.bp b/system/gd/Android.bp index c5dc79e6c04..7064a59e18c 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -287,6 +287,10 @@ cc_binary { defaults: [ "gd_defaults", ], + cflags: [ + // The generated gRPC code triggers these warnings. + "-Wno-missing-prototypes", + ], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/include", diff --git a/system/gd/common/metric_id_manager_unittest.cc b/system/gd/common/metric_id_manager_unittest.cc index 2b23c59db4b..6c36187a55c 100644 --- a/system/gd/common/metric_id_manager_unittest.cc +++ b/system/gd/common/metric_id_manager_unittest.cc @@ -22,6 +22,9 @@ #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace testing { using bluetooth::common::MetricIdManager; diff --git a/system/gd/common/strings_test.cc b/system/gd/common/strings_test.cc index c252429ec94..63a9804ab70 100644 --- a/system/gd/common/strings_test.cc +++ b/system/gd/common/strings_test.cc @@ -23,6 +23,9 @@ #include #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace testing { using bluetooth::common::BoolFromString; diff --git a/system/gd/dumpsys/bundler/bundler.cc b/system/gd/dumpsys/bundler/bundler.cc index 099c75bc452..a88da57466a 100644 --- a/system/gd/dumpsys/bundler/bundler.cc +++ b/system/gd/dumpsys/bundler/bundler.cc @@ -28,6 +28,9 @@ #include "flatbuffers/idl.h" #include "flatbuffers/util.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using namespace dumpsys; diff --git a/system/gd/fuzz_test.cc b/system/gd/fuzz_test.cc index bdb007b2952..8b4b2b9786d 100644 --- a/system/gd/fuzz_test.cc +++ b/system/gd/fuzz_test.cc @@ -17,6 +17,9 @@ #include #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void RunHciPacketFuzzTest(const uint8_t* data, size_t size); extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { diff --git a/system/gd/hal/snoop_logger_test.cc b/system/gd/hal/snoop_logger_test.cc index 1e3fec18806..ac32603f949 100644 --- a/system/gd/hal/snoop_logger_test.cc +++ b/system/gd/hal/snoop_logger_test.cc @@ -31,6 +31,9 @@ #include "os/system_properties.h" #include "os/utils.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace testing { using bluetooth::hal::SnoopLoggerCommon; diff --git a/system/gd/hci/acl_manager/classic_impl_test.cc b/system/gd/hci/acl_manager/classic_impl_test.cc index 543fa0d0bf9..e5aa6d61aeb 100644 --- a/system/gd/hci/acl_manager/classic_impl_test.cc +++ b/system/gd/hci/acl_manager/classic_impl_test.cc @@ -33,6 +33,9 @@ #include "packet/bit_inserter.h" #include "packet/raw_builder.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using namespace std::chrono_literals; diff --git a/system/gd/hci/controller_test.cc b/system/gd/hci/controller_test.cc index 305c1e361f6..3ea8416469b 100644 --- a/system/gd/hci/controller_test.cc +++ b/system/gd/hci/controller_test.cc @@ -33,6 +33,9 @@ #include "os/thread.h" #include "packet/raw_builder.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using namespace std::chrono_literals; diff --git a/system/gd/hci/facade/le_advertising_manager_facade.cc b/system/gd/hci/facade/le_advertising_manager_facade.cc index 88207dd242d..43b68aedf5e 100644 --- a/system/gd/hci/facade/le_advertising_manager_facade.cc +++ b/system/gd/hci/facade/le_advertising_manager_facade.cc @@ -33,6 +33,9 @@ #include "hci/le_advertising_manager.h" #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace hci { namespace facade { diff --git a/system/gd/hci/fuzz/acl_manager_fuzz_test.cc b/system/gd/hci/fuzz/acl_manager_fuzz_test.cc index 53bf55d6f47..527982ced5f 100644 --- a/system/gd/hci/fuzz/acl_manager_fuzz_test.cc +++ b/system/gd/hci/fuzz/acl_manager_fuzz_test.cc @@ -26,6 +26,9 @@ #include "os/fake_timer/fake_timerfd.h" #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::FuzzTestModuleRegistry; using bluetooth::fuzz::GetArbitraryBytes; using bluetooth::hci::AclManager; diff --git a/system/gd/hci/fuzz/hci_layer_fuzz_test.cc b/system/gd/hci/fuzz/hci_layer_fuzz_test.cc index 2c46fa2a0fb..48191efe1c9 100644 --- a/system/gd/hci/fuzz/hci_layer_fuzz_test.cc +++ b/system/gd/hci/fuzz/hci_layer_fuzz_test.cc @@ -26,6 +26,9 @@ #include "os/fake_timer/fake_timerfd.h" #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::FuzzTestModuleRegistry; using bluetooth::fuzz::GetArbitraryBytes; using bluetooth::hal::HciHal; diff --git a/system/gd/hci/hci_layer_unittest.cc b/system/gd/hci/hci_layer_unittest.cc index b9a0a1b1385..1f2526e46df 100644 --- a/system/gd/hci/hci_layer_unittest.cc +++ b/system/gd/hci/hci_layer_unittest.cc @@ -34,6 +34,9 @@ #include "os/thread.h" #include "packet/raw_builder.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace std::chrono_literals; namespace { diff --git a/system/gd/hci/hci_packets_fuzz_test.cc b/system/gd/hci/hci_packets_fuzz_test.cc index 1388f1bbd86..68ebf7e6daf 100644 --- a/system/gd/hci/hci_packets_fuzz_test.cc +++ b/system/gd/hci/hci_packets_fuzz_test.cc @@ -22,6 +22,9 @@ #include "packet/bit_inserter.h" #include "packet/raw_builder.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::packet::BitInserter; using bluetooth::packet::RawBuilder; using std::vector; diff --git a/system/gd/hci/le_address_manager.cc b/system/gd/hci/le_address_manager.cc index 5eedc206300..b8ac989b83d 100644 --- a/system/gd/hci/le_address_manager.cc +++ b/system/gd/hci/le_address_manager.cc @@ -23,6 +23,9 @@ #include "include/macros.h" #include "os/rand.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace hci { diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc index 7a3eebf47b7..8f342922ace 100644 --- a/system/gd/hci/le_advertising_manager.cc +++ b/system/gd/hci/le_advertising_manager.cc @@ -35,6 +35,9 @@ #include "os/system_properties.h" #include "packet/fragmenting_inserter.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace hci { diff --git a/system/gd/metrics/bluetooth_event.cc b/system/gd/metrics/bluetooth_event.cc index c18412a2bda..86ac065eac3 100644 --- a/system/gd/metrics/bluetooth_event.cc +++ b/system/gd/metrics/bluetooth_event.cc @@ -20,6 +20,9 @@ #include "main/shim/helpers.h" #include "os/metrics.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace metrics { diff --git a/system/gd/module_gdx_unittest.cc b/system/gd/module_gdx_unittest.cc index a744e176abb..9d9ee4c7c85 100644 --- a/system/gd/module_gdx_unittest.cc +++ b/system/gd/module_gdx_unittest.cc @@ -32,6 +32,9 @@ #include "module.h" #include "os/handler.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/gd/module_jniloop_unittest.cc b/system/gd/module_jniloop_unittest.cc index 1ce47036b43..98c6b7e09d0 100644 --- a/system/gd/module_jniloop_unittest.cc +++ b/system/gd/module_jniloop_unittest.cc @@ -30,6 +30,9 @@ #include "os/handler.h" #include "os/thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/gd/module_mainloop_unittest.cc b/system/gd/module_mainloop_unittest.cc index f9e9ce3419d..cac37f83fea 100644 --- a/system/gd/module_mainloop_unittest.cc +++ b/system/gd/module_mainloop_unittest.cc @@ -30,6 +30,9 @@ #include "os/thread.h" #include "stack/include/main_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/gd/os/linux_generic/alarm_timerfd_unittest.cc b/system/gd/os/linux_generic/alarm_timerfd_unittest.cc index aee1b6277e5..03d99bb4763 100644 --- a/system/gd/os/linux_generic/alarm_timerfd_unittest.cc +++ b/system/gd/os/linux_generic/alarm_timerfd_unittest.cc @@ -23,6 +23,9 @@ #include "gtest/gtest.h" #include "os/alarm.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth::common { struct IsSpace { diff --git a/system/gd/os/linux_generic/wakelock_manager.cc b/system/gd/os/linux_generic/wakelock_manager.cc index a5b65ac35b3..022904c942d 100644 --- a/system/gd/os/linux_generic/wakelock_manager.cc +++ b/system/gd/os/linux_generic/wakelock_manager.cc @@ -28,6 +28,9 @@ #include "os/internal/wakelock_native.h" #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace os { diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc index 057a7c41b39..79d60320958 100644 --- a/system/main/shim/acl.cc +++ b/system/main/shim/acl.cc @@ -66,6 +66,9 @@ #include "types/ble_address_with_type.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + extern tBTM_CB btm_cb; using namespace bluetooth; diff --git a/system/main/shim/hci_layer.cc b/system/main/shim/hci_layer.cc index 95794f04926..62b3e801edb 100644 --- a/system/main/shim/hci_layer.cc +++ b/system/main/shim/hci_layer.cc @@ -37,6 +37,9 @@ #include "stack/include/hcimsgs.h" #include "stack/include/main_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /** diff --git a/system/main/test/main_shim_test.cc b/system/main/test/main_shim_test.cc index a7e781742df..43d40bc799e 100644 --- a/system/main/test/main_shim_test.cc +++ b/system/main/test/main_shim_test.cc @@ -69,6 +69,9 @@ #include "types/hci_role.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::testing::_; using namespace bluetooth; diff --git a/system/osi/src/list.cc b/system/osi/src/list.cc index 5fe07aaf424..d361b18ef97 100644 --- a/system/osi/src/list.cc +++ b/system/osi/src/list.cc @@ -4,6 +4,9 @@ #include "osi/include/allocator.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; struct list_node_t { diff --git a/system/osi/src/stack_power_telemetry.cc b/system/osi/src/stack_power_telemetry.cc index 7f4d513fcca..f8ca11e32c9 100644 --- a/system/osi/src/stack_power_telemetry.cc +++ b/system/osi/src/stack_power_telemetry.cc @@ -35,6 +35,9 @@ #include "stack/include/btm_status.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; time_t get_current_time() { return time(0); } diff --git a/system/osi/src/thread_scheduler.cc b/system/osi/src/thread_scheduler.cc index bb7a44e410e..e67b9c662ae 100644 --- a/system/osi/src/thread_scheduler.cc +++ b/system/osi/src/thread_scheduler.cc @@ -17,6 +17,9 @@ #include #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { constexpr int kRealTimeFifoSchedulingPriority = 1; } // namespace diff --git a/system/osi/test/alarm_test.cc b/system/osi/test/alarm_test.cc index 5eab1cbc41d..a7538a99041 100644 --- a/system/osi/test/alarm_test.cc +++ b/system/osi/test/alarm_test.cc @@ -28,6 +28,9 @@ #include "osi/include/wakelock.h" #include "osi/semaphore.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::Closure; using bluetooth::common::MessageLoopThread; diff --git a/system/osi/test/fuzzers/Android.bp b/system/osi/test/fuzzers/Android.bp index 86f7f82dd02..2d08f5e3487 100644 --- a/system/osi/test/fuzzers/Android.bp +++ b/system/osi/test/fuzzers/Android.bp @@ -11,6 +11,9 @@ cc_defaults { name: "libosi_fuzz_defaults", defaults: ["fluoride_osi_defaults"], host_supported: true, + cflags: [ + "-Wno-missing-prototypes", + ], static_libs: [ "libosi", ], diff --git a/system/packet/tests/fuzzers/Android.bp b/system/packet/tests/fuzzers/Android.bp index b002967ae20..e15bbdc9932 100644 --- a/system/packet/tests/fuzzers/Android.bp +++ b/system/packet/tests/fuzzers/Android.bp @@ -37,6 +37,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -76,6 +77,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -115,6 +117,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -154,6 +157,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -193,6 +197,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -232,6 +237,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -271,6 +277,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -310,6 +317,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -349,6 +357,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -388,6 +397,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -427,6 +437,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -466,6 +477,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -505,6 +517,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -544,6 +557,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -583,6 +597,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -622,6 +637,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -661,6 +677,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -700,6 +717,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -739,6 +757,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -778,6 +797,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -817,6 +837,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -856,6 +877,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -895,6 +917,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -934,6 +957,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ @@ -973,6 +997,7 @@ cc_fuzz { "libgmock", ], cflags: [ + "-Wno-missing-prototypes", "-Wno-unused-parameter", ], shared_libs: [ diff --git a/system/packet/tests/fuzzers/reject_packet_fuzzer.cc b/system/packet/tests/fuzzers/reject_packet_fuzzer.cc index 5c0ae1d3c73..b06b73f55cb 100644 --- a/system/packet/tests/fuzzers/reject_packet_fuzzer.cc +++ b/system/packet/tests/fuzzers/reject_packet_fuzzer.cc @@ -22,6 +22,9 @@ #include "avrcp_test_packets.h" #include "packet_test_helper.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace avrcp { diff --git a/system/profile/avrcp/connection_handler.cc b/system/profile/avrcp/connection_handler.cc index 1c443ca5277..3d6a67c964e 100644 --- a/system/profile/avrcp/connection_handler.cc +++ b/system/profile/avrcp/connection_handler.cc @@ -38,6 +38,9 @@ #include "stack/include/sdp_status.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + extern bool btif_av_peer_is_connected_sink(const RawAddress& peer_address); extern bool btif_av_peer_is_connected_source(const RawAddress& peer_address); extern bool btif_av_both_enable(void); diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index 526ef2e2f4a..1851e88d346 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -36,6 +36,9 @@ #include "packet/avrcp/set_player_application_setting_value.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + extern bool btif_av_peer_is_connected_sink(const RawAddress& peer_address); extern bool btif_av_both_enable(void); extern bool btif_av_src_sink_coexist_enabled(void); diff --git a/system/profile/avrcp/tests/avrcp_connection_handler_test.cc b/system/profile/avrcp/tests/avrcp_connection_handler_test.cc index ac8217a267b..cd1ecbae759 100644 --- a/system/profile/avrcp/tests/avrcp_connection_handler_test.cc +++ b/system/profile/avrcp/tests/avrcp_connection_handler_test.cc @@ -28,6 +28,9 @@ #include "stack/include/sdp_status.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::testing::_; using ::testing::DoAll; using ::testing::MockFunction; diff --git a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc index e7c02fd7589..5f69a6ac59d 100644 --- a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc +++ b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc @@ -21,6 +21,9 @@ #include "packet_test_helper.h" #include "pass_through_packet.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool btif_av_src_sink_coexist_enabled(void) { return true; } namespace bluetooth { diff --git a/system/profile/avrcp/tests/avrcp_device_test.cc b/system/profile/avrcp/tests/avrcp_device_test.cc index 135de5017b1..24cf0ff87df 100644 --- a/system/profile/avrcp/tests/avrcp_device_test.cc +++ b/system/profile/avrcp/tests/avrcp_device_test.cc @@ -30,6 +30,9 @@ #include "tests/packet_test_helper.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool btif_av_src_sink_coexist_enabled(void) { return true; } namespace bluetooth { diff --git a/system/profile/sdp/common/test/data_element_reader_test.cc b/system/profile/sdp/common/test/data_element_reader_test.cc index 71ba0a4a698..3203098e0d1 100644 --- a/system/profile/sdp/common/test/data_element_reader_test.cc +++ b/system/profile/sdp/common/test/data_element_reader_test.cc @@ -20,6 +20,9 @@ #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace sdp { diff --git a/system/rust/Android.bp b/system/rust/Android.bp index 251ef9008e3..4281cae7aea 100644 --- a/system/rust/Android.bp +++ b/system/rust/Android.bp @@ -110,6 +110,10 @@ rust_test_host { cc_library_static { name: "libbluetooth_core_rs_bridge", defaults: ["bluetooth_cflags"], + cflags: [ + // The generated code triggers these warnings. + "-Wno-missing-prototypes", + ], srcs: [ "src/connection/ffi/connection_shim.cc", "src/core/ffi/module.cc", diff --git a/system/stack/Android.bp b/system/stack/Android.bp index ff7c956bcd4..ba06dddfa81 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -327,16 +327,13 @@ cc_library_static { cc_defaults { name: "btstack_fuzzer_default", host_supported: true, - cflags: [ - "-Wall", - "-Werror", - "-Wextra", - // Mocked components have too many unused parameters - "-Wno-unused-parameter", - ], defaults: [ + "bluetooth_cflags", "bluetooth_flatbuffer_bundler_defaults", ], + cflags: [ + "-Wno-unused-parameter", + ], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index aa21fe3fede..c7ad2adbbd4 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -32,6 +32,9 @@ #include "stack/include/l2cap_hci_link_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index dc5d1dc3d5e..858f139d272 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -89,6 +89,9 @@ #define PROPERTY_AUTO_FLUSH_TIMEOUT "bluetooth.core.classic.auto_flush_timeout" #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using bluetooth::legacy::hci::GetInterface; diff --git a/system/stack/acl/btm_pm.cc b/system/stack/acl/btm_pm.cc index 3edf3980876..f77efd47b71 100644 --- a/system/stack/acl/btm_pm.cc +++ b/system/stack/acl/btm_pm.cc @@ -50,6 +50,9 @@ #include "stack/include/btm_status.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; void l2c_OnHciModeChangeSendPendingPackets(RawAddress remote); diff --git a/system/stack/ais/ais_ble.cc b/system/stack/ais/ais_ble.cc index c35c4a2acb2..879797ed34d 100644 --- a/system/stack/ais/ais_ble.cc +++ b/system/stack/ais/ais_ble.cc @@ -28,6 +28,9 @@ #include "stack/include/gatt_api.h" #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using bluetooth::log::error; using bluetooth::log::warn; diff --git a/system/stack/avdt/avdt_msg.cc b/system/stack/avdt/avdt_msg.cc index 28f3d129326..28535033d2c 100644 --- a/system/stack/avdt/avdt_msg.cc +++ b/system/stack/avdt/avdt_msg.cc @@ -41,6 +41,9 @@ #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/stack/avdt/avdt_scb_act.cc b/system/stack/avdt/avdt_scb_act.cc index 3785876c4bb..4eec721d465 100644 --- a/system/stack/avdt/avdt_scb_act.cc +++ b/system/stack/avdt/avdt_scb_act.cc @@ -39,6 +39,9 @@ #include "stack/include/l2cap_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /* This table is used to lookup the callback event that matches a particular diff --git a/system/stack/avrc/avrc_api.cc b/system/stack/avrc/avrc_api.cc index 6d97d5c6af2..60d1da067ed 100644 --- a/system/stack/avrc/avrc_api.cc +++ b/system/stack/avrc/avrc_api.cc @@ -42,6 +42,9 @@ #include "storage/config_keys.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/stack/avrc/avrc_bld_tg.cc b/system/stack/avrc/avrc_bld_tg.cc index e6ca39167e5..63902322931 100644 --- a/system/stack/avrc/avrc_bld_tg.cc +++ b/system/stack/avrc/avrc_bld_tg.cc @@ -31,6 +31,9 @@ #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/stack/avrc/avrc_pars_ct.cc b/system/stack/avrc/avrc_pars_ct.cc index 805365cc6f9..045cee3dd2f 100644 --- a/system/stack/avrc/avrc_pars_ct.cc +++ b/system/stack/avrc/avrc_pars_ct.cc @@ -26,6 +26,9 @@ #include "osi/include/osi.h" #include "stack/include/bt_types.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** diff --git a/system/stack/bnep/bnep_utils.cc b/system/stack/bnep/bnep_utils.cc index 06566d85b3f..252facf668f 100644 --- a/system/stack/bnep/bnep_utils.cc +++ b/system/stack/bnep/bnep_utils.cc @@ -37,6 +37,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using bluetooth::Uuid; diff --git a/system/stack/btm/btm_ble.cc b/system/stack/btm/btm_ble.cc index 1e7cbfece13..e71dfe67fa1 100644 --- a/system/stack/btm/btm_ble.cc +++ b/system/stack/btm/btm_ble.cc @@ -42,6 +42,9 @@ #include "stack/include/gatt_api.h" #include "stack/include/hcimsgs.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc index 6a7f61a3a85..bd92d9121dd 100644 --- a/system/stack/btm/btm_ble_gap.cc +++ b/system/stack/btm/btm_ble_gap.cc @@ -69,6 +69,9 @@ #include "types/ble_address_with_type.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/btm/btm_ble_privacy.cc b/system/stack/btm/btm_ble_privacy.cc index eeb20980205..bba53e0448b 100644 --- a/system/stack/btm/btm_ble_privacy.cc +++ b/system/stack/btm/btm_ble_privacy.cc @@ -40,6 +40,9 @@ #include "stack/include/btm_client_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/btm/btm_ble_sec.cc b/system/stack/btm/btm_ble_sec.cc index bd6283189f6..9927751bb1e 100644 --- a/system/stack/btm/btm_ble_sec.cc +++ b/system/stack/btm/btm_ble_sec.cc @@ -60,6 +60,9 @@ #include "stack/include/smp_api_types.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc index 76a69b5fbe3..ad5ad9de159 100644 --- a/system/stack/btm/btm_dev.cc +++ b/system/stack/btm/btm_dev.cc @@ -48,6 +48,9 @@ #include "stack/include/l2cap_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc index 9b627f41e8a..86f4af00e4b 100644 --- a/system/stack/btm/btm_devctl.cc +++ b/system/stack/btm/btm_devctl.cc @@ -49,6 +49,9 @@ #include "stack/include/l2cap_controller_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace ::bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/btm/btm_inq.cc b/system/stack/btm/btm_inq.cc index a2992cb2103..255b9cb69bc 100644 --- a/system/stack/btm/btm_inq.cc +++ b/system/stack/btm/btm_inq.cc @@ -85,6 +85,9 @@ ((uint32_t)1 << (((uint32_t)(service)) % BTM_EIR_ARRAY_BITS))) >> \ (((uint32_t)(service)) % BTM_EIR_ARRAY_BITS)) +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { constexpr char kBtmLogTag[] = "SCAN"; diff --git a/system/stack/btm/btm_iot_config.cc b/system/stack/btm/btm_iot_config.cc index d1fc5b2f24f..27990d3e867 100644 --- a/system/stack/btm/btm_iot_config.cc +++ b/system/stack/btm/btm_iot_config.cc @@ -26,6 +26,9 @@ #include "stack/acl/acl.h" #include "stack/include/btm_client_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************* diff --git a/system/stack/btm/btm_main.cc b/system/stack/btm/btm_main.cc index 0925a68f047..d07769b1571 100644 --- a/system/stack/btm/btm_main.cc +++ b/system/stack/btm/btm_main.cc @@ -33,6 +33,9 @@ #include "stack/include/security_client_callbacks.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /* Global BTM control block structure diff --git a/system/stack/btm/btm_sco.cc b/system/stack/btm/btm_sco.cc index 5ad176fc56c..e7a33541d9e 100644 --- a/system/stack/btm/btm_sco.cc +++ b/system/stack/btm/btm_sco.cc @@ -63,6 +63,9 @@ #include "stack/include/stack_metrics_logging.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + extern tBTM_CB btm_cb; /* Default to allow enhanced connections where supported. */ diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index f310bde7bd6..bbb765b3801 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -77,6 +77,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { constexpr char kBtmLogTag[] = "SEC"; diff --git a/system/stack/btu/btu_event.cc b/system/stack/btu/btu_event.cc index d1bfc5b2caa..02d701d6f61 100644 --- a/system/stack/btu/btu_event.cc +++ b/system/stack/btu/btu_event.cc @@ -20,6 +20,9 @@ #include "stack/include/bt_types.h" #include "stack/include/btu_hcif.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::hci::IsoManager; void btu_hci_msg_process(BT_HDR* p_msg) { diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc index d392f29fdde..f184626779a 100644 --- a/system/stack/btu/btu_hcif.cc +++ b/system/stack/btu/btu_hcif.cc @@ -59,6 +59,9 @@ #include "types/hci_role.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using base::Location; using bluetooth::hci::IsoManager; diff --git a/system/stack/fuzzers/avrc_fuzzer.cc b/system/stack/fuzzers/avrc_fuzzer.cc index 21662d28b41..03267249fd5 100644 --- a/system/stack/fuzzers/avrc_fuzzer.cc +++ b/system/stack/fuzzers/avrc_fuzzer.cc @@ -34,6 +34,9 @@ #include "test/mock/mock_stack_l2cap_ble.h" #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/fuzzers/bnep_fuzzer.cc b/system/stack/fuzzers/bnep_fuzzer.cc index 6976ccd6025..4ad6bffb0b5 100644 --- a/system/stack/fuzzers/bnep_fuzzer.cc +++ b/system/stack/fuzzers/bnep_fuzzer.cc @@ -31,6 +31,9 @@ #include "test/mock/mock_stack_l2cap_ble.h" #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; namespace { diff --git a/system/stack/fuzzers/gatt_fuzzer.cc b/system/stack/fuzzers/gatt_fuzzer.cc index e2ccb35eff3..3aa0f8ce01e 100644 --- a/system/stack/fuzzers/gatt_fuzzer.cc +++ b/system/stack/fuzzers/gatt_fuzzer.cc @@ -33,6 +33,9 @@ #include "test/mock/mock_stack_l2cap_api.h" #include "test/mock/mock_stack_l2cap_ble.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; bt_status_t do_in_main_thread(base::OnceCallback) { // this is not properly mocked, so we use abort to catch if this is used in diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc index f8714cc3f30..f9fff7ff80a 100644 --- a/system/stack/fuzzers/l2cap_fuzzer.cc +++ b/system/stack/fuzzers/l2cap_fuzzer.cc @@ -41,6 +41,9 @@ #include "test/mock/mock_stack_acl.h" #include "test/mock/mock_stack_btm_devctl.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using testing::Return; using namespace bluetooth; diff --git a/system/stack/fuzzers/rfcomm_fuzzer.cc b/system/stack/fuzzers/rfcomm_fuzzer.cc index 8652c7e90a0..238354d6424 100644 --- a/system/stack/fuzzers/rfcomm_fuzzer.cc +++ b/system/stack/fuzzers/rfcomm_fuzzer.cc @@ -38,6 +38,9 @@ #include "test/mock/mock_stack_l2cap_ble.h" #include "test/rfcomm/stack_rfcomm_test_utils.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace hal { class SnoopLogger; diff --git a/system/stack/fuzzers/sdp_fuzzer.cc b/system/stack/fuzzers/sdp_fuzzer.cc index de994d415e8..8fbcb8f7d8c 100644 --- a/system/stack/fuzzers/sdp_fuzzer.cc +++ b/system/stack/fuzzers/sdp_fuzzer.cc @@ -31,6 +31,9 @@ #include "test/mock/mock_stack_l2cap_api.h" #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { #define SDP_DB_SIZE 0x10000 diff --git a/system/stack/fuzzers/smp_fuzzer.cc b/system/stack/fuzzers/smp_fuzzer.cc index 4c66c4c4bcc..e8f3ba8d914 100644 --- a/system/stack/fuzzers/smp_fuzzer.cc +++ b/system/stack/fuzzers/smp_fuzzer.cc @@ -33,6 +33,9 @@ #include "test/mock/mock_stack_l2cap_api.h" #include "test/mock/mock_stack_l2cap_ble.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bluetooth::common::MessageLoopThread* main_thread_ptr = nullptr; bluetooth::common::MessageLoopThread* get_main_thread() { return main_thread_ptr; } diff --git a/system/stack/gap/gap_ble.cc b/system/stack/gap/gap_ble.cc index a1853eeb349..92c826afc31 100644 --- a/system/stack/gap/gap_ble.cc +++ b/system/stack/gap/gap_ble.cc @@ -33,6 +33,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/gap/gap_conn.cc b/system/stack/gap/gap_conn.cc index 1375b3e838e..8208edf4d53 100644 --- a/system/stack/gap/gap_conn.cc +++ b/system/stack/gap/gap_conn.cc @@ -34,6 +34,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /* Define the GAP Connection Control Block */ diff --git a/system/stack/gatt/att_protocol.cc b/system/stack/gatt/att_protocol.cc index af8cfdc7d85..60bf695167b 100644 --- a/system/stack/gatt/att_protocol.cc +++ b/system/stack/gatt/att_protocol.cc @@ -37,6 +37,9 @@ #define GATT_OP_CODE_SIZE 1 #define GATT_START_END_HANDLE_SIZE 4 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::StringPrintf; using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/gatt/connection_manager.cc b/system/stack/gatt/connection_manager.cc index ccd902da008..6b6f8a71ba6 100644 --- a/system/stack/gatt/connection_manager.cc +++ b/system/stack/gatt/connection_manager.cc @@ -41,6 +41,9 @@ #define DIRECT_CONNECT_TIMEOUT (30 * 1000) /* 30 seconds */ +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; constexpr char kBtmLogTag[] = "TA"; diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index ba5ec145275..3715292f89e 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -52,6 +52,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; diff --git a/system/stack/gatt/gatt_attr.cc b/system/stack/gatt/gatt_attr.cc index 9cb7d1323da..a4b2935c52c 100644 --- a/system/stack/gatt/gatt_attr.cc +++ b/system/stack/gatt/gatt_attr.cc @@ -40,6 +40,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using base::StringPrintf; using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/gatt/gatt_auth.cc b/system/stack/gatt/gatt_auth.cc index 7ed047b8ebe..fc11e2570ca 100644 --- a/system/stack/gatt/gatt_auth.cc +++ b/system/stack/gatt/gatt_auth.cc @@ -39,6 +39,9 @@ #include "stack/include/btm_status.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************* diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc index de1923a4dc3..28ee7fb4a34 100644 --- a/system/stack/gatt/gatt_cl.cc +++ b/system/stack/gatt/gatt_cl.cc @@ -51,6 +51,9 @@ #define L2CAP_PKT_OVERHEAD 4 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using bluetooth::Uuid; using bluetooth::eatt::EattChannel; diff --git a/system/stack/gatt/gatt_db.cc b/system/stack/gatt/gatt_db.cc index 1b5cf2385be..2141fd47eba 100644 --- a/system/stack/gatt/gatt_db.cc +++ b/system/stack/gatt/gatt_db.cc @@ -31,6 +31,9 @@ #include "stack/include/l2cap_types.h" #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index d8c5a1c75ac..8e0c4d0b937 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -52,6 +52,9 @@ #include "stack/include/srvc_api.h" // tDIS_VALUE #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::eatt::EattExtension; using namespace bluetooth; diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 979bd4a3c26..cfd48fbeb48 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -44,6 +44,9 @@ #define GATT_MTU_REQ_MIN_LEN 2 #define L2CAP_PKT_OVERHEAD 4 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using bluetooth::eatt::EattChannel; using bluetooth::eatt::EattExtension; diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index f15b880d88c..1aa1923857f 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -49,6 +49,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr); using namespace bluetooth::legacy::stack::sdp; diff --git a/system/stack/hid/hidh_api.cc b/system/stack/hid/hidh_api.cc index d61bc06bdff..72c30e3f13a 100644 --- a/system/stack/hid/hidh_api.cc +++ b/system/stack/hid/hidh_api.cc @@ -43,6 +43,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; using namespace bluetooth::legacy::stack::sdp; using bluetooth::Uuid; diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc index ec703e6dfa8..cb66ec209db 100644 --- a/system/stack/l2cap/l2c_api.cc +++ b/system/stack/l2cap/l2c_api.cc @@ -49,6 +49,9 @@ #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern fixed_queue_t* btu_general_alarm_queue; diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index ab182357911..e2a1fbceff9 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -57,6 +57,9 @@ #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/stack/l2cap/l2c_ble_conn_params.cc b/system/stack/l2cap/l2c_ble_conn_params.cc index 46d1b0d0b41..f617e59d5df 100644 --- a/system/stack/l2cap/l2c_ble_conn_params.cc +++ b/system/stack/l2cap/l2c_ble_conn_params.cc @@ -43,6 +43,9 @@ #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; void l2cble_start_conn_update(tL2C_LCB* p_lcb); diff --git a/system/stack/l2cap/l2c_link.cc b/system/stack/l2cap/l2c_link.cc index d9582b65c3a..baf9d4c2dd3 100644 --- a/system/stack/l2cap/l2c_link.cc +++ b/system/stack/l2cap/l2c_link.cc @@ -46,6 +46,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/l2cap/l2c_main.cc b/system/stack/l2cap/l2c_main.cc index 9d5645e9c19..92592831097 100644 --- a/system/stack/l2cap/l2c_main.cc +++ b/system/stack/l2cap/l2c_main.cc @@ -40,6 +40,9 @@ #include "stack/include/l2cdefs.h" #include "stack/l2cap/l2c_int.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************/ diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index 8e69744d82a..a45d2c1e688 100644 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -50,6 +50,9 @@ #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb); // TODO Move diff --git a/system/stack/rfcomm/rfc_ts_frames.cc b/system/stack/rfcomm/rfc_ts_frames.cc index b0b4b1c143f..93bf02a0a42 100644 --- a/system/stack/rfcomm/rfc_ts_frames.cc +++ b/system/stack/rfcomm/rfc_ts_frames.cc @@ -35,6 +35,9 @@ #include "stack/rfcomm/port_int.h" #include "stack/rfcomm/rfc_int.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************* diff --git a/system/stack/rnr/remote_name_request.cc b/system/stack/rnr/remote_name_request.cc index da7ae2c2e92..ed6801a8553 100644 --- a/system/stack/rnr/remote_name_request.cc +++ b/system/stack/rnr/remote_name_request.cc @@ -27,6 +27,9 @@ #include "stack/btm/security_device_record.h" #include "stack/include/btm_client_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + extern tBTM_CB btm_cb; using namespace bluetooth; diff --git a/system/stack/sdp/sdp_db.cc b/system/stack/sdp/sdp_db.cc index b381089aa44..e7bd4cf37b8 100644 --- a/system/stack/sdp/sdp_db.cc +++ b/system/stack/sdp/sdp_db.cc @@ -38,6 +38,9 @@ #include "stack/sdp/sdp_discovery_db.h" #include "stack/sdp/sdpint.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /******************************************************************************* diff --git a/system/stack/sdp/sdp_discovery.cc b/system/stack/sdp/sdp_discovery.cc index 73f15d1acd1..01429371044 100644 --- a/system/stack/sdp/sdp_discovery.cc +++ b/system/stack/sdp/sdp_discovery.cc @@ -38,6 +38,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/sdp/sdp_server.cc b/system/stack/sdp/sdp_server.cc index 7061cc5885b..58a17727cfa 100644 --- a/system/stack/sdp/sdp_server.cc +++ b/system/stack/sdp/sdp_server.cc @@ -61,6 +61,9 @@ #define PBAP_1_2 0x0102 #define PBAP_1_2_BL_LEN 14 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /* Used to set PBAP local SDP device record for PBAP 1.2 upgrade */ diff --git a/system/stack/smp/smp_act.cc b/system/stack/smp/smp_act.cc index 655a2061e58..07502a2a889 100644 --- a/system/stack/smp/smp_act.cc +++ b/system/stack/smp/smp_act.cc @@ -42,6 +42,9 @@ #include "stack/include/smp_api_types.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/stack/smp/smp_keys.cc b/system/stack/smp/smp_keys.cc index 7369ff0ccc7..801a3d4e630 100644 --- a/system/stack/smp/smp_keys.cc +++ b/system/stack/smp/smp_keys.cc @@ -47,6 +47,9 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::common::BindOnce; using bluetooth::common::OnceCallback; using crypto_toolbox::aes_128; diff --git a/system/stack/smp/smp_utils.cc b/system/stack/smp/smp_utils.cc index 848bced48a4..01a045bda9d 100644 --- a/system/stack/smp/smp_utils.cc +++ b/system/stack/smp/smp_utils.cc @@ -71,6 +71,9 @@ Check*/) #define SMP_PAIR_KEYPR_NOTIF_SIZE (1 /* opcode */ + 1 /*Notif Type*/) +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; namespace { diff --git a/system/stack/srvc/srvc_dis.cc b/system/stack/srvc/srvc_dis.cc index 402ec14febc..58f6befd11e 100644 --- a/system/stack/srvc/srvc_dis.cc +++ b/system/stack/srvc/srvc_dis.cc @@ -33,6 +33,9 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; static const uint16_t dis_attr_uuid[] = { diff --git a/system/stack/test/a2dp/mock_bta_av_codec.cc b/system/stack/test/a2dp/mock_bta_av_codec.cc index c4a30a70812..c261bebfe98 100644 --- a/system/stack/test/a2dp/mock_bta_av_codec.cc +++ b/system/stack/test/a2dp/mock_bta_av_codec.cc @@ -16,4 +16,7 @@ #include "a2dp_codec_api.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) { return nullptr; } diff --git a/system/stack/test/btm/stack_btm_inq_test.cc b/system/stack/test/btm/stack_btm_inq_test.cc index 6262915a2ca..160ff6124f5 100644 --- a/system/stack/test/btm/stack_btm_inq_test.cc +++ b/system/stack/test/btm/stack_btm_inq_test.cc @@ -36,6 +36,9 @@ #include "test/mock/mock_main_shim_entry.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + extern tBTM_CB btm_cb; using bluetooth::common::ContextualCallback; diff --git a/system/stack/test/btm/stack_btm_test.cc b/system/stack/test/btm/stack_btm_test.cc index aeaaf689139..c1b90eeef9e 100644 --- a/system/stack/test/btm/stack_btm_test.cc +++ b/system/stack/test/btm/stack_btm_test.cc @@ -38,6 +38,9 @@ #include "test/mock/mock_main_shim_entry.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::testing::_; using ::testing::Each; using ::testing::Eq; diff --git a/system/stack/test/btm_iso_test.cc b/system/stack/test/btm_iso_test.cc index 489a356f4e0..50a4948b34b 100644 --- a/system/stack/test/btm_iso_test.cc +++ b/system/stack/test/btm_iso_test.cc @@ -32,6 +32,9 @@ #include "test/mock/mock_main_shim_entry.h" #include "test/mock/mock_main_shim_hci_layer.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::hci::IsoManager; using testing::_; using testing::AnyNumber; diff --git a/system/stack/test/common/mock_btif_storage.cc b/system/stack/test/common/mock_btif_storage.cc index ae11b0d3e4e..bf51e41c636 100644 --- a/system/stack/test/common/mock_btif_storage.cc +++ b/system/stack/test/common/mock_btif_storage.cc @@ -20,6 +20,9 @@ #include "stack/include/btm_sec_api_types.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + static bluetooth::manager::MockBtifStorageInterface* btif_storage_interface = nullptr; void bluetooth::manager::SetMockBtifStorageInterface( diff --git a/system/stack/test/common/mock_btm_api_layer.cc b/system/stack/test/common/mock_btm_api_layer.cc index cc9389289da..735d6be806f 100644 --- a/system/stack/test/common/mock_btm_api_layer.cc +++ b/system/stack/test/common/mock_btm_api_layer.cc @@ -17,6 +17,9 @@ #include "mock_btm_api_layer.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + static bluetooth::manager::MockBtmApiInterface* btm_api_interface = nullptr; void bluetooth::manager::SetMockBtmApiInterface(MockBtmApiInterface* mock_btm_api_interface) { @@ -40,4 +43,4 @@ bool BTM_IsLinkKeyKnown(const RawAddress& remote_bd_addr, tBT_TRANSPORT transpor uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr) { return btm_api_interface->ReadSecKeySize(bd_addr); -} \ No newline at end of file +} diff --git a/system/stack/test/common/mock_btm_layer.cc b/system/stack/test/common/mock_btm_layer.cc index 2dd17a3a7e3..acfb6357a62 100644 --- a/system/stack/test/common/mock_btm_layer.cc +++ b/system/stack/test/common/mock_btm_layer.cc @@ -22,6 +22,9 @@ #include "stack/include/rfcdefs.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + static bluetooth::manager::MockBtmSecurityInternalInterface* btm_security_internal_interface = nullptr; diff --git a/system/stack/test/common/mock_btu_layer.cc b/system/stack/test/common/mock_btu_layer.cc index cc9ef53c79b..26ab4b58c56 100644 --- a/system/stack/test/common/mock_btu_layer.cc +++ b/system/stack/test/common/mock_btu_layer.cc @@ -18,4 +18,7 @@ #include "common/message_loop_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; } diff --git a/system/stack/test/common/mock_l2cap_layer.cc b/system/stack/test/common/mock_l2cap_layer.cc index 287743dab73..c2c6ab18a00 100644 --- a/system/stack/test/common/mock_l2cap_layer.cc +++ b/system/stack/test/common/mock_l2cap_layer.cc @@ -23,6 +23,9 @@ #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + static bluetooth::l2cap::MockL2capInterface* l2cap_interface = nullptr; void bluetooth::l2cap::SetMockInterface(MockL2capInterface* mock_l2cap_interface) { diff --git a/system/stack/test/common/mock_stack_avdt_msg.cc b/system/stack/test/common/mock_stack_avdt_msg.cc index 86848618452..76ff6ac8c46 100644 --- a/system/stack/test/common/mock_stack_avdt_msg.cc +++ b/system/stack/test/common/mock_stack_avdt_msg.cc @@ -25,6 +25,9 @@ * Need to consider more sophisticated existing methods. */ +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + static std::vector _rsp_sig_ids{}; void avdt_msg_send_rsp(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) { diff --git a/system/stack/test/eatt/eatt_test.cc b/system/stack/test/eatt/eatt_test.cc index d89fb268bce..0965fc59877 100644 --- a/system/stack/test/eatt/eatt_test.cc +++ b/system/stack/test/eatt/eatt_test.cc @@ -36,6 +36,9 @@ #include "test/mock/mock_stack_l2cap_interface.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using testing::_; using testing::DoAll; using testing::MockFunction; diff --git a/system/stack/test/fuzzers/Android.bp b/system/stack/test/fuzzers/Android.bp index d7559762c6c..92de791e1b1 100644 --- a/system/stack/test/fuzzers/Android.bp +++ b/system/stack/test/fuzzers/Android.bp @@ -15,6 +15,10 @@ cc_defaults { "latest_android_hardware_bluetooth_audio_ndk_static", "latest_android_media_audio_common_types_ndk_static", ], + cflags: [ + // Fuzzers are hopeless.. + "-Wno-missing-prototypes", + ], include_dirs: [ "packages/modules/Bluetooth/system/", "packages/modules/Bluetooth/system/gd/", diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc index cab85bcfa64..564a2e555a6 100644 --- a/system/stack/test/gatt/mock_gatt_utils_ref.cc +++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc @@ -18,6 +18,9 @@ #include "stack/include/bt_hdr.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + /** stack/gatt/connection_manager.cc */ namespace connection_manager { bool background_connect_remove(uint8_t app_id, const RawAddress& address) { return false; } diff --git a/system/stack/test/gatt_connection_manager_test.cc b/system/stack/test/gatt_connection_manager_test.cc index 16eabbc6711..e7912106083 100644 --- a/system/stack/test/gatt_connection_manager_test.cc +++ b/system/stack/test/gatt_connection_manager_test.cc @@ -12,6 +12,9 @@ #include "stack/btm/neighbor_inquiry.h" #include "stack/gatt/connection_manager.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using testing::_; using testing::DoAll; using testing::Mock; diff --git a/system/stack/test/hid/stack_hid_test.cc b/system/stack/test/hid/stack_hid_test.cc index f9f27fbdf24..7fc527ac2bf 100644 --- a/system/stack/test/hid/stack_hid_test.cc +++ b/system/stack/test/hid/stack_hid_test.cc @@ -23,6 +23,9 @@ #include "test/common/mock_functions.h" #include "test/mock/mock_stack_l2cap_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; } tHCI_REASON btm_get_acl_disc_reason_code(void) { return HCI_SUCCESS; } diff --git a/system/stack/test/rfcomm/stack_rfcomm_test.cc b/system/stack/test/rfcomm/stack_rfcomm_test.cc index 4e94eb40149..c15bd8fb554 100644 --- a/system/stack/test/rfcomm/stack_rfcomm_test.cc +++ b/system/stack/test/rfcomm/stack_rfcomm_test.cc @@ -34,6 +34,9 @@ #include "stack/test/rfcomm/stack_rfcomm_test_utils.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; std::string DumpByteBufferToString(uint8_t* p_data, size_t len) { diff --git a/system/stack/test/rfcomm/stack_rfcomm_test_utils.cc b/system/stack/test/rfcomm/stack_rfcomm_test_utils.cc index 77e3c39e807..f11639bc0f7 100644 --- a/system/stack/test/rfcomm/stack_rfcomm_test_utils.cc +++ b/system/stack/test/rfcomm/stack_rfcomm_test_utils.cc @@ -25,6 +25,9 @@ #include "stack/rfcomm/rfc_int.h" #include "stack_test_packet_utils.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace rfcomm { diff --git a/system/stack/test/sdp/stack_sdp_test.cc b/system/stack/test/sdp/stack_sdp_test.cc index 8c1bd4e2538..a60f808b4b2 100644 --- a/system/stack/test/sdp/stack_sdp_test.cc +++ b/system/stack/test/sdp/stack_sdp_test.cc @@ -36,6 +36,9 @@ #define BT_DEFAULT_BUFFER_SIZE (4096 + 16) #endif +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using ::testing::_; using ::testing::DoAll; using ::testing::Invoke; diff --git a/system/stack/test/sdp/stack_sdp_utils_test.cc b/system/stack/test/sdp/stack_sdp_utils_test.cc index 764df1affcf..c089f48df7a 100644 --- a/system/stack/test/sdp/stack_sdp_utils_test.cc +++ b/system/stack/test/sdp/stack_sdp_utils_test.cc @@ -49,6 +49,9 @@ #define HFP_PROFILE_MINOR_VERSION_6 0x06 #define HFP_PROFILE_MINOR_VERSION_7 0x07 +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + static int L2CA_ConnectReqWithSecurity_cid = 0x42; static RawAddress addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6}); static tSDP_DISCOVERY_DB* sdp_db = nullptr; diff --git a/system/stack/test/stack_rnr_test.cc b/system/stack/test/stack_rnr_test.cc index 0299e1574f1..e2b0b3cb732 100644 --- a/system/stack/test/stack_rnr_test.cc +++ b/system/stack/test/stack_rnr_test.cc @@ -27,6 +27,9 @@ #include "test/mock/mock_osi_thread.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + extern tBTM_CB btm_cb; bool ble_evt_type_is_connectable(uint16_t /* evt_type */) { return true; } diff --git a/system/stack/test/stack_smp_test.cc b/system/stack/test/stack_smp_test.cc index cfe0368bcb7..31a006d2496 100644 --- a/system/stack/test/stack_smp_test.cc +++ b/system/stack/test/stack_smp_test.cc @@ -35,6 +35,9 @@ #include "types/hci_role.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using testing::StrEq; tBTM_CB btm_cb; diff --git a/system/test/common/jni_thread.cc b/system/test/common/jni_thread.cc index ae3e00d7ab0..984b2337c15 100644 --- a/system/test/common/jni_thread.cc +++ b/system/test/common/jni_thread.cc @@ -23,6 +23,9 @@ #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + std::queue do_in_jni_thread_task_queue; void run_one_jni_thread_task() { diff --git a/system/test/common/main_handler.cc b/system/test/common/main_handler.cc index 0849ef37db7..8728ab1cd8b 100644 --- a/system/test/common/main_handler.cc +++ b/system/test/common/main_handler.cc @@ -29,6 +29,9 @@ #include "include/hardware/bluetooth.h" #include "os/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using bluetooth::common::MessageLoopThread; using BtMainClosure = std::function; diff --git a/system/test/common/stack_config.cc b/system/test/common/stack_config.cc index 41366496e97..c1bc7e7ae70 100644 --- a/system/test/common/stack_config.cc +++ b/system/test/common/stack_config.cc @@ -22,6 +22,9 @@ #include #include +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + const std::string kSmpOptions("mock smp options"); const std::string kBroadcastAudioConfigOptions("mock broadcast audio config options"); bool get_pts_avrcp_test(void) { return false; } diff --git a/system/test/common/sync_main_handler.cc b/system/test/common/sync_main_handler.cc index 7c59f61a1fd..1b6219e761b 100644 --- a/system/test/common/sync_main_handler.cc +++ b/system/test/common/sync_main_handler.cc @@ -19,6 +19,9 @@ #include "stack/include/main_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + constexpr int sync_timeout_in_ms = 3000; void sync_main_handler() { diff --git a/system/test/fake/fake_looper.cc b/system/test/fake/fake_looper.cc index 81bcdfb4eed..b7d94dd8490 100644 --- a/system/test/fake/fake_looper.cc +++ b/system/test/fake/fake_looper.cc @@ -27,6 +27,9 @@ #include "osi/include/allocator.h" #include "test/fake/fake_thread.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + pid_t get_thread_id() { #if defined(OS_MACOSX) return pthread_mach_thread_np(pthread_self()); diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp index f05be39aa6f..3349dc607ea 100644 --- a/system/test/headless/Android.bp +++ b/system/test/headless/Android.bp @@ -35,9 +35,6 @@ cc_binary { "latest_android_media_audio_common_types_ndk_static", ], cflags: [ - "-Wall", - "-Werror", - "-Wextra", "-Wno-date-time", ], generated_headers: [ diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc index 21553a73f75..0ff3155258e 100644 --- a/system/test/headless/headless.cc +++ b/system/test/headless/headless.cc @@ -33,6 +33,9 @@ #include "test/headless/messenger.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // // Aggregate disparate variables from callback API into unified single structure // diff --git a/system/test/headless/log.cc b/system/test/headless/log.cc index 6105a9afcff..4714b98c2d1 100644 --- a/system/test/headless/log.cc +++ b/system/test/headless/log.cc @@ -24,6 +24,9 @@ #include "internal_include/bt_trace.h" #include "stack/btm/btm_int_types.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + std::chrono::system_clock::time_point _prev = std::chrono::system_clock::now(); extern tBTM_CB btm_cb; diff --git a/system/test/headless/messenger.cc b/system/test/headless/messenger.cc index e8dba380d6d..4e84ad1c49a 100644 --- a/system/test/headless/messenger.cc +++ b/system/test/headless/messenger.cc @@ -26,6 +26,9 @@ #include "test/headless/interface.h" #include "test/headless/log.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth::test::headless; using namespace std::chrono_literals; diff --git a/system/test/headless/read/name.cc b/system/test/headless/read/name.cc index e1e0940a079..0dc5aa38b76 100644 --- a/system/test/headless/read/name.cc +++ b/system/test/headless/read/name.cc @@ -29,6 +29,9 @@ #include "test/headless/headless.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + std::promise promise_; void RemoteNameCallback(const tBTM_REMOTE_DEV_NAME* data) { promise_.set_value(*data); } diff --git a/system/test/headless/util.cc b/system/test/headless/util.cc index df3a15fd0ea..8c18a3893f3 100644 --- a/system/test/headless/util.cc +++ b/system/test/headless/util.cc @@ -19,6 +19,9 @@ #include "include/hardware/bluetooth.h" #include "osi/include/properties.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool is_android_running() { #ifdef __ANDROID__ char value[PROPERTY_VALUE_MAX]; diff --git a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc index 09d095627e1..52c9e0eb86a 100644 --- a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc +++ b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc @@ -32,6 +32,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace audio_hal_interface_a2dp_encoding { diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc index 44dfcf279af..0dbe67dadc4 100644 --- a/system/test/mock/mock_bluetooth_interface.cc +++ b/system/test/mock/mock_bluetooth_interface.cc @@ -21,6 +21,9 @@ #include "stack/include/bt_octets.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void invoke_adapter_state_changed_cb(bt_state_t /* state */) {} void invoke_adapter_properties_cb(bt_status_t /* status */, int /* num_properties */, bt_property_t* /* properties */) {} diff --git a/system/test/mock/mock_bta_ag_api.cc b/system/test/mock/mock_bta_ag_api.cc index 41138e20a15..f59d2e4ed5c 100644 --- a/system/test/mock/mock_bta_ag_api.cc +++ b/system/test/mock/mock_bta_ag_api.cc @@ -30,6 +30,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tBTA_STATUS BTA_AgEnable(tBTA_AG_CBACK* /* p_cback */) { inc_func_call_count(__func__); return BTA_SUCCESS; diff --git a/system/test/mock/mock_bta_ag_sco.cc b/system/test/mock/mock_bta_ag_sco.cc index 09da576c348..b290955c6a5 100644 --- a/system/test/mock/mock_bta_ag_sco.cc +++ b/system/test/mock/mock_bta_ag_sco.cc @@ -27,6 +27,9 @@ #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // Original usings using HfpInterface = bluetooth::audio::hfp::HfpClientInterface; using namespace bluetooth; diff --git a/system/test/mock/mock_bta_ar.cc b/system/test/mock/mock_bta_ar.cc index ff2ec4368c4..a75e40fa055 100644 --- a/system/test/mock/mock_bta_ar.cc +++ b/system/test/mock/mock_bta_ar.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void bta_ar_avdt_conn(tBTA_SYS_ID /* sys_id */, const RawAddress& /* bd_addr */, uint8_t /* scb_index */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_bta_av_ci.cc b/system/test/mock/mock_bta_av_ci.cc index 05904cf0290..07da0478615 100644 --- a/system/test/mock/mock_bta_av_ci.cc +++ b/system/test/mock/mock_bta_av_ci.cc @@ -22,6 +22,9 @@ #include "bta/include/bta_av_api.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void bta_av_ci_setconfig(tBTA_AV_HNDL /* bta_av_handle */, uint8_t /* err_code */, uint8_t /* category */, bool /* recfg_needed */, uint8_t /* avdt_handle */) { diff --git a/system/test/mock/mock_bta_dm_act.cc b/system/test/mock/mock_bta_dm_act.cc index 601b70cacc1..243ad3e1fe2 100644 --- a/system/test/mock/mock_bta_dm_act.cc +++ b/system/test/mock/mock_bta_dm_act.cc @@ -31,6 +31,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace bta_dm_act { diff --git a/system/test/mock/mock_bta_dm_api.cc b/system/test/mock/mock_bta_dm_api.cc index ece4a9d69bf..2d8129d0a53 100644 --- a/system/test/mock/mock_bta_dm_api.cc +++ b/system/test/mock/mock_bta_dm_api.cc @@ -32,6 +32,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace bta_dm_api { diff --git a/system/test/mock/mock_bta_dm_main.cc b/system/test/mock/mock_bta_dm_main.cc index 87a441ee6f7..4c559cba3c7 100644 --- a/system/test/mock/mock_bta_dm_main.cc +++ b/system/test/mock/mock_bta_dm_main.cc @@ -29,6 +29,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace bta_dm_main { diff --git a/system/test/mock/mock_bta_gattc_api.cc b/system/test/mock/mock_bta_gattc_api.cc index 0ea4a4ddc70..1649ce8980c 100644 --- a/system/test/mock/mock_bta_gattc_api.cc +++ b/system/test/mock/mock_bta_gattc_api.cc @@ -30,6 +30,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void BTA_GATTC_Disable(void) { inc_func_call_count(__func__); } const gatt::Characteristic* BTA_GATTC_GetCharacteristic(uint16_t /* conn_id */, uint16_t /* handle */) { diff --git a/system/test/mock/mock_bta_gatts_api.cc b/system/test/mock/mock_bta_gatts_api.cc index 1e3e7707488..ca13a393c87 100644 --- a/system/test/mock/mock_bta_gatts_api.cc +++ b/system/test/mock/mock_bta_gatts_api.cc @@ -32,6 +32,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void BTA_GATTS_Disable(void) { inc_func_call_count(__func__); } void BTA_GATTS_AppDeregister(tGATT_IF /* server_if */) { inc_func_call_count(__func__); } void BTA_GATTS_AppRegister(const bluetooth::Uuid& /* app_uuid */, tBTA_GATTS_CBACK* /* p_cback */, diff --git a/system/test/mock/mock_bta_hh_utils.cc b/system/test/mock/mock_bta_hh_utils.cc index e45da059663..a9224212424 100644 --- a/system/test/mock/mock_bta_hh_utils.cc +++ b/system/test/mock/mock_bta_hh_utils.cc @@ -30,6 +30,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace bta_hh_utils { diff --git a/system/test/mock/mock_bta_pan_api.cc b/system/test/mock/mock_bta_pan_api.cc index 4f353f3aa17..0e662c5d191 100644 --- a/system/test/mock/mock_bta_pan_api.cc +++ b/system/test/mock/mock_bta_pan_api.cc @@ -25,6 +25,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void BTA_PanClose(uint16_t /* handle */) { inc_func_call_count(__func__); } void BTA_PanDisable(void) { inc_func_call_count(__func__); } void BTA_PanEnable(tBTA_PAN_CBACK /* p_cback */) { inc_func_call_count(__func__); } diff --git a/system/test/mock/mock_bta_pan_ci.cc b/system/test/mock/mock_bta_pan_ci.cc index 1b75c364a62..ca15b4c33bb 100644 --- a/system/test/mock/mock_bta_pan_ci.cc +++ b/system/test/mock/mock_bta_pan_ci.cc @@ -23,6 +23,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + BT_HDR* bta_pan_ci_readbuf(uint16_t /* handle */, RawAddress& /* src */, RawAddress& /* dst */, uint16_t* /* p_protocol */, bool* /* p_ext */, bool* /* p_forward */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_bta_sdp_api.cc b/system/test/mock/mock_bta_sdp_api.cc index 1f5b0159afa..966920221a5 100644 --- a/system/test/mock/mock_bta_sdp_api.cc +++ b/system/test/mock/mock_bta_sdp_api.cc @@ -28,6 +28,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace bta_sdp_api { diff --git a/system/test/mock/mock_bta_sys_conn.cc b/system/test/mock/mock_bta_sys_conn.cc index 84cf5037dd0..e8453047a37 100644 --- a/system/test/mock/mock_bta_sys_conn.cc +++ b/system/test/mock/mock_bta_sys_conn.cc @@ -26,6 +26,9 @@ #include "types/hci_role.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void bta_sys_app_close(tBTA_SYS_ID /* id */, uint8_t /* app_id */, const RawAddress& /* peer_addr */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_bta_sys_main.cc b/system/test/mock/mock_bta_sys_main.cc index 32f5b24c2dc..709be46b211 100644 --- a/system/test/mock/mock_bta_sys_main.cc +++ b/system/test/mock/mock_bta_sys_main.cc @@ -30,6 +30,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace bta_sys_main { diff --git a/system/test/mock/mock_btif_av.cc b/system/test/mock/mock_btif_av.cc index 966771378f3..9b4a7065720 100644 --- a/system/test/mock/mock_btif_av.cc +++ b/system/test/mock/mock_btif_av.cc @@ -32,6 +32,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace btif_av { diff --git a/system/test/mock/mock_btif_bluetooth.cc b/system/test/mock/mock_btif_bluetooth.cc index fe77f0789cf..c101c6ee4d3 100644 --- a/system/test/mock/mock_btif_bluetooth.cc +++ b/system/test/mock/mock_btif_bluetooth.cc @@ -31,6 +31,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace btif_bluetooth { diff --git a/system/test/mock/mock_btif_bqr.cc b/system/test/mock/mock_btif_bqr.cc index b6347043739..2a17a7778e7 100644 --- a/system/test/mock/mock_btif_bqr.cc +++ b/system/test/mock/mock_btif_bqr.cc @@ -23,6 +23,9 @@ #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace bqr { diff --git a/system/test/mock/mock_btif_bta_pan_co_rx.cc b/system/test/mock/mock_btif_bta_pan_co_rx.cc index d1df05d8e1f..741104b2283 100644 --- a/system/test/mock/mock_btif_bta_pan_co_rx.cc +++ b/system/test/mock/mock_btif_bta_pan_co_rx.cc @@ -30,6 +30,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace btif_bta_pan_co_rx { diff --git a/system/test/mock/mock_btif_co_bta_av_co.cc b/system/test/mock/mock_btif_co_bta_av_co.cc index 2c7f9f39fec..efa055531f3 100644 --- a/system/test/mock/mock_btif_co_bta_av_co.cc +++ b/system/test/mock/mock_btif_co_bta_av_co.cc @@ -31,6 +31,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace btif_co_bta_av_co { diff --git a/system/test/mock/mock_btif_co_bta_dm_co.cc b/system/test/mock/mock_btif_co_bta_dm_co.cc index d2e4244b07d..656b94cda25 100644 --- a/system/test/mock/mock_btif_co_bta_dm_co.cc +++ b/system/test/mock/mock_btif_co_bta_dm_co.cc @@ -24,6 +24,9 @@ #include "bta/sys/bta_sys.h" #include "internal_include/bte_appl.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tBTE_APPL_CFG bte_appl_cfg = {BTA_LE_AUTH_REQ_SC_MITM_BOND, // Authentication requirements BTM_IO_CAP_UNKNOWN, BTM_BLE_INITIATOR_KEY_SIZE, BTM_BLE_RESPONDER_KEY_SIZE, BTM_BLE_MAX_KEY_SIZE}; diff --git a/system/test/mock/mock_btif_co_bta_hh_co.cc b/system/test/mock/mock_btif_co_bta_hh_co.cc index 9ea3994b52f..788317f56ca 100644 --- a/system/test/mock/mock_btif_co_bta_hh_co.cc +++ b/system/test/mock/mock_btif_co_bta_hh_co.cc @@ -27,6 +27,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + int bta_hh_co_write(int /* fd */, uint8_t* /* rpt */, uint16_t /* len */) { inc_func_call_count(__func__); return 0; diff --git a/system/test/mock/mock_btif_config.cc b/system/test/mock/mock_btif_config.cc index 1d8bafa8cbc..549fe4bf44e 100644 --- a/system/test/mock/mock_btif_config.cc +++ b/system/test/mock/mock_btif_config.cc @@ -33,6 +33,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace btif_config { diff --git a/system/test/mock/mock_btif_core.cc b/system/test/mock/mock_btif_core.cc index faf22890786..001c5b553f6 100644 --- a/system/test/mock/mock_btif_core.cc +++ b/system/test/mock/mock_btif_core.cc @@ -29,6 +29,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool btif_is_dut_mode() { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_btif_dm.cc b/system/test/mock/mock_btif_dm.cc index 0f6698d3a2c..f4baf57ea1c 100644 --- a/system/test/mock/mock_btif_dm.cc +++ b/system/test/mock/mock_btif_dm.cc @@ -31,6 +31,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + struct uid_set_t; bool btif_dm_pairing_is_busy() { diff --git a/system/test/mock/mock_btif_hf.cc b/system/test/mock/mock_btif_hf.cc index e49f8f09fc8..3004d4a97ed 100644 --- a/system/test/mock/mock_btif_hf.cc +++ b/system/test/mock/mock_btif_hf.cc @@ -29,6 +29,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace btif_hf { diff --git a/system/test/mock/mock_btif_profile_storage.cc b/system/test/mock/mock_btif_profile_storage.cc index 8658ab740bd..a89422a7ee8 100644 --- a/system/test/mock/mock_btif_profile_storage.cc +++ b/system/test/mock/mock_btif_profile_storage.cc @@ -27,6 +27,9 @@ #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // Original usings using bluetooth::Uuid; diff --git a/system/test/mock/mock_btif_sock_rfc.cc b/system/test/mock/mock_btif_sock_rfc.cc index 5ab162a470c..49b5b117fa0 100644 --- a/system/test/mock/mock_btif_sock_rfc.cc +++ b/system/test/mock/mock_btif_sock_rfc.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // Original usings using bluetooth::Uuid; diff --git a/system/test/mock/mock_btif_stack_manager.cc b/system/test/mock/mock_btif_stack_manager.cc index 77a87303453..bdc4150ca9d 100644 --- a/system/test/mock/mock_btif_stack_manager.cc +++ b/system/test/mock/mock_btif_stack_manager.cc @@ -22,6 +22,9 @@ #include "osi/include/future.h" #include "test/common/core_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + static future_t* hack_future; future_t* stack_manager_get_hack_future() { return hack_future; } diff --git a/system/test/mock/mock_btif_storage.cc b/system/test/mock/mock_btif_storage.cc index f0990f6022d..1f327eeb162 100644 --- a/system/test/mock/mock_btif_storage.cc +++ b/system/test/mock/mock_btif_storage.cc @@ -27,6 +27,9 @@ #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // Original usings using bluetooth::Uuid; diff --git a/system/test/mock/mock_btif_util.cc b/system/test/mock/mock_btif_util.cc index f361608b208..662fa3fcbc9 100644 --- a/system/test/mock/mock_btif_util.cc +++ b/system/test/mock/mock_btif_util.cc @@ -30,6 +30,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace btif_util { diff --git a/system/test/mock/mock_btu_task.cc b/system/test/mock/mock_btu_task.cc index 5c3cf08a8d9..bf5bf2a314e 100644 --- a/system/test/mock/mock_btu_task.cc +++ b/system/test/mock/mock_btu_task.cc @@ -22,4 +22,7 @@ #include "stack/include/bt_hdr.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void btu_hci_msg_process(BT_HDR* /* p_msg */) { inc_func_call_count(__func__); } diff --git a/system/test/mock/mock_device_esco_parameters.cc b/system/test/mock/mock_device_esco_parameters.cc index 311daf7f0b8..5a9a3ad2632 100644 --- a/system/test/mock/mock_device_esco_parameters.cc +++ b/system/test/mock/mock_device_esco_parameters.cc @@ -27,6 +27,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace device_esco_parameters { diff --git a/system/test/mock/mock_device_interop.cc b/system/test/mock/mock_device_interop.cc index 4f98781b236..0f7a0a27e50 100644 --- a/system/test/mock/mock_device_interop.cc +++ b/system/test/mock/mock_device_interop.cc @@ -31,6 +31,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace device_interop { diff --git a/system/test/mock/mock_device_iot_config.cc b/system/test/mock/mock_device_iot_config.cc index 6188e58c8d6..61308a883aa 100644 --- a/system/test/mock/mock_device_iot_config.cc +++ b/system/test/mock/mock_device_iot_config.cc @@ -21,6 +21,9 @@ #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace device_iot_config { diff --git a/system/test/mock/mock_jni_thread.cc b/system/test/mock/mock_jni_thread.cc index 29af8f640c6..eb8b6db093a 100644 --- a/system/test/mock/mock_jni_thread.cc +++ b/system/test/mock/mock_jni_thread.cc @@ -28,6 +28,9 @@ #include "test/common/jni_thread.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool is_on_jni_thread() { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_main_shim_acl.cc b/system/test/mock/mock_main_shim_acl.cc index 9db83b7ff44..2c11004ba26 100644 --- a/system/test/mock/mock_main_shim_acl.cc +++ b/system/test/mock/mock_main_shim_acl.cc @@ -33,6 +33,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; void DumpsysL2cap(int /* fd */) { inc_func_call_count(__func__); } diff --git a/system/test/mock/mock_main_shim_acl_interface.cc b/system/test/mock/mock_main_shim_acl_interface.cc index 56075efa582..2ba60144431 100644 --- a/system/test/mock/mock_main_shim_acl_interface.cc +++ b/system/test/mock/mock_main_shim_acl_interface.cc @@ -16,6 +16,9 @@ #include "main/shim/acl_interface.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth { namespace shim { namespace legacy { diff --git a/system/test/mock/mock_main_shim_hci_layer.cc b/system/test/mock/mock_main_shim_hci_layer.cc index d9c715d380c..c02f009333a 100644 --- a/system/test/mock/mock_main_shim_hci_layer.cc +++ b/system/test/mock/mock_main_shim_hci_layer.cc @@ -31,6 +31,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace bluetooth::shim { namespace testing { const hci_t* test_interface = nullptr; diff --git a/system/test/mock/mock_osi_future.cc b/system/test/mock/mock_osi_future.cc index 4a6122a105b..c7c98a3ac77 100644 --- a/system/test/mock/mock_osi_future.cc +++ b/system/test/mock/mock_osi_future.cc @@ -27,6 +27,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace osi_future { diff --git a/system/test/mock/mock_osi_list.cc b/system/test/mock/mock_osi_list.cc index bed9c042876..2aa2bfd4623 100644 --- a/system/test/mock/mock_osi_list.cc +++ b/system/test/mock/mock_osi_list.cc @@ -27,6 +27,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace osi_list { diff --git a/system/test/mock/mock_osi_mutex.cc b/system/test/mock/mock_osi_mutex.cc index 25fb8de3cf5..ff8aa0afb2c 100644 --- a/system/test/mock/mock_osi_mutex.cc +++ b/system/test/mock/mock_osi_mutex.cc @@ -27,6 +27,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace osi_mutex { diff --git a/system/test/mock/mock_osi_properties.cc b/system/test/mock/mock_osi_properties.cc index cc2231125d0..f22b3e0e1df 100644 --- a/system/test/mock/mock_osi_properties.cc +++ b/system/test/mock/mock_osi_properties.cc @@ -30,6 +30,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace osi_properties { diff --git a/system/test/mock/mock_osi_socket.cc b/system/test/mock/mock_osi_socket.cc index 6fecb157e45..7daa32c5e2a 100644 --- a/system/test/mock/mock_osi_socket.cc +++ b/system/test/mock/mock_osi_socket.cc @@ -27,6 +27,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace osi_socket { diff --git a/system/test/mock/mock_osi_thread_scheduler.cc b/system/test/mock/mock_osi_thread_scheduler.cc index ff978b2b4d4..a248efc327b 100644 --- a/system/test/mock/mock_osi_thread_scheduler.cc +++ b/system/test/mock/mock_osi_thread_scheduler.cc @@ -27,6 +27,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace osi_thread_scheduler { diff --git a/system/test/mock/mock_osi_wakelock.cc b/system/test/mock/mock_osi_wakelock.cc index 03cb33a2f4b..b2805a7cba3 100644 --- a/system/test/mock/mock_osi_wakelock.cc +++ b/system/test/mock/mock_osi_wakelock.cc @@ -27,6 +27,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace osi_wakelock { diff --git a/system/test/mock/mock_stack_a2dp_sbc.cc b/system/test/mock/mock_stack_a2dp_sbc.cc index d612278939a..7423ae79cb6 100644 --- a/system/test/mock/mock_stack_a2dp_sbc.cc +++ b/system/test/mock/mock_stack_a2dp_sbc.cc @@ -31,6 +31,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_a2dp_sbc { diff --git a/system/test/mock/mock_stack_acl.cc b/system/test/mock/mock_stack_acl.cc index 89ad3da5f0b..22822f2f89c 100644 --- a/system/test/mock/mock_stack_acl.cc +++ b/system/test/mock/mock_stack_acl.cc @@ -35,6 +35,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_acl { diff --git a/system/test/mock/mock_stack_acl_ble.cc b/system/test/mock/mock_stack_acl_ble.cc index c073b50aa5c..e403a923e3a 100644 --- a/system/test/mock/mock_stack_acl_ble.cc +++ b/system/test/mock/mock_stack_acl_ble.cc @@ -27,6 +27,9 @@ #include "types/hci_role.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void acl_ble_connection_fail(const tBLE_BD_ADDR& /* address_with_type */, uint16_t /* handle */, bool /* enhanced */, tHCI_STATUS /* status */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_acl_btm_pm.cc b/system/test/mock/mock_stack_acl_btm_pm.cc index f57dbf641ca..8ae9f01c631 100644 --- a/system/test/mock/mock_stack_acl_btm_pm.cc +++ b/system/test/mock/mock_stack_acl_btm_pm.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool BTM_ReadPowerMode(const RawAddress& /* remote_bda */, tBTM_PM_MODE* /* p_mode */) { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_stack_avrc_api.cc b/system/test/mock/mock_stack_avrc_api.cc index a3fa3c7c570..5409f753452 100644 --- a/system/test/mock/mock_stack_avrc_api.cc +++ b/system/test/mock/mock_stack_avrc_api.cc @@ -25,6 +25,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool avrcp_absolute_volume_is_enabled() { inc_func_call_count(__func__); return true; diff --git a/system/test/mock/mock_stack_avrc_apt.cc b/system/test/mock/mock_stack_avrc_apt.cc index 7b3cead1670..2380d1756eb 100644 --- a/system/test/mock/mock_stack_avrc_apt.cc +++ b/system/test/mock/mock_stack_avrc_apt.cc @@ -30,6 +30,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_avrc_apt { diff --git a/system/test/mock/mock_stack_avrc_bld_tg.cc b/system/test/mock/mock_stack_avrc_bld_tg.cc index c060df0d22f..6a1f126edd7 100644 --- a/system/test/mock/mock_stack_avrc_bld_tg.cc +++ b/system/test/mock/mock_stack_avrc_bld_tg.cc @@ -24,6 +24,9 @@ #include "stack/include/bt_hdr.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tAVRC_STS AVRC_BldResponse(uint8_t /* handle */, tAVRC_RESPONSE* /* p_rsp */, BT_HDR** /* pp_pkt */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_avrc_pars.ct.cc b/system/test/mock/mock_stack_avrc_pars.ct.cc index 7635d796378..511231e11d4 100644 --- a/system/test/mock/mock_stack_avrc_pars.ct.cc +++ b/system/test/mock/mock_stack_avrc_pars.ct.cc @@ -23,6 +23,9 @@ #include "avrc_defs.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* /* p_msg */, tAVRC_RESPONSE* /* p_result */, uint8_t* /* p_buf */, uint16_t* /* buf_len */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_avrc_utils.cc b/system/test/mock/mock_stack_avrc_utils.cc index 78a37cbeb25..b4eca59731a 100644 --- a/system/test/mock/mock_stack_avrc_utils.cc +++ b/system/test/mock/mock_stack_avrc_utils.cc @@ -30,6 +30,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_avrc_utils { diff --git a/system/test/mock/mock_stack_btm_ble.cc b/system/test/mock/mock_stack_btm_ble.cc index 71137f0a20d..7e1a2154b95 100644 --- a/system/test/mock/mock_stack_btm_ble.cc +++ b/system/test/mock/mock_stack_btm_ble.cc @@ -33,6 +33,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_ble { @@ -302,3 +305,7 @@ void read_phy_cb(base::Callback BTM_BleGetPeerLTK(const RawAddress /* address */) { return std::nullopt; } + +std::optional BTM_BleGetIdentityAddress(const RawAddress /* address */) { + return std::nullopt; +} diff --git a/system/test/mock/mock_stack_btm_ble.h b/system/test/mock/mock_stack_btm_ble.h index 7d5013b8593..1133b60b4cf 100644 --- a/system/test/mock/mock_stack_btm_ble.h +++ b/system/test/mock/mock_stack_btm_ble.h @@ -575,8 +575,4 @@ extern struct read_phy_cb read_phy_cb; } // namespace mock } // namespace test -std::optional BTM_BleGetIdentityAddress(const RawAddress /* address */) { - return std::nullopt; -} - // END mockcify generation diff --git a/system/test/mock/mock_stack_btm_ble_addr.cc b/system/test/mock/mock_stack_btm_ble_addr.cc index d2b841f6de4..2a52fb57eae 100644 --- a/system/test/mock/mock_stack_btm_ble_addr.cc +++ b/system/test/mock/mock_stack_btm_ble_addr.cc @@ -32,6 +32,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_ble_addr { diff --git a/system/test/mock/mock_stack_btm_ble_bgconn.cc b/system/test/mock/mock_stack_btm_ble_bgconn.cc index afdab209f84..2d14a1a5b6d 100644 --- a/system/test/mock/mock_stack_btm_ble_bgconn.cc +++ b/system/test/mock/mock_stack_btm_ble_bgconn.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // Mocked compile conditionals, if any // Mocked internal structures, if any struct BackgroundConnection {}; diff --git a/system/test/mock/mock_stack_btm_ble_gap.cc b/system/test/mock/mock_stack_btm_ble_gap.cc index 444093a5e60..93e134c4a85 100644 --- a/system/test/mock/mock_stack_btm_ble_gap.cc +++ b/system/test/mock/mock_stack_btm_ble_gap.cc @@ -34,6 +34,9 @@ #include "types/ble_address_with_type.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using StartSyncCb = base::Callback; diff --git a/system/test/mock/mock_stack_btm_ble_privacy.cc b/system/test/mock/mock_stack_btm_ble_privacy.cc index f4cb9929f06..7781d9cc753 100644 --- a/system/test/mock/mock_stack_btm_ble_privacy.cc +++ b/system/test/mock/mock_stack_btm_ble_privacy.cc @@ -30,6 +30,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_ble_privacy { diff --git a/system/test/mock/mock_stack_btm_dev.cc b/system/test/mock/mock_stack_btm_dev.cc index d14b67113d6..1dc2da8646d 100644 --- a/system/test/mock/mock_stack_btm_dev.cc +++ b/system/test/mock/mock_stack_btm_dev.cc @@ -32,6 +32,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_dev { diff --git a/system/test/mock/mock_stack_btm_devctl.cc b/system/test/mock/mock_stack_btm_devctl.cc index f50ee833963..fc27fab6dbb 100644 --- a/system/test/mock/mock_stack_btm_devctl.cc +++ b/system/test/mock/mock_stack_btm_devctl.cc @@ -29,6 +29,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_devctl { diff --git a/system/test/mock/mock_stack_btm_hfp_lc3_encoder.cc b/system/test/mock/mock_stack_btm_hfp_lc3_encoder.cc index 49056eb490d..d2ed992484a 100644 --- a/system/test/mock/mock_stack_btm_hfp_lc3_encoder.cc +++ b/system/test/mock/mock_stack_btm_hfp_lc3_encoder.cc @@ -32,6 +32,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_hfp_lc3_encoder { diff --git a/system/test/mock/mock_stack_btm_hfp_msbc_decoder.cc b/system/test/mock/mock_stack_btm_hfp_msbc_decoder.cc index a2597e84551..dea537f621b 100644 --- a/system/test/mock/mock_stack_btm_hfp_msbc_decoder.cc +++ b/system/test/mock/mock_stack_btm_hfp_msbc_decoder.cc @@ -30,6 +30,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_hfp_msbc_decoder { diff --git a/system/test/mock/mock_stack_btm_hfp_msbc_encoder.cc b/system/test/mock/mock_stack_btm_hfp_msbc_encoder.cc index 219578455b7..3c38e667549 100644 --- a/system/test/mock/mock_stack_btm_hfp_msbc_encoder.cc +++ b/system/test/mock/mock_stack_btm_hfp_msbc_encoder.cc @@ -33,6 +33,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_hfp_msbc_encoder { diff --git a/system/test/mock/mock_stack_btm_inq.cc b/system/test/mock/mock_stack_btm_inq.cc index 82fd00d2b1d..b137827eb95 100644 --- a/system/test/mock/mock_stack_btm_inq.cc +++ b/system/test/mock/mock_stack_btm_inq.cc @@ -31,6 +31,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_inq { diff --git a/system/test/mock/mock_stack_btm_interface.cc b/system/test/mock/mock_stack_btm_interface.cc index 5f5004428ee..7016d4b6622 100644 --- a/system/test/mock/mock_stack_btm_interface.cc +++ b/system/test/mock/mock_stack_btm_interface.cc @@ -26,6 +26,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // Test accessible feature page uint8_t hci_feature_bytes_per_page[HCI_FEATURE_BYTES_PER_PAGE] = {}; diff --git a/system/test/mock/mock_stack_btm_main.cc b/system/test/mock/mock_stack_btm_main.cc index 75fb6ca4001..e188d0d89ca 100644 --- a/system/test/mock/mock_stack_btm_main.cc +++ b/system/test/mock/mock_stack_btm_main.cc @@ -25,6 +25,9 @@ #include "types/ble_address_with_type.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void BTM_LogHistory(const std::string& /* tag */, const RawAddress& /* bd_addr */, const std::string& /* msg */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_btm_sco.cc b/system/test/mock/mock_stack_btm_sco.cc index aa717496039..949e635b09e 100644 --- a/system/test/mock/mock_stack_btm_sco.cc +++ b/system/test/mock/mock_stack_btm_sco.cc @@ -30,6 +30,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool btm_sco_removed(uint16_t /* hci_handle */, tHCI_REASON /* reason */) { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_stack_btm_sec.cc b/system/test/mock/mock_stack_btm_sec.cc index 4be4fe51cb2..2bfd288187f 100644 --- a/system/test/mock/mock_stack_btm_sec.cc +++ b/system/test/mock/mock_stack_btm_sec.cc @@ -34,6 +34,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_btm_sec { diff --git a/system/test/mock/mock_stack_btu_hcif.cc b/system/test/mock/mock_stack_btu_hcif.cc index 90ea7db6419..4fecd7bcc2c 100644 --- a/system/test/mock/mock_stack_btu_hcif.cc +++ b/system/test/mock/mock_stack_btu_hcif.cc @@ -28,6 +28,9 @@ #include "stack/include/btu_hcif.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using hci_cmd_cb = base::OnceCallback; diff --git a/system/test/mock/mock_stack_gap_ble.cc b/system/test/mock/mock_stack_gap_ble.cc index e07b77b1d36..941ca7d1875 100644 --- a/system/test/mock/mock_stack_gap_ble.cc +++ b/system/test/mock/mock_stack_gap_ble.cc @@ -25,6 +25,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool GAP_BleCancelReadPeerDevName(const RawAddress& /* peer_bda */) { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_stack_gap_conn.cc b/system/test/mock/mock_stack_gap_conn.cc index 0ef505d14a8..6fb98265881 100644 --- a/system/test/mock/mock_stack_gap_conn.cc +++ b/system/test/mock/mock_stack_gap_conn.cc @@ -24,6 +24,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + const RawAddress* GAP_ConnGetRemoteAddr(uint16_t /* gap_handle */) { inc_func_call_count(__func__); return nullptr; diff --git a/system/test/mock/mock_stack_gatt.cc b/system/test/mock/mock_stack_gatt.cc index 9e66fc17000..297ec5747ae 100644 --- a/system/test/mock/mock_stack_gatt.cc +++ b/system/test/mock/mock_stack_gatt.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/bluetooth/uuid.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; tGATT_HDL_LIST_ELEM elem; // gatt_add_an_item_to_list diff --git a/system/test/mock/mock_stack_gatt_api.cc b/system/test/mock/mock_stack_gatt_api.cc index 9ad7f8786b2..947cc1a7288 100644 --- a/system/test/mock/mock_stack_gatt_api.cc +++ b/system/test/mock/mock_stack_gatt_api.cc @@ -27,6 +27,9 @@ #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + // Original usings using bluetooth::Uuid; diff --git a/system/test/mock/mock_stack_gatt_attr.cc b/system/test/mock/mock_stack_gatt_attr.cc index a1dd9a51036..6de9539644f 100644 --- a/system/test/mock/mock_stack_gatt_attr.cc +++ b/system/test/mock/mock_stack_gatt_attr.cc @@ -28,6 +28,9 @@ #include "types/bt_transport.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + uint16_t gatt_profile_find_conn_id_by_bd_addr(const RawAddress& /* remote_bda */) { inc_func_call_count(__func__); return 0; diff --git a/system/test/mock/mock_stack_gatt_auth.cc b/system/test/mock/mock_stack_gatt_auth.cc index e676da43fd7..1e59e8152d0 100644 --- a/system/test/mock/mock_stack_gatt_auth.cc +++ b/system/test/mock/mock_stack_gatt_auth.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool gatt_security_check_start(tGATT_CLCB* /* p_clcb */) { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_stack_gatt_main.cc b/system/test/mock/mock_stack_gatt_main.cc index 66cb4a5844e..8ef0677c495 100644 --- a/system/test/mock/mock_stack_gatt_main.cc +++ b/system/test/mock/mock_stack_gatt_main.cc @@ -25,6 +25,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void gatt_init(void) { inc_func_call_count(__func__); } bool gatt_act_connect(tGATT_REG* /* p_reg */, const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */, tBT_TRANSPORT /* transport */, diff --git a/system/test/mock/mock_stack_hcic_hciblecmds.cc b/system/test/mock/mock_stack_hcic_hciblecmds.cc index 354d4c151f4..b44bbff0a40 100644 --- a/system/test/mock/mock_stack_hcic_hciblecmds.cc +++ b/system/test/mock/mock_stack_hcic_hciblecmds.cc @@ -28,6 +28,9 @@ // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_hcic_hciblecmds { diff --git a/system/test/mock/mock_stack_hidh.cc b/system/test/mock/mock_stack_hidh.cc index c3ab99f9692..15b16a4ae83 100644 --- a/system/test/mock/mock_stack_hidh.cc +++ b/system/test/mock/mock_stack_hidh.cc @@ -27,6 +27,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tHID_STATUS HID_HostAddDev(const RawAddress& /* addr */, uint16_t /* attr_mask */, uint8_t* /* handle */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_l2cap_api.cc b/system/test/mock/mock_stack_l2cap_api.cc index 1fec5442f59..c360878a6b6 100644 --- a/system/test/mock/mock_stack_l2cap_api.cc +++ b/system/test/mock/mock_stack_l2cap_api.cc @@ -29,6 +29,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_l2cap_api { diff --git a/system/test/mock/mock_stack_l2cap_ble.cc b/system/test/mock/mock_stack_l2cap_ble.cc index 9c25b6f3486..ee625765160 100644 --- a/system/test/mock/mock_stack_l2cap_ble.cc +++ b/system/test/mock/mock_stack_l2cap_ble.cc @@ -31,6 +31,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_l2cap_ble { diff --git a/system/test/mock/mock_stack_l2cap_link.cc b/system/test/mock/mock_stack_l2cap_link.cc index cc05d9a566f..c0dea8c1fc4 100644 --- a/system/test/mock/mock_stack_l2cap_link.cc +++ b/system/test/mock/mock_stack_l2cap_link.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* /* p_lcb */) { inc_func_call_count(__func__); return nullptr; diff --git a/system/test/mock/mock_stack_l2cap_main.cc b/system/test/mock/mock_stack_l2cap_main.cc index fb33fed8f8e..606551fb989 100644 --- a/system/test/mock/mock_stack_l2cap_main.cc +++ b/system/test/mock/mock_stack_l2cap_main.cc @@ -23,6 +23,9 @@ #include "stack/l2cap/l2c_int.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tL2CAP_DW_RESULT l2c_data_write(uint16_t /* cid */, BT_HDR* /* p_data */, uint16_t /* flags */) { inc_func_call_count(__func__); return tL2CAP_DW_RESULT::FAILED; diff --git a/system/test/mock/mock_stack_l2cap_utils.cc b/system/test/mock/mock_stack_l2cap_utils.cc index 1838912b015..accdc728813 100644 --- a/system/test/mock/mock_stack_l2cap_utils.cc +++ b/system/test/mock/mock_stack_l2cap_utils.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + BT_HDR* l2cu_build_header(tL2C_LCB* /* p_lcb */, uint16_t /* len */, uint8_t /* cmd */, uint8_t /* signal_id */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_metrics_logging.cc b/system/test/mock/mock_stack_metrics_logging.cc index 6c21688de2b..7b1e54c1913 100644 --- a/system/test/mock/mock_stack_metrics_logging.cc +++ b/system/test/mock/mock_stack_metrics_logging.cc @@ -35,6 +35,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_metrics_logging { diff --git a/system/test/mock/mock_stack_sdp_api.cc b/system/test/mock/mock_stack_sdp_api.cc index 65db618c1c6..8ae3af47624 100644 --- a/system/test/mock/mock_stack_sdp_api.cc +++ b/system/test/mock/mock_stack_sdp_api.cc @@ -32,6 +32,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_sdp_api { diff --git a/system/test/mock/mock_stack_sdp_db.cc b/system/test/mock/mock_stack_sdp_db.cc index 91ddae982c7..57c4db280d4 100644 --- a/system/test/mock/mock_stack_sdp_db.cc +++ b/system/test/mock/mock_stack_sdp_db.cc @@ -22,6 +22,9 @@ #include "stack/sdp/sdpint.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool SDP_AddAdditionProtoLists(uint32_t /* handle */, uint16_t /* num_elem */, tSDP_PROTO_LIST_ELEM* /* p_proto_list */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_sdp_main.cc b/system/test/mock/mock_stack_sdp_main.cc index e66b58bbd08..751daba254f 100644 --- a/system/test/mock/mock_stack_sdp_main.cc +++ b/system/test/mock/mock_stack_sdp_main.cc @@ -23,6 +23,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + tCONN_CB* sdp_conn_originate(const RawAddress& /* p_bd_addr */) { inc_func_call_count(__func__); return nullptr; diff --git a/system/test/mock/mock_stack_sdp_server.cc b/system/test/mock/mock_stack_sdp_server.cc index 21e61901bd4..6802bc4d6ef 100644 --- a/system/test/mock/mock_stack_sdp_server.cc +++ b/system/test/mock/mock_stack_sdp_server.cc @@ -17,6 +17,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + void update_pce_entry_to_interop_database(RawAddress /* remote_addr */) { inc_func_call_count(__func__); } diff --git a/system/test/mock/mock_stack_security_client_interface.cc b/system/test/mock/mock_stack_security_client_interface.cc index d7dfeb28176..5ccb5e31dfd 100644 --- a/system/test/mock/mock_stack_security_client_interface.cc +++ b/system/test/mock/mock_stack_security_client_interface.cc @@ -19,6 +19,9 @@ #include "stack/include/security_client_callbacks.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace { // Initialize the working btm client interface to the default diff --git a/system/test/mock/mock_stack_smp_act.cc b/system/test/mock/mock_stack_smp_act.cc index 8f02fa14b25..486cf5dea7a 100644 --- a/system/test/mock/mock_stack_smp_act.cc +++ b/system/test/mock/mock_stack_smp_act.cc @@ -32,6 +32,9 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + namespace test { namespace mock { namespace stack_smp_act { diff --git a/system/test/mock/mock_stack_srvc_dis.cc b/system/test/mock/mock_stack_srvc_dis.cc index 365ff059eb4..abd467c3a90 100644 --- a/system/test/mock/mock_stack_srvc_dis.cc +++ b/system/test/mock/mock_stack_srvc_dis.cc @@ -26,6 +26,9 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + bool DIS_ReadDISInfo(const RawAddress& /* peer_bda */, tDIS_READ_CBACK* /* p_cback */, tDIS_ATTR_MASK /* mask */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_udrv_ulinux_uipc.cc b/system/test/mock/mock_udrv_ulinux_uipc.cc index cc6d354be33..daa7cc7f7cf 100644 --- a/system/test/mock/mock_udrv_ulinux_uipc.cc +++ b/system/test/mock/mock_udrv_ulinux_uipc.cc @@ -24,6 +24,9 @@ #include "test/common/mock_functions.h" #include "udrv/include/uipc.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + std::unique_ptr mock_uipc_init_ret; uint32_t mock_uipc_read_ret; bool mock_uipc_send_ret; diff --git a/system/test/stub/osi.cc b/system/test/stub/osi.cc index e41965e7f6e..cae495f2ca1 100644 --- a/system/test/stub/osi.cc +++ b/system/test/stub/osi.cc @@ -42,6 +42,9 @@ #include "test/common/fake_osi.h" #include "test/common/mock_functions.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + OsiObject::OsiObject(void* ptr) : ptr_(ptr) {} OsiObject::OsiObject(const void* ptr) : ptr_(const_cast(ptr)) {} diff --git a/system/udrv/ulinux/uipc.cc b/system/udrv/ulinux/uipc.cc index e90fe9a22a0..464e02b7f13 100644 --- a/system/udrv/ulinux/uipc.cc +++ b/system/udrv/ulinux/uipc.cc @@ -48,6 +48,9 @@ #include "osi/include/osi.h" #include "osi/include/socket_utils/sockets.h" +// TODO(b/369381361) Enfore -Wmissing-prototypes +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + using namespace bluetooth; /***************************************************************************** -- GitLab From a007dcd33e1e0a1c2cdf8ec79119970a36837bd1 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Mon, 23 Sep 2024 15:14:02 -0700 Subject: [PATCH 048/875] use snapshot instead of synchronized to simplify logic Bug: 367479598 Bug: 315234036 Flag: exempt, no logic change Test: atest HeadsetStateMachineTest Change-Id: I1ed8508d625e50c237b4f31a712e8de2ec4d303d --- .../src/com/android/bluetooth/hfp/HeadsetStateMachine.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java index cd15b65c412..52cc028e9f7 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java @@ -1795,11 +1795,12 @@ class HeadsetStateMachine extends StateMachine { * BluetoothHeadset#STATE_AUDIO_CONNECTING}, or {@link * BluetoothHeadset#STATE_AUDIO_CONNECTED} */ - public synchronized int getAudioState() { - if (mCurrentState == null) { + public int getAudioState() { + HeadsetStateBase state = mCurrentState; + if (state == null) { return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; } - return mCurrentState.getAudioStateInt(); + return state.getAudioStateInt(); } public long getConnectingTimestampMs() { -- GitLab From 69af983939a547a5b6e7b66ccbd30e4d9215c8b3 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Mon, 23 Sep 2024 14:43:38 -0700 Subject: [PATCH 049/875] move Audio related API outside synchronize to avoid deadlock 1. move Audio Manager out of synchronize 2. move phone call status check from java to native Bug: 367479598 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio and HFP session type only enabled when flag is enabled Test: atest HeadsetStateMachineTest Change-Id: I0a41c8d3e9d49568c9f435707d9dedb6f5b7bfaa --- .../android/bluetooth/hfp/HeadsetService.java | 80 +++++++++---------- .../aidl/hfp_client_interface_aidl.cc | 8 ++ system/btif/include/btif_hf.h | 2 + system/btif/src/btif_hf.cc | 27 +++++++ system/test/mock/mock_btif_hf.cc | 12 +++ system/test/mock/mock_btif_hf.h | 14 ++++ 6 files changed, 102 insertions(+), 41 deletions(-) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index a7a6895486b..a6372af61c4 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -80,7 +80,6 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.concurrent.FutureTask; /** * Provides Bluetooth Headset and Handsfree profile, as a service in the Bluetooth application. @@ -1153,31 +1152,40 @@ public class HeadsetService extends ProfileService { } else { stateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_START, device); } - if (Utils.isScoManagedByAudioEnabled()) { - // when isScoManagedByAudio is on, tell AudioManager to connect SCO - AudioManager am = mSystemInterface.getAudioManager(); - BluetoothDevice finalDevice = device; - Optional audioDeviceInfo = - am.getAvailableCommunicationDevices().stream() - .filter( - x -> - x.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO - && x.getAddress() - .equals(finalDevice.getAddress())) - .findFirst(); - if (audioDeviceInfo.isPresent()) { - am.setCommunicationDevice(audioDeviceInfo.get()); - Log.i(TAG, "Audio Manager will initiate the SCO connection"); - return true; - } + if (!Utils.isScoManagedByAudioEnabled()) { + stateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device); + } + } + + if (Utils.isScoManagedByAudioEnabled()) { + BluetoothDevice voiceRecognitionDevice = device; + // when isScoManagedByAudio is on, tell AudioManager to connect SCO + AudioManager am = mSystemInterface.getAudioManager(); + Optional audioDeviceInfo = + am.getAvailableCommunicationDevices().stream() + .filter( + x -> + x.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO + && x.getAddress() + .equals( + voiceRecognitionDevice + .getAddress())) + .findFirst(); + if (audioDeviceInfo.isPresent()) { + mHandler.post( + () -> { + am.setCommunicationDevice(audioDeviceInfo.get()); + Log.i(TAG, "Audio Manager will initiate the SCO for Voice Recognition"); + }); + return true; + } else { Log.w( TAG, "Cannot find audioDeviceInfo that matches device=" - + device + + voiceRecognitionDevice + " to create the SCO"); return false; } - stateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device); } enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, device); return true; @@ -1213,11 +1221,18 @@ public class HeadsetService extends ProfileService { } mVoiceRecognitionStarted = false; stateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_STOP, device); - if (Utils.isScoManagedByAudioEnabled()) { - mSystemInterface.getAudioManager().clearCommunicationDevice(); - return true; + if (!Utils.isScoManagedByAudioEnabled()) { + stateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, device); } - stateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, device); + } + + if (Utils.isScoManagedByAudioEnabled()) { + // do the task outside synchronized to avoid deadlock with Audio Fwk + mHandler.post( + () -> { + mSystemInterface.getAudioManager().clearCommunicationDevice(); + }); + return true; } enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, device); return true; @@ -2015,23 +2030,6 @@ public class HeadsetService extends ProfileService { HeadsetStateMachine.CALL_STATE_CHANGED, new HeadsetCallState( numActive, numHeld, callState, number, type, name))); - if (Utils.isScoManagedByAudioEnabled()) { - if (mActiveDevice == null) { - Log.i(TAG, "HeadsetService's active device is null"); - } else { - // wait until mActiveDevice's state machine processed CALL_STATE_CHANGED message, - // then Audio Framework starts the SCO connection - FutureTask task = new FutureTask(() -> {}, null); - mStateMachines.get(mActiveDevice).getHandler().post(task); - try { - task.get(); - } catch (Exception e) { - Log.e( - TAG, - "Exception when waiting for CALL_STATE_CHANGED message" + e.toString()); - } - } - } mStateMachinesThreadHandler.post( () -> { if (callState == HeadsetHalConstants.CALL_STATE_IDLE diff --git a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc index 67082b85de6..6b8082fedd6 100644 --- a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc @@ -93,6 +93,14 @@ BluetoothAudioCtrlAck HfpTransport::StartRequest() { /* Post start SCO event and wait for sco to open */ hfp_pending_cmd_ = HFP_CTRL_CMD_START; + bool is_call_idle = bluetooth::headset::IsCallIdle(); + bool is_during_vr = bluetooth::headset::IsDuringVoiceRecognition(&(cb->peer_addr)); + if (is_call_idle && !is_during_vr) { + log::warn("Call ongoing={}, voice recognition ongoing={}, wait for retry", !is_call_idle, + is_during_vr); + hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; + return BluetoothAudioCtrlAck::PENDING; + } // as ConnectAudio only queues the command into main thread, keep PENDING // status auto status = bluetooth::headset::GetInterface()->ConnectAudio(&cb->peer_addr, 0); diff --git a/system/btif/include/btif_hf.h b/system/btif/include/btif_hf.h index 4f19ae1e314..67a32ce621d 100644 --- a/system/btif/include/btif_hf.h +++ b/system/btif/include/btif_hf.h @@ -38,6 +38,8 @@ Interface* GetInterface(); */ bool IsCallIdle(); +bool IsDuringVoiceRecognition(RawAddress* bd_addr); + /** * Start up or shutdown the service * diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index 35408361844..422fa976ddb 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -112,6 +112,7 @@ struct btif_hf_cb_t { tBTA_AG_PEER_FEAT peer_feat; int num_active; int num_held; + bool is_during_voice_recognition; bthf_call_state_t call_setup_state; }; @@ -132,6 +133,8 @@ static const char* dump_hf_call_state(bthf_call_state_t call_state) { } } +static int btif_hf_idx_by_bdaddr(RawAddress* bd_addr); + /** * Check if bd_addr is the current active device. * @@ -818,6 +821,28 @@ bool IsCallIdle() { return true; } +bool IsDuringVoiceRecognition(RawAddress* bd_addr) { + if (!bt_hf_callbacks) { + return false; + } + if (bd_addr == nullptr) { + log::error("null address"); + return false; + } + int idx = btif_hf_idx_by_bdaddr(bd_addr); + if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) { + log::error("Invalid index {}", idx); + return false; + } + if (!is_connected(bd_addr)) { + log::error("{} is not connected", *bd_addr); + return false; + } + bool in_vr = btif_hf_cb[idx].is_during_voice_recognition; + log::debug("IsDuringVoiceRecognition={}", in_vr); + return in_vr; +} + class HeadsetInterface : Interface { public: static Interface* GetInstance() { @@ -989,6 +1014,7 @@ bt_status_t HeadsetInterface::StartVoiceRecognition(RawAddress* bd_addr) { log::error("voice recognition not supported, features=0x{:x}", btif_hf_cb[idx].peer_feat); 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); @@ -1011,6 +1037,7 @@ bt_status_t HeadsetInterface::StopVoiceRecognition(RawAddress* bd_addr) { log::error("voice recognition not supported, features=0x{:x}", btif_hf_cb[idx].peer_feat); return BT_STATUS_UNSUPPORTED; } + btif_hf_cb[idx].is_during_voice_recognition = false; tBTA_AG_RES_DATA ag_res = {}; ag_res.state = false; BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, ag_res); diff --git a/system/test/mock/mock_btif_hf.cc b/system/test/mock/mock_btif_hf.cc index e49f8f09fc8..7c1080a8b33 100644 --- a/system/test/mock/mock_btif_hf.cc +++ b/system/test/mock/mock_btif_hf.cc @@ -35,6 +35,8 @@ namespace btif_hf { // Function state capture and return values, if needed struct GetInterface GetInterface; +struct IsCallIdle IsCallIdle; +struct IsDuringVoiceRecognition IsDuringVoiceRecognition; } // namespace btif_hf } // namespace mock } // namespace test @@ -46,6 +48,16 @@ Interface* GetInterface() { inc_func_call_count(__func__); return test::mock::btif_hf::GetInterface(); } + +bool IsCallIdle() { + inc_func_call_count(__func__); + return test::mock::btif_hf::IsCallIdle(); +} + +bool IsDuringVoiceRecognition(RawAddress* bd_addr) { + inc_func_call_count(__func__); + return test::mock::btif_hf::IsDuringVoiceRecognition(bd_addr); +} } // namespace headset } // namespace bluetooth diff --git a/system/test/mock/mock_btif_hf.h b/system/test/mock/mock_btif_hf.h index 8d742b1a49f..864ca85af05 100644 --- a/system/test/mock/mock_btif_hf.h +++ b/system/test/mock/mock_btif_hf.h @@ -25,6 +25,7 @@ #include #include "include/hardware/bluetooth_headset_interface.h" +#include "types/raw_address.h" // Original included files, if any // NOTE: Since this is a mock file with mock definitions some number of @@ -52,6 +53,19 @@ struct GetInterface { }; extern struct GetInterface GetInterface; +struct IsCallIdle { + std::function body{[]() { return false; }}; + bool operator()() { return body(); } +}; +extern struct IsCallIdle IsCallIdle; + +struct IsDuringVoiceRecognition { + std::function body{ + [](RawAddress* bd_addr) { return bd_addr != nullptr; }}; + bool operator()(RawAddress* bd_addr) { return body(bd_addr); } +}; +extern struct IsDuringVoiceRecognition IsDuringVoiceRecognition; + // Shared state between mocked functions and tests } // namespace btif_hf } // namespace mock -- GitLab From 7c5c2fc99d9401f4979199b134cc0d173e8f3517 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Mon, 23 Sep 2024 15:19:58 -0700 Subject: [PATCH 050/875] reset hfp_pending_cmd_ to handle retry logic 1. when a new session start, reset 2. when startStream failed, reset hfp_pending_cmd_ to allow retry 3. after suspendStream, reset hfp_pending_cmd_ to avoid stuck in pending suspend when SCO already disconnected Bug: 367479598 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio and HFP session type only enabled when flag is enabled Test: atest HeadsetStateMachineTest Change-Id: I21f7091cf8965aed19c02da61e6c91bbd9f85172 --- .../aidl/hfp_client_interface_aidl.cc | 41 +++++++++++++++++-- .../hfp_client_interface.cc | 12 ++++-- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc index 6b8082fedd6..45557cc82f0 100644 --- a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc @@ -45,6 +45,31 @@ std::map status_to_ack_map = { {BT_STATUS_UNSUPPORTED, BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED}, }; +std::string command_to_text(tHFP_CTRL_CMD cmd) { + switch (cmd) { + case HFP_CTRL_CMD_NONE: + return "none"; + case HFP_CTRL_CMD_CHECK_READY: + return "check ready"; + case HFP_CTRL_CMD_START: + return "start"; + case HFP_CTRL_CMD_STOP: + return "stop"; + case HFP_CTRL_CMD_SUSPEND: + return "suspend"; + case HFP_CTRL_GET_INPUT_AUDIO_CONFIG: + return "get input audio config"; + case HFP_CTRL_GET_OUTPUT_AUDIO_CONFIG: + return "get output audio config"; + case HFP_CTRL_SET_OUTPUT_AUDIO_CONFIG: + return "set output audio config"; + case HFP_CTRL_GET_PRESENTATION_POSITION: + return "get presentation position"; + default: + return "undefined"; + } +} + tBTA_AG_SCB* get_hfp_active_device_callback() { const RawAddress& addr = bta_ag_get_active_device(); if (addr.IsEmpty()) { @@ -77,7 +102,7 @@ BluetoothAudioCtrlAck HfpTransport::StartRequest() { log::info("HFP_CTRL_CMD_START in progress"); return BluetoothAudioCtrlAck::PENDING; } else if (hfp_pending_cmd_ != HFP_CTRL_CMD_NONE) { - log::warn("busy in pending_cmd={}", hfp_pending_cmd_); + log::warn("busy in pending_cmd={}, {}", hfp_pending_cmd_, command_to_text(hfp_pending_cmd_)); return BluetoothAudioCtrlAck::FAILURE_BUSY; } @@ -108,9 +133,11 @@ BluetoothAudioCtrlAck HfpTransport::StartRequest() { auto ctrl_ack = status_to_ack_map.find(status); if (ctrl_ack == status_to_ack_map.end()) { log::warn("Unmapped status={}", status); + hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; return BluetoothAudioCtrlAck::FAILURE; } if (ctrl_ack->second != BluetoothAudioCtrlAck::SUCCESS_FINISHED) { + hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; return ctrl_ack->second; } return BluetoothAudioCtrlAck::PENDING; @@ -140,7 +167,7 @@ void HfpTransport::LogBytesProcessed(size_t bytes_read) {} BluetoothAudioCtrlAck HfpTransport::SuspendRequest() { log::info("handling"); if (hfp_pending_cmd_ != HFP_CTRL_CMD_NONE) { - log::warn("busy in pending_cmd={}", hfp_pending_cmd_); + log::warn("busy in pending_cmd={}, {}", hfp_pending_cmd_, command_to_text(hfp_pending_cmd_)); return BluetoothAudioCtrlAck::FAILURE_BUSY; } @@ -158,8 +185,14 @@ BluetoothAudioCtrlAck HfpTransport::SuspendRequest() { } auto status = instance->DisconnectAudio(&addr); log::info("DisconnectAudio status = {} - {}", status, bt_status_text(status)); - return status == BT_STATUS_SUCCESS ? BluetoothAudioCtrlAck::SUCCESS_FINISHED - : BluetoothAudioCtrlAck::FAILURE; + // once disconnect audio is queued, not waiting on that + // because disconnect audio request can come when audio is disconnected + hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; + if (status == BT_STATUS_SUCCESS) { + return BluetoothAudioCtrlAck::SUCCESS_FINISHED; + } else { + return BluetoothAudioCtrlAck::FAILURE; + } } void HfpTransport::SetLatencyMode(LatencyMode latency_mode) {} diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index 35aeea0728f..2df82b342e3 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -139,6 +139,8 @@ void HfpClientInterface::Decode::StartSession() { log::error("cannot update audio config to HAL"); return; } + auto instance = aidl::hfp::HfpEncodingTransport::instance_; + instance->ResetPendingCmd(); get_decode_client_interface()->StartSession(); } @@ -441,7 +443,11 @@ void HfpClientInterface::Offload::StartSession() { log::error("cannot update audio config to HAL"); return; } - get_encode_client_interface()->StartSession(); + if (get_encode_client_interface()->StartSession() == 0) { + log::info("session started"); + } else { + log::warn("session not started"); + } } void HfpClientInterface::Offload::StopSession() { @@ -496,8 +502,8 @@ void HfpClientInterface::Offload::CancelStreamingRequest() { instance->ResetPendingCmd(); return; case aidl::hfp::HFP_CTRL_CMD_NONE: - log::warn("no pending start stream request"); - return; + log::info("no pending start stream request"); + [[fallthrough]]; case aidl::hfp::HFP_CTRL_CMD_SUSPEND: log::info("suspends"); aidl::hfp::HfpEncodingTransport::offloading_hal_interface->StreamSuspended( -- GitLab From 071d0427933aaeffd2459f8cb73d5c65c9204c9e Mon Sep 17 00:00:00 2001 From: Palash Ahuja Date: Tue, 24 Sep 2024 20:02:01 -0700 Subject: [PATCH 051/875] BluetoothMetrics: Logging bytes_field instead of 0 for cross layer metric Test: m statsd_testdrive && statsd_testdrive 916 Bug: 345564021 Flag:EXEMPT, metrics changes Change-Id: I8c1468226918349e77d4b494d03c5f39990412b2 --- system/gd/os/android/metrics.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc index e73ac2f29e9..daea83d0a58 100644 --- a/system/gd/os/android/metrics.cc +++ b/system/gd/os/android/metrics.cc @@ -465,7 +465,12 @@ void LogMetricBluetoothEvent(const Address& address, android::bluetooth::EventTy return; } int metric_id = MetricIdManager::GetInstance().AllocateId(address); - int ret = stats_write(BLUETOOTH_CROSS_LAYER_EVENT_REPORTED, event_type, state, 0, metric_id, 0); + int ret = stats_write(BLUETOOTH_CROSS_LAYER_EVENT_REPORTED, + event_type, + state, + 0, + metric_id, + BytesField(nullptr, 0)); if (ret < 0) { log::warn("Failed BluetoothEvent Upload - Address {}, Event_type {}, State {}", address, event_type, state); -- GitLab From 4a74579e509ae5708c875c7c0254e0420696946b Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Thu, 26 Sep 2024 15:30:27 +0800 Subject: [PATCH 052/875] flag: Add forward_get_set_report_failure_to_uhid Bug: 369748430 Bug: 315241296 Test: m -j Change-Id: I7d8b9d5031fee3115976abe2d3ea9c607c78dcda --- flags/hid.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/hid.aconfig b/flags/hid.aconfig index caf160415eb..7ec7f03f3ce 100644 --- a/flags/hid.aconfig +++ b/flags/hid.aconfig @@ -122,3 +122,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +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 + } +} -- GitLab From b52e6b6f7f9788b79470c1783c7386113acc55a6 Mon Sep 17 00:00:00 2001 From: Ying Hsu Date: Thu, 26 Sep 2024 08:07:36 +0000 Subject: [PATCH 053/875] Introduce a soong config for HFP HAL selection For most Bluetooth transports (except USB), there's no need to query HFP codec capabilities or configure SCO parameters. This patch introduces a soong config that allows product to select appropriate HFP HAL when necessary. Note: this is based on ag/27953637. Bug: 349136847 Test: m -j com.google.android.btservices Flag: Exempt, build-only change, no change to default behavior Change-Id: If3c465d66d8a69dfae360678cce50793a7a39fa1 --- system/stack/Android.bp | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 8c98468d972..0e0637bdf0f 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -176,9 +176,45 @@ filegroup { ], } +soong_config_module_type { + name: "hfp_hal_cc_defaults", + module_type: "cc_defaults", + config_namespace: "hfp_hal", + variables: ["vertical"], + properties: ["srcs"], +} + +soong_config_string_variable { + name: "vertical", + values: [ + "android_default", + "android_desktop", + ], +} + +hfp_hal_cc_defaults { + name: "hfp_hal_defaults", + soong_config_variables: { + vertical: { + android_desktop: { + srcs: ["btm/btm_sco_hfp_hal_linux.cc"], + }, + android_default: { + srcs: ["btm/btm_sco_hfp_hal.cc"], + }, + conditions_default: { + srcs: ["btm/btm_sco_hfp_hal.cc"], + }, + }, + }, +} + cc_library_static { name: "libbt-stack-core", - defaults: ["fluoride_defaults"], + defaults: [ + "fluoride_defaults", + "hfp_hal_defaults", + ], local_include_dirs: [ "ais", "avct", @@ -235,7 +271,6 @@ cc_library_static { "btm/btm_main.cc", "btm/btm_sco.cc", "btm/btm_sco_hci.cc", - "btm/btm_sco_hfp_hal.cc", "btm/btm_sec.cc", "btm/btm_sec_cb.cc", "btm/btm_security_client_interface.cc", -- GitLab From 9a25064a88b449af4cd0c3440caf9e05f5c178a3 Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 26 Sep 2024 08:18:13 +0000 Subject: [PATCH 054/875] LeAudio: Fix reconnecting LeAudio when profile is disabled When BT is enabled we should set the BT device autoconnect feature according to the profile connection policy to avoid the unnecessary and endless LE link establishment and disconnection cycle. Bug: 369784445 Test: atest GoogleBluetoothInstrumentationTests Flag: Exempt; Bug fix covered with unit test Change-Id: I069227b70c6d66978a7bb1a32968fd47989ac3a7 --- .../bluetooth/le_audio/LeAudioService.java | 5 +++- .../le_audio/LeAudioServiceTest.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) 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 f9cd05402c9..3dca9d250ad 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -4671,9 +4671,12 @@ public class LeAudioService extends ProfileService { return; } for (BluetoothDevice device : mDeviceDescriptors.keySet()) { - if (getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { + int connection_policy = getConnectionPolicy(device); + if (connection_policy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { setAuthorizationForRelatedProfiles(device, true); } + setEnabledState( + device, connection_policy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); } } finally { mGroupReadLock.unlock(); 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 0a1fe265611..fb1a2bcac80 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 @@ -72,8 +72,10 @@ import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.csip.CsipSetCoordinatorService; import com.android.bluetooth.flags.Flags; +import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.hap.HapClientService; import com.android.bluetooth.hfp.HeadsetService; +import com.android.bluetooth.le_scan.TransitionalScanHelper; import com.android.bluetooth.mcp.McpService; import com.android.bluetooth.tbs.TbsService; import com.android.bluetooth.vc.VolumeControlService; @@ -133,6 +135,8 @@ public class LeAudioServiceTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; + @Mock private GattService mGattService; + @Mock private TransitionalScanHelper mTransitionalScanHelper; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AudioManager mAudioManager; @Mock private DatabaseManager mDatabaseManager; @@ -220,6 +224,8 @@ public class LeAudioServiceTest { doAnswer(invocation -> mBondedDevices.toArray(new BluetoothDevice[] {})) .when(mAdapterService) .getBondedDevices(); + doReturn(mGattService).when(mAdapterService).getBluetoothGattService(); + doReturn(mTransitionalScanHelper).when(mGattService).getTransitionalScanHelper(); LeAudioBroadcasterNativeInterface.setInstance(mLeAudioBroadcasterNativeInterface); LeAudioNativeInterface.setInstance(mNativeInterface); @@ -386,6 +392,26 @@ public class LeAudioServiceTest { assertThat(mService).isEqualTo(LeAudioService.getLeAudioService()); } + /** Test enabling disabling device autoconnections when connection policy is set */ + @Test + public void testEnableDisableProfile() { + // Make sure the device is known to the service and is not forbidden to connect + mService.createDeviceDescriptor(mSingleDevice, true); + when(mDatabaseManager.getProfileConnectionPolicy(mSingleDevice, BluetoothProfile.LE_AUDIO)) + .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); + + // Verify the device is enabled in the service when policy is not FORBIDDEN during BT Enable + mService.handleBluetoothEnabled(); + verify(mNativeInterface).setEnableState(eq(mSingleDevice), eq(true)); + + // Verify the device is disabled in the service when policy is set to FORBIDDEN + when(mDatabaseManager.setProfileConnectionPolicy( + eq(mSingleDevice), eq(BluetoothProfile.LE_AUDIO), anyInt())) + .thenReturn(true); + mService.setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + verify(mNativeInterface).setEnableState(eq(mSingleDevice), eq(false)); + } + /** Test stop LeAudio Service */ @Test public void testStopLeAudioService() { -- GitLab From 68c043342208523e9a22cbc03eb404af47404aa2 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Wed, 4 Sep 2024 15:02:24 +0200 Subject: [PATCH 055/875] Wire Encryption Change event to Java This is preparation to expose it as Broadcast Flag: EXEMPT, just wiring event through the stack. Following API patch will hide it under a flag Test: mma -j32 Bug: 297598060 Bug: 369753860 Change-Id: I02beb43c7dfd09e101122e072c5096385b0ac1da --- ...oid_bluetooth_btservice_AdapterService.cpp | 31 +++++++++++++++++++ .../bluetooth/btservice/JniCallbacks.java | 11 +++++++ .../bluetooth/btservice/RemoteDevices.java | 30 ++++++++++++++++++ system/bta/dm/bta_dm_sec.cc | 8 +++++ system/bta/include/bta_sec_api.h | 3 ++ system/btif/include/btif_common.h | 1 + system/btif/include/core_callbacks.h | 1 + system/btif/include/mock_core_callbacks.h | 1 + system/btif/src/bluetooth.cc | 9 ++++++ system/btif/src/btif_dm.cc | 4 +++ system/gd/rust/topshim/src/btif.rs | 2 ++ system/include/hardware/bluetooth.h | 12 +++++++ system/stack/btm/btm_sec.cc | 9 +++++- system/test/common/core_interface.cc | 3 +- system/test/mock/mock_bluetooth_interface.cc | 1 + system/test/mock/mock_bta_dm_act.cc | 5 +++ system/test/mock/mock_bta_dm_act.h | 10 ++++++ 17 files changed, 139 insertions(+), 2 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index 0d69e449398..3b5d62404ec 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -97,6 +97,7 @@ static jmethodID method_acquireWakeLock; static jmethodID method_releaseWakeLock; static jmethodID method_energyInfo; static jmethodID method_keyMissingCallback; +static jmethodID method_encryptionChangeCallback; static struct { jclass clazz; @@ -773,6 +774,34 @@ static void key_missing_callback(const RawAddress bd_addr) { sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_keyMissingCallback, addr.get()); } +static void encryption_change_callback(const bt_encryption_change_evt encryption_change) { + std::shared_lock lock(jniObjMutex); + if (!sJniCallbacksObj) { + log::error("JNI obj is null. Failed to call JNI callback"); + return; + } + + CallbackEnv sCallbackEnv(__func__); + if (!sCallbackEnv.valid()) { + return; + } + + ScopedLocalRef addr(sCallbackEnv.get(), + sCallbackEnv->NewByteArray(sizeof(RawAddress))); + if (!addr.get()) { + log::error("Address allocation failed"); + return; + } + sCallbackEnv->SetByteArrayRegion( + addr.get(), 0, sizeof(RawAddress), + reinterpret_cast(const_cast(&encryption_change.bd_addr))); + + sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_encryptionChangeCallback, addr.get(), + encryption_change.status, encryption_change.encr_enable, + encryption_change.transport, encryption_change.secure_connections, + encryption_change.key_size); +} + static void callback_thread_event(bt_cb_thread_evt event) { if (event == ASSOCIATE_JVM) { JavaVMAttachArgs args; @@ -861,6 +890,7 @@ static bt_callbacks_t sBluetoothCallbacks = { switch_codec_callback, le_rand_callback, key_missing_callback, + encryption_change_callback, }; class JNIThreadAttacher { @@ -2318,6 +2348,7 @@ int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) { {"releaseWakeLock", "(Ljava/lang/String;)Z", &method_releaseWakeLock}, {"energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V", &method_energyInfo}, {"keyMissingCallback", "([B)V", &method_keyMissingCallback}, + {"encryptionChangeCallback", "([BIZIZI)V", &method_encryptionChangeCallback}, }; GET_JAVA_METHODS(env, "com/android/bluetooth/btservice/JniCallbacks", javaMethods); diff --git a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java index 2822345ed4c..a8e5492a351 100644 --- a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +++ b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java @@ -91,6 +91,17 @@ class JniCallbacks { mRemoteDevices.keyMissingCallback(address); } + void encryptionChangeCallback( + byte[] address, + int status, + boolean encryptionEnable, + int transport, + boolean secureConnection, + int keySize) { + mRemoteDevices.encryptionChangeCallback( + address, status, encryptionEnable, transport, secureConnection, keySize); + } + void stateChangeCallback(int status) { mAdapterService.stateChangeCallback(status); } diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index b0f858139bf..a2693764b89 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -1398,6 +1398,36 @@ public class RemoteDevices { } } + void encryptionChangeCallback( + byte[] address, + int status, + boolean encryptionEnable, + int transport, + boolean secureConnection, + int keySize) { + BluetoothDevice bluetoothDevice = getDevice(address); + if (bluetoothDevice == null) { + errorLog( + "encryptionChangeCallback: device is NULL, address=" + + Utils.getRedactedAddressStringFromByte(address)); + return; + } + Log.d( + TAG, + "encryptionChangeCallback device: " + + bluetoothDevice + + ", status: " + + status + + ", enabled: " + + encryptionEnable + + ", transport: " + + transport + + ", secureConnection: " + + secureConnection + + ", keySize: " + + keySize); + } + void fetchUuids(BluetoothDevice device, int transport) { if (mSdpTracker.contains(device)) { debugLog( diff --git a/system/bta/dm/bta_dm_sec.cc b/system/bta/dm/bta_dm_sec.cc index 0e5eaf97ac1..7592b57c323 100644 --- a/system/bta/dm/bta_dm_sec.cc +++ b/system/bta/dm/bta_dm_sec.cc @@ -107,6 +107,14 @@ void bta_dm_sec_enable(tBTA_DM_SEC_CBACK* p_sec_cback) { } } +void bta_dm_on_encryption_change(bt_encryption_change_evt encryption_change) { + if (bta_dm_sec_cb.p_sec_cback) { + tBTA_DM_SEC sec_event; + sec_event.encryption_change = encryption_change; + bta_dm_sec_cb.p_sec_cback(BTA_DM_ENCRYPTION_CHANGE_EVT, &sec_event); + } +} + void bta_dm_remote_key_missing(const RawAddress bd_addr) { if (bta_dm_sec_cb.p_sec_cback) { tBTA_DM_SEC sec_event; diff --git a/system/bta/include/bta_sec_api.h b/system/bta/include/bta_sec_api.h index f17f251f7ab..7446e729f92 100644 --- a/system/bta/include/bta_sec_api.h +++ b/system/bta/include/bta_sec_api.h @@ -25,6 +25,7 @@ #include #include "bta/include/bta_api_data_types.h" +#include "include/hardware/bluetooth.h" #include "stack/include/bt_device_type.h" #include "stack/include/bt_name.h" #include "stack/include/bt_octets.h" @@ -67,6 +68,7 @@ typedef enum : uint8_t { BTA_DM_LE_ADDR_ASSOC_EVT = 33, /* identity address association event */ BTA_DM_SIRK_VERIFICATION_REQ_EVT = 35, BTA_DM_KEY_MISSING_EVT = 36, + BTA_DM_ENCRYPTION_CHANGE_EVT = 37, } tBTA_DM_SEC_EVT; /* Structure associated with BTA_DM_PIN_REQ_EVT */ @@ -236,6 +238,7 @@ typedef union { tBTA_DM_RC_UNPAIR delete_key_RC_to_unpair; tBTA_DM_PROC_ID_ADDR proc_id_addr; /* Identity address event */ tBTA_DM_KEY_MISSING key_missing; + bt_encryption_change_evt encryption_change; } tBTA_DM_SEC; /* Security callback */ diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h index 616da3a8d8a..64433579f0f 100644 --- a/system/btif/include/btif_common.h +++ b/system/btif/include/btif_common.h @@ -163,4 +163,5 @@ void invoke_link_quality_report_cb(uint64_t timestamp, int report_id, int rssi, void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size); void invoke_switch_codec_cb(bool is_low_latency_buffer_size); void invoke_key_missing_cb(RawAddress bd_addr); +void invoke_encryption_change_cb(bt_encryption_change_evt encryption_change); #endif /* BTIF_COMMON_H */ diff --git a/system/btif/include/core_callbacks.h b/system/btif/include/core_callbacks.h index 59a7f790518..43a07d00b45 100644 --- a/system/btif/include/core_callbacks.h +++ b/system/btif/include/core_callbacks.h @@ -55,6 +55,7 @@ struct EventCallbacks { int retransmission_count, int packets_not_receive_count, int negative_acknowledgement_count); void (*invoke_key_missing_cb)(RawAddress bd_addr); + void (*invoke_encryption_change_cb)(bt_encryption_change_evt encryption_change); EventCallbacks& operator=(const EventCallbacks&) = delete; }; diff --git a/system/btif/include/mock_core_callbacks.h b/system/btif/include/mock_core_callbacks.h index 7bbe1612a22..79bd5018b9d 100644 --- a/system/btif/include/mock_core_callbacks.h +++ b/system/btif/include/mock_core_callbacks.h @@ -64,6 +64,7 @@ EventCallbacks mock_event_callbacks = { int /* retransmission_count */, int /* packets_not_receive_count */, int /* negative_acknowledgement_count */) {}, .invoke_key_missing_cb = [](RawAddress /* bd_addr */) {}, + .invoke_encryption_change_cb = [](bt_encryption_change_evt /* encryption_change */) {}, }; // This interface lets us query for configuration properties of the stack that diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index ba8f77acfea..1575924289f 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -376,6 +376,7 @@ static bluetooth::core::CoreInterface* CreateInterfaceToProfiles() { .invoke_energy_info_cb = invoke_energy_info_cb, .invoke_link_quality_report_cb = invoke_link_quality_report_cb, .invoke_key_missing_cb = invoke_key_missing_cb, + .invoke_encryption_change_cb = invoke_encryption_change_cb, }; static bluetooth::core::HACK_ProfileInterface profileInterface{ // HID @@ -1549,6 +1550,14 @@ void invoke_key_missing_cb(RawAddress bd_addr) { [](RawAddress bd_addr) { HAL_CBACK(bt_hal_cbacks, key_missing_cb, bd_addr); }, bd_addr)); } +void invoke_encryption_change_cb(bt_encryption_change_evt encryption_change) { + do_in_jni_thread(base::BindOnce( + [](bt_encryption_change_evt encryption_change) { + HAL_CBACK(bt_hal_cbacks, encryption_change_cb, encryption_change); + }, + encryption_change)); +} + namespace bluetooth::testing { void set_hal_cbacks(bt_callbacks_t* callbacks) { ::set_hal_cbacks(callbacks); } diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 97696a1600e..ea2f121ead1 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -2169,6 +2169,10 @@ void btif_dm_sec_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) { GetInterfaceToProfiles()->events->invoke_key_missing_cb(p_data->key_missing.bd_addr); break; + case BTA_DM_ENCRYPTION_CHANGE_EVT: + GetInterfaceToProfiles()->events->invoke_encryption_change_cb(p_data->encryption_change); + break; + default: log::warn("unhandled event({})", event); break; diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index b557f8db08d..0837f5fcfb4 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -1077,6 +1077,7 @@ pub enum BaseCallbacks { GenerateLocalOobData(u8, Box), // Box OobData as its size is much bigger than others LeRandCallback(u64), // key_missing_cb + // encryption_change_cb } pub struct BaseCallbacksDispatcher { @@ -1269,6 +1270,7 @@ impl BluetoothInterface { switch_codec_cb: None, le_rand_cb: Some(le_rand_cb), key_missing_cb: None, + encryption_change_cb: None, }); let cb_ptr = LTCheckedPtrMut::from(&mut callbacks); diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index 903bc917801..bf53607a8da 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -477,6 +477,15 @@ typedef enum { BT_SSP_VARIANT_PASSKEY_NOTIFICATION } bt_ssp_variant_t; +typedef struct { + RawAddress bd_addr; + uint8_t status; /* bt_hci_error_code_t */ + bool encr_enable; + uint8_t key_size; + tBT_TRANSPORT transport; + bool secure_connections; +} bt_encryption_change_evt; + #define BT_MAX_NUM_UUIDS 32 /** Bluetooth Interface callbacks */ @@ -594,6 +603,8 @@ typedef void (*generate_local_oob_data_callback)(tBT_TRANSPORT transport, bt_oob typedef void (*key_missing_callback)(const RawAddress bd_addr); +typedef void (*encryption_change_callback)(const bt_encryption_change_evt encryption_change); + /** TODO: Add callbacks for Link Up/Down and other generic * notifications/callbacks */ @@ -622,6 +633,7 @@ typedef struct { switch_codec_callback switch_codec_cb; le_rand_callback le_rand_cb; key_missing_callback key_missing_cb; + encryption_change_callback encryption_change_cb; } bt_callbacks_t; typedef int (*acquire_wake_lock_callout)(const char* lock_name); diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index f310bde7bd6..12ee97b9d2a 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -100,6 +100,7 @@ extern tBTM_CB btm_cb; bool btm_ble_init_pseudo_addr(tBTM_SEC_DEV_REC* p_dev_rec, const RawAddress& new_pseudo_addr); void bta_dm_remove_device(const RawAddress& bd_addr); +void bta_dm_on_encryption_change(bt_encryption_change_evt encryption_change); void bta_dm_remote_key_missing(const RawAddress bd_addr); void bta_dm_process_remove_device(const RawAddress& bd_addr); @@ -3175,7 +3176,7 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) { * ******************************************************************************/ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, - uint8_t key_size, bool = false) { + uint8_t key_size, bool from_key_refresh = false) { /* For transaction collision we need to wait and repeat. There is no need */ /* for random timeout because only peripheral should receive the result */ if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) || @@ -3262,6 +3263,12 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_en btm_sec_check_pending_enc_req(p_dev_rec, transport, encr_enable); + if (!from_key_refresh) { + bta_dm_on_encryption_change(bt_encryption_change_evt{p_dev_rec->ble.pseudo_addr, status, + (bool)encr_enable, key_size, transport, + p_dev_rec->SupportsSecureConnections()}); + } + if (transport == BT_TRANSPORT_LE) { if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE || status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) { diff --git a/system/test/common/core_interface.cc b/system/test/common/core_interface.cc index 978858bec7f..9d434ae576d 100644 --- a/system/test/common/core_interface.cc +++ b/system/test/common/core_interface.cc @@ -39,7 +39,8 @@ static bluetooth::core::EventCallbacks eventCallbacks = { .invoke_le_test_mode_cb = invoke_le_test_mode_cb, .invoke_energy_info_cb = invoke_energy_info_cb, .invoke_link_quality_report_cb = invoke_link_quality_report_cb, - .invoke_key_missing_cb = invoke_key_missing_cb}; + .invoke_key_missing_cb = invoke_key_missing_cb, + .invoke_encryption_change_cb = invoke_encryption_change_cb}; // This interface lets us query for configuration properties of the stack that // could change at runtime diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc index 44dfcf279af..7404c099cbf 100644 --- a/system/test/mock/mock_bluetooth_interface.cc +++ b/system/test/mock/mock_bluetooth_interface.cc @@ -57,6 +57,7 @@ void invoke_link_quality_report_cb(uint64_t /* timestamp */, int /* report_id */ int /* packets_not_receive_count */, int /* negative_acknowledgement_count */) {} void invoke_key_missing_cb(const RawAddress /* bd_addr */) {} +void invoke_encryption_change_cb(bt_encryption_change_evt /* bd_addr */) {} static void init_stack(bluetooth::core::CoreInterface* /* interface */) {} diff --git a/system/test/mock/mock_bta_dm_act.cc b/system/test/mock/mock_bta_dm_act.cc index 601b70cacc1..9f7416e84ba 100644 --- a/system/test/mock/mock_bta_dm_act.cc +++ b/system/test/mock/mock_bta_dm_act.cc @@ -70,6 +70,7 @@ struct bta_dm_pin_reply bta_dm_pin_reply; struct bta_dm_process_remove_device bta_dm_process_remove_device; struct bta_dm_remove_device bta_dm_remove_device; struct bta_dm_remote_key_missing bta_dm_remote_key_missing; +struct bta_dm_on_encryption_change bta_dm_on_encryption_change; struct bta_dm_rm_cback bta_dm_rm_cback; struct bta_dm_set_dev_name bta_dm_set_dev_name; struct bta_dm_set_encryption bta_dm_set_encryption; @@ -228,6 +229,10 @@ void bta_dm_remote_key_missing(const RawAddress bd_addr) { inc_func_call_count(__func__); test::mock::bta_dm_act::bta_dm_remote_key_missing(bd_addr); } +void bta_dm_on_encryption_change(bt_encryption_change_evt encryption_change) { + inc_func_call_count(__func__); + test::mock::bta_dm_act::bta_dm_on_encryption_change(encryption_change); +} void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id, uint8_t app_id, const RawAddress& peer_addr) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_bta_dm_act.h b/system/test/mock/mock_bta_dm_act.h index 69d6daa9c3a..09fd1bbbc1f 100644 --- a/system/test/mock/mock_bta_dm_act.h +++ b/system/test/mock/mock_bta_dm_act.h @@ -430,6 +430,16 @@ struct bta_dm_remote_key_missing { }; extern struct bta_dm_remote_key_missing bta_dm_remote_key_missing; +// Name: bta_dm_on_encryption_change +// Params: bt_encryption_change_evt encryption_change +// Return: void +struct bta_dm_on_encryption_change { + std::function body{ + [](bt_encryption_change_evt /* encryption_change */) {}}; + void operator()(bt_encryption_change_evt encryption_change) { body(encryption_change); } +}; +extern struct bta_dm_on_encryption_change bta_dm_on_encryption_change; + // Name: bta_dm_rm_cback // Params: tBTA_SYS_CONN_STATUS status, uint8_t id, uint8_t app_id, const // RawAddress& peer_addr Return: void -- GitLab From 86689dba8566ee2af25f14f55453336d0aaaca1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 25 Sep 2024 16:37:05 +0000 Subject: [PATCH 056/875] leaudio: Minor cleanup Extend logs with group id when setting state and target state Bug: 331775328 Flag: Exempt, log only Test: mmm packages/modules/Bluetooth Change-Id: If3001b716d5a54de76f05244cdf5b94a8bc605fe --- system/bta/le_audio/device_groups.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/bta/le_audio/device_groups.h b/system/bta/le_audio/device_groups.h index b1b41901da1..74deb176945 100644 --- a/system/bta/le_audio/device_groups.h +++ b/system/bta/le_audio/device_groups.h @@ -249,7 +249,7 @@ public: inline types::AseState GetState(void) const { return current_state_; } void SetState(types::AseState state) { - log::info("current state: {}, new state {}, in_transition_ {}", + log::info("group_id: {} current state: {}, new state {}, in_transition_ {}", group_id_, bluetooth::common::ToString(current_state_), bluetooth::common::ToString(state), in_transition_); LeAudioLogHistory::Get()->AddLogHistory(kLogStateMachineTag, group_id_, RawAddress::kEmpty, @@ -272,7 +272,7 @@ public: return notify_streaming_when_cises_are_ready_; } void SetTargetState(types::AseState state) { - log::info("target state: {}, new target state: {}, in_transition_ {}", + log::info("group_id: {} target state: {}, new target state: {}, in_transition_ {}", group_id_, bluetooth::common::ToString(target_state_), bluetooth::common::ToString(state), in_transition_); LeAudioLogHistory::Get()->AddLogHistory( -- GitLab From dd2779efc3208965e0f6bf41ba7a8555e1375949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 25 Sep 2024 16:31:11 +0000 Subject: [PATCH 057/875] leaudio: Move QoS Configured state to right place Make sure QOS_CONFIGURED state is set after remote device has all active ASEs in the QOS_CONFIGURED state Bug: 331775328 Flag: Exempt, regression tested with unit tests Test: atest bluetooth_le_audio_test Change-Id: I5c7bae06fc197e44f41c7fc156c2c8f0e40bfbad --- system/bta/le_audio/state_machine.cc | 5 ++--- system/bta/le_audio/state_machine_test.cc | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 62eae8dc3d7..7c9de8095aa 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -505,9 +505,6 @@ public: /* Assign all connection handles to multiple device ASEs */ group->AssignCisConnHandlesToAses(); - /* Last node configured, process group to codec configured state */ - group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); - PrepareAndSendQoSToTheGroup(group); } @@ -2230,6 +2227,8 @@ private: return; } + group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); + PrepareAndSendEnableToTheGroup(group); break; diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index bfa0aa507ac..02fd745aa34 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -1806,13 +1806,14 @@ TEST_F(StateMachineTest, testConfigureCodecSingleFb2) { */ auto* leAudioDevice = group->GetFirstDevice(); PrepareConfigureCodecHandler(group, 1); + PrepareConfigureQosHandler(group, 1); /* Start the configuration and stream Media content. - * Expect 2 times: for Codec Configure & QoS Configure */ + * Expect 3 times: for Codec Configure & QoS Configure & Enable */ EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, GATT_WRITE_NO_RSP, _, _)) - .Times(2); + .Times(3); InjectInitialIdleNotification(group); -- GitLab From 7e76a98a886bcd5d8457e558e1165d5c745823c4 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Thu, 26 Sep 2024 10:18:33 -0700 Subject: [PATCH 058/875] remove early return to make aptx SWB consistent with and without isScoManagedByAudioEnabled Bug: 367479598 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio Test: atest HeadsetStateMachineTest Change-Id: I09708a66c41444fd3a89969e3220c205ed11c877 --- android/app/src/com/android/bluetooth/hfp/HeadsetService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index 55be6eafc70..9cba675ff6e 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -1177,7 +1177,6 @@ public class HeadsetService extends ProfileService { am.setCommunicationDevice(audioDeviceInfo.get()); Log.i(TAG, "Audio Manager will initiate the SCO for Voice Recognition"); }); - return true; } else { Log.w( TAG, @@ -1232,7 +1231,6 @@ public class HeadsetService extends ProfileService { () -> { mSystemInterface.getAudioManager().clearCommunicationDevice(); }); - return true; } enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, device); return true; -- GitLab From 3720e100c7188a0d1563cec4174b6f5145417db1 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 26 Sep 2024 19:01:10 +0000 Subject: [PATCH 059/875] gd/shim: Cleanup dead code in dumpsys implementation Bug: 331817295 Flag: EXEMPT, dead code removal Test: m com.android.btservices Change-Id: Id2c4e533edf2dc0f80ea6a72a957fae1badb2437 --- system/gd/Android.bp | 4 -- system/gd/BUILD.gn | 2 - system/gd/common/init_flags.fbs | 15 ------- system/gd/dumpsys_data.fbs | 2 - system/gd/shim/Android.bp | 2 - system/gd/shim/BUILD.gn | 1 - system/gd/shim/dumpsys.cc | 6 +-- system/gd/shim/dumpsys.h | 5 --- system/gd/shim/dumpsys_args.cc | 44 ------------------- system/gd/shim/dumpsys_args.h | 33 --------------- system/gd/shim/dumpsys_args_test.cc | 49 ---------------------- system/gd/shim/dumpsys_test.cc | 3 -- system/test/mock/mock_main_shim_dumpsys.cc | 2 - 13 files changed, 1 insertion(+), 167 deletions(-) delete mode 100644 system/gd/common/init_flags.fbs delete mode 100644 system/gd/shim/dumpsys_args.cc delete mode 100644 system/gd/shim/dumpsys_args.h delete mode 100644 system/gd/shim/dumpsys_args_test.cc diff --git a/system/gd/Android.bp b/system/gd/Android.bp index c5dc79e6c04..454cba8c046 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -757,7 +757,6 @@ genrule { ], cmd: "$(location flatc) -I packages/modules/Bluetooth/system/gd -b --schema -o $(genDir) $(in) ", srcs: [ - "common/init_flags.fbs", "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", @@ -770,7 +769,6 @@ genrule { "dumpsys_data.bfbs", "hci_acl_manager.bfbs", "hci_controller.bfbs", - "init_flags.bfbs", "wakelock_manager.bfbs", ], } @@ -782,7 +780,6 @@ genrule { ], cmd: "$(location flatc) -I packages/modules/Bluetooth/system/gd -o $(genDir) --cpp $(in) ", srcs: [ - "common/init_flags.fbs", "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", @@ -795,7 +792,6 @@ genrule { "dumpsys_generated.h", "hci_acl_manager_generated.h", "hci_controller_generated.h", - "init_flags_generated.h", "wakelock_manager_generated.h", ], } diff --git a/system/gd/BUILD.gn b/system/gd/BUILD.gn index 23efaf26547..914ec302579 100644 --- a/system/gd/BUILD.gn +++ b/system/gd/BUILD.gn @@ -94,7 +94,6 @@ static_library("libbluetooth_gd") { flatbuffer("BluetoothGeneratedDumpsysDataSchema_h") { sources = [ - "common/init_flags.fbs", "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", @@ -105,7 +104,6 @@ flatbuffer("BluetoothGeneratedDumpsysDataSchema_h") { bt_flatc_binary_schema("BluetoothGeneratedDumpsysBinarySchema_bfbs") { sources = [ - "common/init_flags.fbs", "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", diff --git a/system/gd/common/init_flags.fbs b/system/gd/common/init_flags.fbs deleted file mode 100644 index 984ebc365e5..00000000000 --- a/system/gd/common/init_flags.fbs +++ /dev/null @@ -1,15 +0,0 @@ -namespace bluetooth.common; - -attribute "privacy"; - -table InitFlagsData { - title:string (privacy:"Any"); - values:[InitFlagValue] (privacy:"Any"); -} - -table InitFlagValue { - flag:string (privacy:"Any"); - value:string (privacy:"Any"); -} - -root_type InitFlagsData; diff --git a/system/gd/dumpsys_data.fbs b/system/gd/dumpsys_data.fbs index f19b53593c8..a3837d59f07 100644 --- a/system/gd/dumpsys_data.fbs +++ b/system/gd/dumpsys_data.fbs @@ -9,7 +9,6 @@ // privacy:"Any" -include "common/init_flags.fbs"; include "hci/hci_acl_manager.fbs"; include "hci/hci_controller.fbs"; include "module_unittest.fbs"; @@ -22,7 +21,6 @@ attribute "privacy"; table DumpsysData { title:string (privacy:"Any"); - init_flags:common.InitFlagsData (privacy:"Any"); wakelock_manager_data:bluetooth.os.WakelockManagerData (privacy:"Any"); shim_dumpsys_data:bluetooth.shim.DumpsysModuleData (privacy:"Any"); hci_acl_manager_dumpsys_data:bluetooth.hci.AclManagerData (privacy:"Any"); diff --git a/system/gd/shim/Android.bp b/system/gd/shim/Android.bp index 9d638586830..c2b1d8b68e4 100644 --- a/system/gd/shim/Android.bp +++ b/system/gd/shim/Android.bp @@ -11,14 +11,12 @@ filegroup { name: "BluetoothShimSources", srcs: [ "dumpsys.cc", - "dumpsys_args.cc", ], } filegroup { name: "BluetoothShimTestSources", srcs: [ - "dumpsys_args_test.cc", "dumpsys_test.cc", ], } diff --git a/system/gd/shim/BUILD.gn b/system/gd/shim/BUILD.gn index 317cdf4234e..addc7527150 100644 --- a/system/gd/shim/BUILD.gn +++ b/system/gd/shim/BUILD.gn @@ -16,7 +16,6 @@ source_set("BluetoothShimSources") { sources = [ "dumpsys.cc", - "dumpsys_args.cc", ] deps = [ diff --git a/system/gd/shim/dumpsys.cc b/system/gd/shim/dumpsys.cc index 88e4ee5daec..24a0083175f 100644 --- a/system/gd/shim/dumpsys.cc +++ b/system/gd/shim/dumpsys.cc @@ -33,7 +33,6 @@ #include "os/log.h" #include "os/system_properties.h" #include "shim/dumpsys.h" -#include "shim/dumpsys_args.h" namespace bluetooth { namespace shim { @@ -133,8 +132,7 @@ std::string Dumpsys::impl::PrintAsJson(std::string* dumpsys_data) const { return jsongen; } -void Dumpsys::impl::DumpWithArgsAsync(int fd, const char** args) const { - ParsedDumpsysArgs parsed_dumpsys_args(args); +void Dumpsys::impl::DumpWithArgsAsync(int fd, const char** /*args*/) const { const auto registry = dumpsys_module_.GetModuleRegistry(); ModuleDumper dumper(fd, *registry, kDumpsysTitle); @@ -171,8 +169,6 @@ void Dumpsys::Dump(int fd, const char** args, std::promise promise) { CallOn(pimpl_.get(), &Dumpsys::impl::DumpWithArgsSync, fd, args, std::move(promise)); } -os::Handler* Dumpsys::GetGdShimHandler() { return GetHandler(); } - /** * Module methods */ diff --git a/system/gd/shim/dumpsys.h b/system/gd/shim/dumpsys.h index 5b463fd193a..129baa94889 100644 --- a/system/gd/shim/dumpsys.h +++ b/system/gd/shim/dumpsys.h @@ -29,14 +29,9 @@ constexpr char kArgumentDeveloper[] = "--dev"; class Dumpsys : public bluetooth::Module { public: - void Dump(int fd, const char** args); void Dump(int fd, const char** args, std::promise promise); - // Convenience thread used by shim layer for task execution - os::Handler* GetGdShimHandler(); - Dumpsys(const std::string& pre_bundled_schema); - Dumpsys(const Dumpsys&) = delete; Dumpsys& operator=(const Dumpsys&) = delete; diff --git a/system/gd/shim/dumpsys_args.cc b/system/gd/shim/dumpsys_args.cc deleted file mode 100644 index 3813a53c13e..00000000000 --- a/system/gd/shim/dumpsys_args.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2020 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 "shim/dumpsys_args.h" - -#include - -#include "shim/dumpsys.h" - -using namespace bluetooth; - -shim::ParsedDumpsysArgs::ParsedDumpsysArgs(const char** args) { - if (args == nullptr) { - return; - } - const char* p = *args; - while (p != nullptr) { - num_args_++; - if (!std::strcmp(p, kArgumentDeveloper)) { - dev_arg_ = true; - } else { - // silently ignore unexpected option - } - if (++args == nullptr) { - break; - } - p = *args; - } -} - -bool shim::ParsedDumpsysArgs::IsDeveloper() const { return dev_arg_; } diff --git a/system/gd/shim/dumpsys_args.h b/system/gd/shim/dumpsys_args.h deleted file mode 100644 index 38e8bc58551..00000000000 --- a/system/gd/shim/dumpsys_args.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2020 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 - -namespace bluetooth { -namespace shim { - -class ParsedDumpsysArgs { -public: - ParsedDumpsysArgs(const char** args); - bool IsDeveloper() const; - -private: - unsigned num_args_{0}; - bool dev_arg_{false}; -}; - -} // namespace shim -} // namespace bluetooth diff --git a/system/gd/shim/dumpsys_args_test.cc b/system/gd/shim/dumpsys_args_test.cc deleted file mode 100644 index 68af56846ee..00000000000 --- a/system/gd/shim/dumpsys_args_test.cc +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020 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 "shim/dumpsys_args.h" - -#include - -#include "shim/dumpsys.h" - -using namespace bluetooth; - -namespace testing { - -TEST(DumpsysArgsTest, no_args) { - shim::ParsedDumpsysArgs parsed_dumpsys_args(nullptr); - ASSERT_FALSE(parsed_dumpsys_args.IsDeveloper()); -} - -TEST(DumpsysArgsTest, parsed_args_without_dev) { - const char* args[]{ - nullptr, - }; - shim::ParsedDumpsysArgs parsed_dumpsys_args(args); - ASSERT_FALSE(parsed_dumpsys_args.IsDeveloper()); -} - -TEST(DumpsysArgsTest, parsed_args_with_dev) { - const char* args[]{ - bluetooth::shim::kArgumentDeveloper, - nullptr, - }; - shim::ParsedDumpsysArgs parsed_dumpsys_args(args); - ASSERT_TRUE(parsed_dumpsys_args.IsDeveloper()); -} - -} // namespace testing diff --git a/system/gd/shim/dumpsys_test.cc b/system/gd/shim/dumpsys_test.cc index bc368f7b77c..8107f20a6c9 100644 --- a/system/gd/shim/dumpsys_test.cc +++ b/system/gd/shim/dumpsys_test.cc @@ -24,7 +24,6 @@ #include "module.h" #include "os/thread.h" -#include "shim/dumpsys_args.h" #include "test_data/dumpsys_test_data_bin.h" namespace testing { @@ -77,8 +76,6 @@ protected: void TearDown() override { fake_registry_.StopAll(); } - void Print() { dumpsys_module_->Dump(0, nullptr); } - int GetSocketBufferSize(int sockfd) { int socket_buffer_size; socklen_t optlen = sizeof(socket_buffer_size); diff --git a/system/test/mock/mock_main_shim_dumpsys.cc b/system/test/mock/mock_main_shim_dumpsys.cc index b3f4fe15187..77b3bfc06a4 100644 --- a/system/test/mock/mock_main_shim_dumpsys.cc +++ b/system/test/mock/mock_main_shim_dumpsys.cc @@ -30,5 +30,3 @@ void bluetooth::shim::Dump(int /* fd */, const char** /* args */) { inc_func_cal void bluetooth::shim::UnregisterDumpsysFunction(const void* /* token */) { inc_func_call_count(__func__); } - -void bluetooth::shim::Dumpsys::Dump(int /* fd */, const char** /* args */) {} -- GitLab From 83707a2119e6f2ff112d3b062dcb109a52cba7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Y=C4=B1lmaz?= Date: Tue, 24 Sep 2024 22:28:34 +0000 Subject: [PATCH 060/875] Add new BleOnStateTest for Scan Manager Refactor changes Tests for 3 scenarios in the BLE_ON state. 1) To be able to scan regardless of the changes 2) You should be able to advertise in the old format but can't advertise with the new scanManager changes 3) You should be able to connect in the old format but can't connect with the new scanManager changes. Bug: 313335632 Bug: 267361243 Bug: 327503826 Test: atest BleOnStateTest Change-Id: I235192c0cc879fde8191e706d4321c072fd23734 --- .../src/android/bluetooth/BleOnStateTest.java | 317 ++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 framework/tests/bumble/src/android/bluetooth/BleOnStateTest.java diff --git a/framework/tests/bumble/src/android/bluetooth/BleOnStateTest.java b/framework/tests/bumble/src/android/bluetooth/BleOnStateTest.java new file mode 100644 index 00000000000..9efda89fcaf --- /dev/null +++ b/framework/tests/bumble/src/android/bluetooth/BleOnStateTest.java @@ -0,0 +1,317 @@ +/* + * Copyright (C) 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. + */ + +package android.bluetooth; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assume.assumeTrue; +import static org.mockito.Mockito.mock; + +import android.bluetooth.le.AdvertiseCallback; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.BluetoothLeAdvertiser; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; +import android.bluetooth.test_utils.BlockingBluetoothAdapter; +import android.bluetooth.test_utils.TestUtils; +import android.content.Context; +import android.os.ParcelUuid; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.util.Log; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.bluetooth.flags.Flags; +import com.android.compatibility.common.util.AdoptShellPermissionsRule; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import pandora.HostProto; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +public class BleOnStateTest { + private static final String TAG = "BleOnTest"; + private static final int TIMEOUT_ADVERTISING_MS = 1000; + private static final int TIMEOUT_SCANNING_MS = 2000; + private static final String TEST_UUID_STRING = "00001805-0000-1000-8000-00805f9b34fb"; + + @Rule(order = 0) + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @Rule(order = 1) + public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule(); + + @Rule(order = 2) + public final PandoraDevice mBumble = new PandoraDevice(); + + private final Context mContext = ApplicationProvider.getApplicationContext(); + private final BluetoothManager mManager = mContext.getSystemService(BluetoothManager.class); + private final BluetoothAdapter mAdapter = mManager.getAdapter(); + private final BluetoothLeScanner mLeScanner = mAdapter.getBluetoothLeScanner(); + + private boolean mWasBluetoothAdapterEnabled = true; + + @Before + public void setUp() { + assumeTrue(TestUtils.hasBluetooth()); + mWasBluetoothAdapterEnabled = mAdapter.isEnabled(); + if (mWasBluetoothAdapterEnabled) { + assertThat(BlockingBluetoothAdapter.disable(true)).isTrue(); + } + assertThat(BlockingBluetoothAdapter.enableBLE(true)).isTrue(); + } + + @After + public void tearDown() { + assumeTrue(TestUtils.hasBluetooth()); + assertThat(BlockingBluetoothAdapter.disableBLE()).isTrue(); + if (mWasBluetoothAdapterEnabled) { + assertThat(BlockingBluetoothAdapter.enable()).isTrue(); + } + } + + @Test + public void confirm_stateIsBleOn() { + assertThat(mAdapter.isEnabled()).isFalse(); + assertThat(mAdapter.isLeEnabled()).isTrue(); + } + + @Test + public void whenScanManagerRefactorOffOrOn_scanWorks() { + advertiseWithBumble(TEST_UUID_STRING, HostProto.OwnAddressType.PUBLIC); + + ScanFilter scanFilter = + new ScanFilter.Builder() + .setServiceUuid(ParcelUuid.fromString(TEST_UUID_STRING)) + .build(); + + List results = + startScanning( + scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES, /* isLegacy= */ true); + + assertThat(results).isNotNull(); + assertThat(results.get(0).getScanRecord().getServiceUuids().get(0)) + .isEqualTo(ParcelUuid.fromString(TEST_UUID_STRING)); + assertThat(results.get(1).getScanRecord().getServiceUuids().get(0)) + .isEqualTo(ParcelUuid.fromString(TEST_UUID_STRING)); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_SCAN_MANAGER_REFACTOR) + public void whenScanManagerRefactorOff_canAdvertise() throws Exception { + final BluetoothLeAdvertiser bluetoothLeAdvertiser = mAdapter.getBluetoothLeAdvertiser(); + + AdvertiseSettings settings = new AdvertiseSettings.Builder().build(); + AdvertiseData advertiseData = new AdvertiseData.Builder().build(); + + final CompletableFuture future = new CompletableFuture<>(); + + AdvertiseCallback advertiseCallback = + new AdvertiseCallback() { + @Override + public void onStartSuccess(AdvertiseSettings settingsInEffect) { + future.complete(AdvertiseCallback.ADVERTISE_SUCCESS); + } + + @Override + public void onStartFailure(int errorCode) { + future.complete(errorCode); + } + }; + + try { + bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, advertiseCallback); + future.completeOnTimeout(null, TIMEOUT_ADVERTISING_MS, TimeUnit.MILLISECONDS).join(); + + Integer advertisingResult = future.get(); + assertThat(advertisingResult).isNotNull(); + assertThat(advertisingResult).isEqualTo(AdvertiseCallback.ADVERTISE_SUCCESS); + } finally { + bluetoothLeAdvertiser.stopAdvertising(advertiseCallback); + } + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_SCAN_MANAGER_REFACTOR) + public void whenScanManagerRefactorOn_cantAdvertise() throws Exception { + final BluetoothLeAdvertiser bluetoothLeAdvertiser = mAdapter.getBluetoothLeAdvertiser(); + + AdvertiseSettings settings = new AdvertiseSettings.Builder().build(); + AdvertiseData advertiseData = new AdvertiseData.Builder().build(); + + final CompletableFuture future = new CompletableFuture<>(); + + AdvertiseCallback advertiseCallback = + new AdvertiseCallback() { + @Override + public void onStartSuccess(AdvertiseSettings settingsInEffect) { + future.complete(AdvertiseCallback.ADVERTISE_SUCCESS); + } + + @Override + public void onStartFailure(int errorCode) { + future.complete(errorCode); + } + }; + + try { + bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, advertiseCallback); + future.completeOnTimeout(null, TIMEOUT_ADVERTISING_MS, TimeUnit.MILLISECONDS).join(); + + Integer advertisingResult = future.get(); + assertThat(advertisingResult).isNotNull(); + assertThat(advertisingResult) + .isEqualTo(AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + } finally { + bluetoothLeAdvertiser.stopAdvertising(advertiseCallback); + } + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_SCAN_MANAGER_REFACTOR) + public void whenScanManagerRefactorOff_gattCanConnect() { + advertiseWithBumble(); + + BluetoothDevice device = + mAdapter.getRemoteLeDevice( + Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); + + BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); + BluetoothGatt gatt = device.connectGatt(mContext, false, gattCallback); + assertThat(gatt).isNotNull(); + gatt.close(); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_SCAN_MANAGER_REFACTOR) + public void whenScanManagerRefactorOn_gattCantConnect() { + advertiseWithBumble(); + + BluetoothDevice device = + mAdapter.getRemoteLeDevice( + Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); + + BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); + BluetoothGatt gatt = device.connectGatt(mContext, false, gattCallback); + assertThat(gatt).isNull(); + } + + private void advertiseWithBumble() { + HostProto.AdvertiseRequest request = + HostProto.AdvertiseRequest.newBuilder() + .setLegacy(true) + .setConnectable(true) + .setOwnAddressType(HostProto.OwnAddressType.RANDOM) + .build(); + + StreamObserverSpliterator responseObserver = + new StreamObserverSpliterator<>(); + + mBumble.host().advertise(request, responseObserver); + } + + private void advertiseWithBumble(String serviceUuid, HostProto.OwnAddressType addressType) { + HostProto.AdvertiseRequest.Builder requestBuilder = + HostProto.AdvertiseRequest.newBuilder().setOwnAddressType(addressType); + + if (serviceUuid != null) { + HostProto.DataTypes.Builder dataTypeBuilder = HostProto.DataTypes.newBuilder(); + dataTypeBuilder.addCompleteServiceClassUuids128(serviceUuid); + requestBuilder.setData(dataTypeBuilder.build()); + } + + advertiseWithBumble(requestBuilder, true); + } + + private void advertiseWithBumble( + HostProto.AdvertiseRequest.Builder requestBuilder, boolean isLegacy) { + requestBuilder.setLegacy(isLegacy); + // Collect and ignore responses. + StreamObserverSpliterator responseObserver = + new StreamObserverSpliterator<>(); + mBumble.host().advertise(requestBuilder.build(), responseObserver); + } + + private List startScanning( + ScanFilter scanFilter, int callbackType, boolean isLegacy) { + CompletableFuture> future = new CompletableFuture<>(); + List scanResults = new ArrayList<>(); + + ScanSettings scanSettings = + new ScanSettings.Builder() + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) + .setCallbackType(callbackType) + .setLegacy(isLegacy) + .build(); + + ScanCallback scanCallback = + new ScanCallback() { + @Override + public void onScanResult(int callbackType, ScanResult result) { + Log.i( + TAG, + "onScanResult " + + "address: " + + result.getDevice().getAddress() + + ", connectable: " + + result.isConnectable() + + ", callbackType: " + + callbackType + + ", service uuids: " + + result.getScanRecord().getServiceUuids()); + + scanResults.add(result); + if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES + || scanResults.size() > 1) { + future.complete(scanResults); + } + } + + @Override + public void onScanFailed(int errorCode) { + Log.i(TAG, "onScanFailed " + "errorCode: " + errorCode); + future.complete(null); + } + }; + + mLeScanner.startScan(List.of(scanFilter), scanSettings, scanCallback); + + List result = + future.completeOnTimeout(null, TIMEOUT_SCANNING_MS, TimeUnit.MILLISECONDS).join(); + + mLeScanner.stopScan(scanCallback); + + return result; + } +} -- GitLab From a57ec5d8176af61e5d2c6e0ae327374a628102cc Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Wed, 4 Sep 2024 16:37:23 +0000 Subject: [PATCH 061/875] Limit gatt clients per app This change limits the number of GATT clients per app to 32. This prevents a badly implemented app from exhausting the global GATT client limit. The commit also includes a fix for a case where tBTA_GATTC_CLCB could be accessed after it was deallocated. This issue was discovered while updating a test in GattClientTest. Bug: 348559823 Bug: 366473955 Test: atest GattServiceTest GattClientTest Change-Id: I9c600a867d0c2aee4f92d31fdbf3f8a0775a83c1 --- .../android/bluetooth/gatt/ContextMap.java | 19 +++++-- .../android/bluetooth/gatt/GattService.java | 13 +++++ .../bluetooth/gatt/GattServiceTest.java | 12 ++++ .../src/android/bluetooth/GattClientTest.java | 37 ++++++++++++- system/bta/gatt/bta_gattc_act.cc | 2 + system/bta/gatt/bta_gattc_int.h | 4 ++ system/bta/gatt/bta_gattc_utils.cc | 55 +++++++++++++------ 7 files changed, 120 insertions(+), 22 deletions(-) diff --git a/android/app/src/com/android/bluetooth/gatt/ContextMap.java b/android/app/src/com/android/bluetooth/gatt/ContextMap.java index 92fb912213d..ab0af41b469 100644 --- a/android/app/src/com/android/bluetooth/gatt/ContextMap.java +++ b/android/app/src/com/android/bluetooth/gatt/ContextMap.java @@ -64,13 +64,16 @@ public class ContextMap { /** Application entry mapping UUIDs to appIDs and callbacks. */ public class App { /** The UUID of the application */ - public UUID uuid; + public final UUID uuid; /** The id of the application */ public int id; + /** The uid of the application */ + public final int appUid; + /** The package name of the application */ - public String name; + public final String name; /** Application callbacks */ public C callback; @@ -85,9 +88,10 @@ public class ContextMap { private List mCongestionQueue = new ArrayList<>(); /** Creates a new app context. */ - App(UUID uuid, C callback, String name) { + App(UUID uuid, C callback, int appUid, String name) { this.uuid = uuid; this.callback = callback; + this.appUid = appUid; this.name = name; } @@ -150,7 +154,7 @@ public class ContextMap { appName = "Unknown App (UID: " + appUid + ")"; } synchronized (mAppsLock) { - App app = new App(uuid, callback, appName); + App app = new App(uuid, callback, appUid, appName); mApps.add(app); return app; } @@ -334,6 +338,13 @@ public class ContextMap { return currentConnections; } + /** Counts the number of applications that have a given app UID. */ + public int countByAppUid(int appUid) { + synchronized (mAppsLock) { + return (int) (mApps.stream().filter(app -> app.appUid == appUid).count()); + } + } + /** Erases all application context entries. */ public void clear() { synchronized (mAppsLock) { diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index a8755d2e899..b886b8f4d64 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -60,6 +60,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.res.Resources; +import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.HandlerThread; @@ -142,6 +143,8 @@ public class GattService extends ProfileService { "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000", }; + @VisibleForTesting static final int GATT_CLIENT_LIMIT_PER_APP = 32; + public final TransitionalScanHelper mTransitionalScanHelper = new TransitionalScanHelper(this, this::isTestModeEnabled); @@ -2083,6 +2086,16 @@ public class GattService extends ProfileService { this, attributionSource, "GattService registerClient")) { return; } + if (Flags.gattClientDynamicAllocation() + && mClientMap.countByAppUid(Binder.getCallingUid()) >= GATT_CLIENT_LIMIT_PER_APP) { + Log.w(TAG, "registerClient() - failed due to too many clients"); + try { + callback.onClientRegistered(BluetoothGatt.GATT_FAILURE, 0); + } catch (RemoteException e) { + // do nothing + } + return; + } Log.d(TAG, "registerClient() - UUID=" + uuid); mClientMap.add(uuid, callback, this); 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 3c67c100f64..b71c71d52f7 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 @@ -366,6 +366,18 @@ public class GattServiceTest { uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eattSupport); } + @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); + + mService.registerClient(uuid, callback, /* eattSupport= */ true, mAttributionSource); + verify(mClientMap, never()).add(any(), any(), any()); + verify(mNativeInterface, never()).gattClientRegisterApp(anyLong(), anyLong(), anyBoolean()); + } + @Test public void unregisterClient() { int clientIf = 3; diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java index 77af379148d..2af75c96625 100644 --- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java +++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java @@ -54,6 +54,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.AdditionalMatchers; +import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.invocation.Invocation; @@ -480,6 +481,28 @@ public class GattClientTest { return gatt; } + /** Tries to connect GATT, it could fail and return null. */ + private BluetoothGatt tryConnectGatt(BluetoothGattCallback callback) { + advertiseWithBumble(); + + BluetoothDevice device = + mAdapter.getRemoteLeDevice( + Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); + + BluetoothGatt gatt = device.connectGatt(mContext, false, callback); + + ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor stateCaptor = ArgumentCaptor.forClass(Integer.class); + verify(callback, timeout(1000)) + .onConnectionStateChange(eq(gatt), statusCaptor.capture(), stateCaptor.capture()); + + if (statusCaptor.getValue() == GATT_SUCCESS && stateCaptor.getValue() == STATE_CONNECTED) { + return gatt; + } + gatt.close(); + return null; + } + private void disconnectAndWaitDisconnection( BluetoothGatt gatt, BluetoothGattCallback callback) { final int state = BluetoothProfile.STATE_DISCONNECTED; @@ -578,12 +601,22 @@ public class GattClientTest { registerGattService(); List gatts = new ArrayList<>(); + boolean failed = false; final int repeatTimes = 100; try { for (int i = 0; i < repeatTimes; i++) { BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); - BluetoothGatt gatt = connectGattAndWaitConnection(gattCallback); + BluetoothGatt gatt = tryConnectGatt(gattCallback); + // If it fails, close an existing gatt instance and try again. + if (gatt == null) { + failed = true; + BluetoothGatt connectedGatt = gatts.remove(0); + connectedGatt.disconnect(); + connectedGatt.close(); + gattCallback = mock(BluetoothGattCallback.class); + gatt = connectGattAndWaitConnection(gattCallback); + } gatts.add(gatt); gatt.discoverServices(); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); @@ -601,5 +634,7 @@ public class GattClientTest { gatt.close(); } } + // We should fail because we reached the limit. + assertThat(failed).isTrue(); } } diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index 3064e39d97c..bdcec86c9f4 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -311,6 +311,8 @@ void bta_gattc_deregister(tBTA_GATTC_RCB* p_clreg) { }; 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)) { diff --git a/system/bta/gatt/bta_gattc_int.h b/system/bta/gatt/bta_gattc_int.h index c8ac76e124c..c0cfc580e57 100644 --- a/system/bta/gatt/bta_gattc_int.h +++ b/system/bta/gatt/bta_gattc_int.h @@ -349,6 +349,9 @@ typedef struct { tBTA_GATTC_CLCB clcb[BTA_GATTC_CLCB_MAX]; std::unordered_set> clcb_set; + // A set of clcbs that are pending to be deallocated. see bta_gattc_clcb_dealloc + std::unordered_set clcb_pending_dealloc; + tBTA_GATTC_SERV known_server[BTA_GATTC_KNOWN_SR_MAX]; } tBTA_GATTC_CB; @@ -420,6 +423,7 @@ tBTA_GATTC_CLCB* bta_gattc_find_clcb_by_conn_id(tCONN_ID conn_id); tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tGATT_IF client_if, const RawAddress& remote_bda, tBT_TRANSPORT transport); void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB* p_clcb); +void bta_gattc_cleanup_clcb(); void bta_gattc_server_disconnected(tBTA_GATTC_SERV* p_srcb); tBTA_GATTC_CLCB* bta_gattc_find_alloc_clcb(tGATT_IF client_if, const RawAddress& remote_bda, tBT_TRANSPORT transport); diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc index 11e696bc76b..36e05ba8b50 100644 --- a/system/bta/gatt/bta_gattc_utils.cc +++ b/system/bta/gatt/bta_gattc_utils.cc @@ -175,6 +175,7 @@ tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tGATT_IF client_if, const RawAddress& remo 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()); p_clcb = p_clcb_i->get(); @@ -319,26 +320,46 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB* p_clcb) { /* Clear p_clcb. Some of the fields are already reset e.g. p_q_cmd_queue and * p_q_cmd. */ + p_clcb->bta_conn_id = 0; + p_clcb->bda = {}; + p_clcb->transport = BT_TRANSPORT_AUTO; + p_clcb->p_rcb = NULL; + p_clcb->p_srcb = NULL; + p_clcb->request_during_discovery = 0; + p_clcb->auto_update = 0; + p_clcb->disc_active = 0; + p_clcb->in_use = 0; + p_clcb->state = BTA_GATTC_IDLE_ST; + 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()) { - for (auto& p_clcb_i : bta_gattc_cb.clcb_set) { - if (p_clcb_i.get() == p_clcb) { - bta_gattc_cb.clcb_set.erase(p_clcb_i); - break; - } + bta_gattc_cb.clcb_pending_dealloc.insert(p_clcb); + } +} + +/******************************************************************************* + * + * Function bta_gattc_cleanup_clcb + * + * Description cleans up resources from deallocated clcb + * + * Returns none + * + ******************************************************************************/ +void bta_gattc_cleanup_clcb() { + if (bta_gattc_cb.clcb_pending_dealloc.empty()) { + return; + } + auto it = bta_gattc_cb.clcb_set.begin(); + while (it != bta_gattc_cb.clcb_set.end()) { + if (bta_gattc_cb.clcb_pending_dealloc.contains(it->get())) { + it = bta_gattc_cb.clcb_set.erase(it); + } else { + it++; } - } else { - p_clcb->bta_conn_id = 0; - p_clcb->bda = {}; - p_clcb->transport = BT_TRANSPORT_AUTO; - p_clcb->p_rcb = NULL; - p_clcb->p_srcb = NULL; - p_clcb->request_during_discovery = 0; - p_clcb->auto_update = 0; - p_clcb->disc_active = 0; - p_clcb->in_use = 0; - p_clcb->state = BTA_GATTC_IDLE_ST; - p_clcb->status = GATT_SUCCESS; } + bta_gattc_cb.clcb_pending_dealloc.clear(); } /******************************************************************************* -- GitLab From 0619778c0b221e2348ba0b3d697ea0d7f89401c5 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Fri, 27 Sep 2024 00:20:06 +0000 Subject: [PATCH 062/875] Broadcaster: Fix test cases with leaudio_big_depends_on_audio_state Bug: 273864658 Bug: 347204335 Test: atest --host bluetooth_test_broadcaster --no-bazel-mode Change-Id: I8fd810758d2149960abd13770fae3e69cf11f00e --- .../le_audio/broadcaster/broadcaster_test.cc | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/system/bta/le_audio/broadcaster/broadcaster_test.cc b/system/bta/le_audio/broadcaster/broadcaster_test.cc index c69a0745349..063c89e2ee8 100644 --- a/system/bta/le_audio/broadcaster/broadcaster_test.cc +++ b/system/bta/le_audio/broadcaster/broadcaster_test.cc @@ -546,6 +546,14 @@ TEST_F(BroadcasterTest, SuspendAudioBroadcast) { } TEST_F(BroadcasterTest, StartAudioBroadcast) { + com::android::bluetooth::flags::provider_->leaudio_big_depends_on_audio_state(true); + + // Add Audio Actie State while broadcast created + LeAudioSourceAudioHalClient::Callbacks* audio_receiver; + EXPECT_CALL(*mock_audio_source_, Start) + .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) .Times(1); auto broadcast_id = InstantiateBroadcast(); @@ -560,10 +568,9 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) { EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING)) .Times(1); - - LeAudioSourceAudioHalClient::Callbacks* audio_receiver; - EXPECT_CALL(*mock_audio_source_, Start) - .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))); + // Timers not started + ASSERT_TRUE(big_terminate_timer_->cb == nullptr); + ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); ASSERT_NE(audio_receiver, nullptr); @@ -587,6 +594,14 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) { } TEST_F(BroadcasterTest, StartAudioBroadcastMedia) { + com::android::bluetooth::flags::provider_->leaudio_big_depends_on_audio_state(true); + + // Add Audio Actie State while broadcast created + LeAudioSourceAudioHalClient::Callbacks* audio_receiver; + EXPECT_CALL(*mock_audio_source_, Start) + .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) .Times(1); auto broadcast_id = @@ -599,9 +614,10 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) { OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING)) .Times(1); - LeAudioSourceAudioHalClient::Callbacks* audio_receiver; - EXPECT_CALL(*mock_audio_source_, Start) - .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))); + // Timers not started + ASSERT_TRUE(big_terminate_timer_->cb == nullptr); + ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); + EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) .Times(0); EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, false)) @@ -816,12 +832,16 @@ static BasicAudioAnnouncementData prepareAnnouncement( } TEST_F(BroadcasterTest, UpdateMetadataFromAudioTrackMetadata) { - ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA, media_ccid); - auto broadcast_id = InstantiateBroadcast(); + com::android::bluetooth::flags::provider_->leaudio_big_depends_on_audio_state(true); + // Add Audio Actie State while broadcast created LeAudioSourceAudioHalClient::Callbacks* audio_receiver; EXPECT_CALL(*mock_audio_source_, Start) - .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))); + .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))) + .WillRepeatedly(Return(false)); + + ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA, media_ccid); + auto broadcast_id = InstantiateBroadcast(); LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); ASSERT_NE(audio_receiver, nullptr); -- GitLab From fe9f47048c8b242e25bf1830bfcb9f9827a94139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kosi=C5=84ski?= Date: Fri, 27 Sep 2024 01:13:19 +0000 Subject: [PATCH 063/875] Update test for Truth8 deprecation. Truth8 is now included in Truth and importing both no longer works in version 1.4.0. Bug: 369506710 Test: presubmit, m BumbleBluetoothTestsApp Flag: EXEMPT test-only change Change-Id: Idaf8e52e51efa0e260febe1562c37faedb4781f6 --- framework/tests/bumble/Android.bp | 2 +- framework/tests/bumble/build.gradle.kts | 4 ++-- .../tests/bumble/src/android/bluetooth/GattClientTest.java | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/framework/tests/bumble/Android.bp b/framework/tests/bumble/Android.bp index c8a29ff165d..a97112171cb 100644 --- a/framework/tests/bumble/Android.bp +++ b/framework/tests/bumble/Android.bp @@ -35,7 +35,7 @@ android_test_helper_app { "opencensus-java-contrib-grpc-metrics", "pandora-grpc-java", "pandora-proto-java", - "truth-java8-extension", + "truth", ], // Include all test java and kotlin files. diff --git a/framework/tests/bumble/build.gradle.kts b/framework/tests/bumble/build.gradle.kts index 4d926fa1334..e719b41b390 100644 --- a/framework/tests/bumble/build.gradle.kts +++ b/framework/tests/bumble/build.gradle.kts @@ -65,8 +65,8 @@ dependencies { implementation(files("$out/cts/common/device-side/util-axt/compatibility-device-util-axt/android_common/combined/compatibility-device-util-axt.jar")) // Test Parameter Injector implementation(files("$out/external/TestParameterInjector/TestParameterInjector/android_common/combined/TestParameterInjector.jar")) - // TruthJava8 - implementation(files("$out/external/truth/truth-java8-extension/android_common/combined/truth-java8-extension.jar")) + // Truth + implementation(files("$out/external/truth/truth/android_common/combined/truth.jar")) // OkHttp implementation(files("$out/external/grpc-grpc-java/grpc-java-okhttp-client-lite/android_common/combined/grpc-java-okhttp-client-lite.jar")) // Mockito diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java index 77af379148d..91040de36d8 100644 --- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java +++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java @@ -20,7 +20,6 @@ import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth8.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; -- GitLab From 82525286810e81e7d2fbf1606e83b3abd5616664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 27 Sep 2024 06:18:32 +0000 Subject: [PATCH 064/875] leaudio: Fix data path removal when ACL disconnect event arrives first Even on the controller side, Disconnect Event for CIS arrives before Disconnect Event for ACL, it might happen that on the profile layer, those events will come in different order. It happens usually when GATT layer decides to notify profile and ACL disconnection before it actually happens e.g. on GATT response timeout. Stack already handles removing CIS from the streaming in such a case, but datapath was not removed. This patch fixes that. Bug: 355767463 Flag: Exempt, regression verified with unit tests, new test added Test: atest bluetooth_le_audio_test Change-Id: I36e342e8fb246b941e6454c321f19b2bb86a1241 --- system/bta/le_audio/state_machine.cc | 4 ++ system/bta/le_audio/state_machine_test.cc | 55 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 62eae8dc3d7..f4d4d0184cf 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -766,6 +766,10 @@ public: /* It is possible that ACL disconnection came before CIS disconnect event */ for (auto& ase : leAudioDevice->ases_) { + if (ase.data_path_state == DataPathState::CONFIGURED || + ase.data_path_state == DataPathState::CONFIGURING) { + RemoveDataPathByCisHandle(leAudioDevice, ase.cis_conn_hdl); + } group->RemoveCisFromStreamIfNeeded(leAudioDevice, ase.cis_conn_hdl); } diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index bfa0aa507ac..6c255cf9861 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -4704,6 +4704,61 @@ TEST_F(StateMachineTest, testConfigureDataPathForHost) { .source = types::AudioContexts(context_type)})); } +TEST_F(StateMachineTest, testRemoveDataPathWhenSingleBudDisconnectsOnGattTimeout) { + const auto context_type = kContextTypeConversational; + const int leaudio_group_id = 4; + const auto num_devices = 2; + channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel; + + /* Scenario + * 1. Two buds are streaming + * 2. There is a GATT timeout on one of the device which cause disconnection but profile will get + * fist GATT Close and later CIS Disconnection Timeout + * + * 3. Verify that Data Path is removed for the disconnected CIS + */ + + ContentControlIdKeeper::GetInstance()->SetCcid(kContextTypeConversational, call_ccid); + + // Prepare multiple fake connected devices in a group + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + /* Since we prepared device with Ringtone context in mind, only one ASE + * should have been configured. + */ + PrepareConfigureCodecHandler(group); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareReceiverStartReadyHandler(group); + + EXPECT_CALL(*mock_iso_manager_, + SetupIsoDataPath(_, dataPathIsEq(bluetooth::hci::iso_manager::kIsoDataPathHci))) + .Times(4); + + InjectInitialIdleNotification(group); + + // Start the configuration and stream Media content + ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream( + group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)})); + + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); + + EXPECT_CALL(*mock_iso_manager_, + RemoveIsoDataPath( + _, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput | + bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput)) + .Times(1); + + auto device = group->GetFirstDevice(); + InjectAclDisconnected(group, device); + InjectCisDisconnected(group, device, HCI_ERR_CONN_CAUSE_LOCAL_HOST); + + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); +} + TEST_F(StateMachineTestAdsp, testConfigureDataPathForAdsp) { const auto context_type = kContextTypeRingtone; const int leaudio_group_id = 4; -- GitLab From 84bfcf3737287307c7c87396e127d04f4070895d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 25 Sep 2024 16:33:43 +0000 Subject: [PATCH 065/875] leaudio: Improve sending QoSConfigure when CIG is already created There are some cases when ASEs are reconfigured from the QoS Configured state but CIG does not have to be recreated. Usually this is when one device connects while another is not yet in STREAMING state. This patch improves this handling in the way that 1. StartStream() tries to assigne proper configuration to ASEs when detects this. 2. StateMachine will continue with QoSConfigure for whole set, when CIG is already there. Bug: 331775328 Test: atest bluetooth_le_audio_test Flag: Exempt, regression tested with unit test new test added Change-Id: I66c6316d7bd1579aef26607f32c77e154e25a205 --- system/bta/le_audio/state_machine.cc | 45 +++++++++- system/bta/le_audio/state_machine_test.cc | 103 ++++++++++++++++++++++ 2 files changed, 145 insertions(+), 3 deletions(-) diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 7c9de8095aa..1f68c56063f 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -241,7 +241,25 @@ public: case AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED: { LeAudioDevice* leAudioDevice = group->GetFirstActiveDevice(); if (!leAudioDevice) { - log::error("group has no active devices"); + group->PrintDebugState(); + log::error("group_id: {} has no active devices", group->group_id_); + return false; + } + + if (!group->IsConfiguredForContext(context_type)) { + if (group->GetConfigurationContextType() == context_type) { + log::info( + "Looks like another device connected in the meantime to group_id: {}, try to " + "reconfigure.", + group->group_id_); + if (group->Configure(context_type, metadata_context_types, ccid_lists)) { + return PrepareAndSendCodecConfigToTheGroup(group); + } + } + log::error("Trying to start stream not configured for the context {} in group_id: {} ", + ToString(context_type), group->group_id_); + group->PrintDebugState(); + StopStream(group); return false; } @@ -1864,6 +1882,7 @@ private: } std::vector value; + log::info("{} -> ", leAudioDevice->address_); bluetooth::le_audio::client_parser::ascs::PrepareAseCtpCodecConfig(confs, value); WriteToControlPoint(leAudioDevice, value); @@ -1997,8 +2016,12 @@ private: if (group->cig.GetState() == CigState::CREATED) { /* It can happen on the earbuds switch scenario. When one device * is getting remove while other is adding to the stream and CIG is - * already created */ - PrepareAndSendConfigQos(group, leAudioDevice); + * already created. + * Also if one of the set members got reconnected while the other was in QoSConfigured + * state. In this case, state machine will keep CIG but will send Codec Config to all + * the set members and when ASEs will move to Codec Configured State, we would like a + * whole group to move to QoS Configure.*/ + PrepareAndSendQoSToTheGroup(group); } else if (!CigCreate(group)) { log::error("Could not create CIG. Stop the stream for group {}", group->group_id_); StopStream(group); @@ -2467,12 +2490,23 @@ private: msg_stream << kLogAseQoSConfigOp; std::stringstream extra_stream; + int number_of_active_ases = 0; + int number_of_streaming_ases = 0; for (struct ase* ase = leAudioDevice->GetFirstActiveAse(); ase != nullptr; ase = leAudioDevice->GetNextActiveAse(ase)) { log::debug("device: {}, ase_id: {}, cis_id: {}, ase state: {}", leAudioDevice->address_, ase->id, ase->cis_id, ToString(ase->state)); + /* QoS Config can be done on ASEs which are in Codec Configured and QoS Configured state. + * If ASE is streaming, it can be skipped. + */ + number_of_active_ases++; + if (ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { + number_of_streaming_ases++; + continue; + } + /* Fill in the whole group dependent ASE parameters */ if (!group->GetPresentationDelay(&ase->qos_config.presentation_delay, ase->direction)) { log::error("inconsistent presentation delay for group"); @@ -2523,6 +2557,11 @@ private: << +conf.retrans_nb << "," << +conf.phy << "," << +conf.framing << ";;"; } + if (number_of_streaming_ases > 0 && number_of_streaming_ases == number_of_active_ases) { + log::debug("Device {} is already streaming", leAudioDevice->address_); + return; + } + if (confs.size() == 0 || !validate_transport_latency || !validate_max_sdu_size) { log::error("Invalid configuration or latency or sdu size"); group->PrintDebugState(); diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index 02fd745aa34..4250716b461 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -709,6 +709,20 @@ protected: return &(*group); } + void InjectAclConnected(LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice, + uint16_t conn_id) { + // Do what the client.cc does when handling the disconnection event + leAudioDevice->conn_id_ = conn_id; + leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED); + + /* Update all stuff on the group when device got connected */ + group->ReloadAudioLocations(); + group->ReloadAudioDirections(); + group->UpdateAudioContextAvailability(); + group->InvalidateCachedConfigurations(); + group->InvalidateGroupStrategy(); + } + void InjectAclDisconnected(LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { // Do what the client.cc does when handling the disconnection event leAudioDevice->conn_id_ = GATT_INVALID_CONN_ID; @@ -6745,6 +6759,95 @@ TEST_F(StateMachineTest, testAttachDeviceToTheConversationalStream) { types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING)); } +TEST_F(StateMachineTest, ReconfigureGroupWhenSecondDeviceConnectsAndFirstIsInQoSConfiguredState) { + const auto context_type = kContextTypeMedia; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + /** + * Scenario + * 1. One set member is connected and configured to QoS + * 2. Second set member connects and group is configured after that + * 3. Expect Start stream and expect to get Codec Config and later QoS Config on both devices. + * + */ + ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); + + // Prepare multiple fake connected devices in a group + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group, 0, true); + PrepareConfigureQosHandler(group); + + InjectInitialIdleNotification(group); + + auto* leAudioDevice = group->GetFirstDevice(); + LeAudioDevice* firstDevice = leAudioDevice; + LeAudioDevice* secondDevice = group->GetNextDevice(leAudioDevice); + uint16_t stored_conn_id = secondDevice->conn_id_; + + log::info("Inject disconnect second device"); + InjectAclDisconnected(group, secondDevice); + + /* Three Writes: + * 1. Codec configure + * 2. Codec QoS + * 3. Enable + */ + EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl, + _, GATT_WRITE_NO_RSP, _, _)) + .Times(3); + + EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + {.sink = {}, .source = {}}); + + /* Check if group has transitioned to a proper state */ + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); + + testing::Mock::VerifyAndClearExpectations(&gatt_queue); + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); + + log::info("Inject connecting second device"); + InjectAclConnected(group, secondDevice, stored_conn_id); + + PrepareEnableHandler(group); + + EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(0); + EXPECT_CALL(*mock_iso_manager_, RemoveCig).Times(0); + + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)); + + /* Three Writes: + * 1. Codec configure + * 2. Codec QoS + * 3. Enable + */ + EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl, + _, GATT_WRITE_NO_RSP, _, _)) + .Times(3); + EXPECT_CALL(gatt_queue, + WriteCharacteristic(secondDevice->conn_id_, secondDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(3); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + {.sink = {}, .source = {}}); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + testing::Mock::VerifyAndClearExpectations(&gatt_queue); + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); +} + TEST_F(StateMachineTest, StartStreamAfterConfigure) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; -- GitLab From 4a6cbce67914d85c5087f63f80da053673f6d772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 25 Sep 2024 16:42:28 +0000 Subject: [PATCH 066/875] leaudio: Improve LeAudio switch during phone call When LeAudio Group is getting Active during phone call it is because user changed the output device for a phone call. This operations is quite heavy as it takes Telecom/Audio Framework and Bluetooth time and resources. The step by step scenario looks like this: 1. Telecom clears current communication device (could be also Bluetooth) 2. Telecom enables Audio for Bluetooth device 3. LeAudioService calls native to set group as active (GroupSetActive) 4. leaudio native stack starts audio session and notifies upper layer about that 5. LeAudioService requests Audio Manager to connect LeAudio device 6. Audio Manager reads LeAudio device capabilities 7. Audio Manager notifies about LeAudio device being connected 8. LeAudioService notifies users (and Telecom) about LeAudio device being connected 9. Telecom choose new communication device 10. Audio HAL Resumes Bluetooth Encoding session which triggers ASE Configuration up to Streaming The whole thing can take up to 4 sec With this patch, followining modifications are added in following steps 4. in addition to previous steps, if native stack detects ongoing call, it will start ASE configuration for Conversational use case up to QoS Configure state 10. Here instade of complete ASE configuration, only Enable ASE is left. This can decrease time by 1.5 sec Bug: 308510081 Bug: 369322905 Test: atest bluetooth_le_audio_test bluetooth_le_audio_client_test Flag: com::android::bluetooth:flags::leaudio_improve_switch_during_phone_call Change-Id: Iaedd00594e6caa17495435c897e76c199c61eca9 --- system/bta/le_audio/client.cc | 36 +++++ system/bta/le_audio/le_audio_client_test.cc | 140 ++++++++++++++++++-- system/bta/le_audio/mock_state_machine.h | 3 +- system/bta/le_audio/state_machine.cc | 36 ++++- system/bta/le_audio/state_machine.h | 4 +- system/bta/le_audio/state_machine_test.cc | 127 ++++++++++++++++++ 6 files changed, 325 insertions(+), 21 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 448ad8beda2..8b50ff41ce1 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -1302,6 +1302,35 @@ public: active_group_id_ = bluetooth::groups::kGroupUnknown; } + void PrepareStreamForAConversational(LeAudioDeviceGroup* group) { + if (!com::android::bluetooth::flags::leaudio_improve_switch_during_phone_call()) { + log::info("Flag leaudio_improve_switch_during_phone_call is not enabled"); + return; + } + + log::debug("group_id: {}", group->group_id_); + + auto remote_direction = bluetooth::le_audio::types::kLeAudioDirectionSink; + ReconfigureOrUpdateRemote(group, remote_direction); + + if (configuration_context_type_ != LeAudioContextType::CONVERSATIONAL) { + log::error("Something went wrong {} != {} ", ToString(configuration_context_type_), + ToString(LeAudioContextType::CONVERSATIONAL)); + return; + } + + BidirectionalPair> ccids = { + .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids( + local_metadata_context_types_.sink), + .source = ContentControlIdKeeper::GetInstance()->GetAllCcids( + local_metadata_context_types_.source)}; + if (!groupStateMachine_->ConfigureStream(group, configuration_context_type_, + local_metadata_context_types_, ccids, true)) { + log::info("Reconfiguration is needed for group {}", group->group_id_); + initReconfiguration(group, LeAudioContextType::UNSPECIFIED); + } + } + void GroupSetActive(const int group_id) override { log::info("group_id: {}", group_id); @@ -1418,6 +1447,13 @@ public: callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE); SendAudioGroupSelectableCodecConfigChanged(group); } + + /* If group become active while phone call, let's configure it right away, + * so when audio framework resumes the stream, it will be almost there. + */ + if (IsInCall()) { + PrepareStreamForAConversational(group); + } } void SetEnableState(const RawAddress& address, bool enabled) override { diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 995aff27816..0d10c9c832e 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -851,16 +851,19 @@ protected: ON_CALL(mock_state_machine_, Initialize(_)) .WillByDefault(SaveArg<0>(&state_machine_callbacks_)); - ON_CALL(mock_state_machine_, ConfigureStream(_, _, _, _)) + ON_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)) .WillByDefault([this](LeAudioDeviceGroup* group, types::LeAudioContextType context_type, types::BidirectionalPair metadata_context_types, - types::BidirectionalPair> ccid_lists) { + types::BidirectionalPair> ccid_lists, + bool configure_qos) { bool isReconfiguration = group->IsPendingConfiguration(); - log::info("ConfigureStream: group_id {}, context_type {} isReconfiguration {}", - group->group_id_, bluetooth::common::ToString(context_type), - isReconfiguration); + log::info( + "ConfigureStream: group_id {}, context_type {}, configure_qos {}, " + "isReconfiguration {}", + group->group_id_, bluetooth::common::ToString(context_type), configure_qos, + isReconfiguration); /* Do what ReleaseCisIds(group) does: start */ LeAudioDevice* leAudioDevice = group->GetFirstDevice(); @@ -885,6 +888,12 @@ protected: types::AseState config_state = types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; + if (configure_qos) { + // Make sure CIG is created + config_state = types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED; + group->cig.SetState(types::CigState::CREATED); + } + for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr; device = group->GetNextDevice(device)) { if (!group->cig.AssignCisIds(device)) { @@ -4855,6 +4864,111 @@ TEST_F(UnicastTest, GroupSetActive_and_InactiveDuringStreamConfiguration) { Mock::VerifyAndClearExpectations(&mock_state_machine_); } +TEST_F(UnicastTest, GroupSetActive_and_GroupSetInactive_DuringPhoneCall) { + com::android::bluetooth::flags::provider_->leaudio_improve_switch_during_phone_call(true); + const RawAddress test_address0 = GetTestAddress(0); + int group_id = bluetooth::groups::kGroupUnknown; + + /** + * Scenario: + * 1. Call is started + * 2. Group is set active - it is expected the state machine to be instructed to Configure to Qos + * 3. Group is set to inactive - it is expected that state machine is instructed to stop * + */ + + default_channel_cnt = 1; + + SetSampleDatabaseEarbudsValid( + 1, test_address0, codec_spec_conf::kLeAudioLocationStereo, + codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004, + /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/, + default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnConnectionState(ConnectionState::CONNECTED, test_address0)) + .Times(1); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) + .WillOnce(DoAll(SaveArg<1>(&group_id))); + + ConnectLeAudio(test_address0); + ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); + + EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, true)).Times(1); + + log::info("Call is started and group is getting Active"); + LeAudioClient::Get()->SetInCall(true); + LeAudioClient::Get()->GroupSetActive(group_id); + + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); + + log::info("Group is getting inctive"); + EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1); + LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); + + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); +} + +TEST_F(UnicastTest, GroupSetActive_DuringPhoneCall_ThenResume) { + com::android::bluetooth::flags::provider_->leaudio_improve_switch_during_phone_call(true); + const RawAddress test_address0 = GetTestAddress(0); + int group_id = bluetooth::groups::kGroupUnknown; + + /** + * Scenario: + * 1. Call is started + * 2. Group is set active - it is expected the state machine to be instructed to Configure to Qos + * 3. Audio Framework callse Resume - expect stream is started. + * 4. Group is set to inactive - it is expected that state machine is instructed to stop * + */ + + default_channel_cnt = 1; + + SetSampleDatabaseEarbudsValid( + 1, test_address0, codec_spec_conf::kLeAudioLocationStereo, + codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004, + /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/, + default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnConnectionState(ConnectionState::CONNECTED, test_address0)) + .Times(1); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) + .WillOnce(DoAll(SaveArg<1>(&group_id))); + + ConnectLeAudio(test_address0); + ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); + + EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, true)).Times(1); + + log::info("Call is started and group is getting Active"); + LeAudioClient::Get()->SetInCall(true); + LeAudioClient::Get()->GroupSetActive(group_id); + + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); + + log::info("AF resumes the stream"); + /* Simulate resume and expect StartStream to be called. + * Do not expect confirmation on resume, as this part is not mocked on the state machine + */ + EXPECT_CALL(mock_state_machine_, StartStream(_, LeAudioContextType::CONVERSATIONAL, _, _)) + .Times(1); + LocalAudioSourceResume(true, false); + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); + + log::info("Group is getting inactive"); + EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1); + LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); + + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); +} + TEST_F(UnicastTest, ChangeAvailableContextTypeWhenInCodecConfigured) { const RawAddress test_address0 = GetTestAddress(0); int group_id = bluetooth::groups::kGroupUnknown; @@ -8133,7 +8247,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) { .source = types::AudioContexts()}; EXPECT_CALL(mock_state_machine_, ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, - ccids)) + ccids, _)) .Times(1); StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, true); @@ -8202,7 +8316,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigF EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()) .Times(1) .After(reconfigure); - EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _)).Times(1); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1); // SetInCall is used by GTBS - and only then we can expect CCID to be set. LeAudioClient::Get()->SetInCall(true); SyncOnMainLoop(); @@ -8237,7 +8351,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigF EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()) .Times(1) .After(reconfigure); - EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _)).Times(1); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1); LeAudioClient::Get()->SetInCall(false); SyncOnMainLoop(); @@ -8253,7 +8367,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigF .source = types::AudioContexts()}; EXPECT_CALL(mock_state_machine_, ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, - ccids)) + ccids, _)) .Times(0); EXPECT_CALL( mock_state_machine_, @@ -8405,7 +8519,7 @@ TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) { .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)}; EXPECT_CALL(mock_state_machine_, - ConfigureStream(_, types::LeAudioContextType::CONVERSATIONAL, _, _)) + ConfigureStream(_, types::LeAudioContextType::CONVERSATIONAL, _, _, _)) .Times(AtLeast(1)); // Update metadata and resume @@ -9743,7 +9857,7 @@ TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) { // When the local audio sink resumes we should reconfigure EXPECT_CALL(mock_state_machine_, - ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, _, _)) + ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, _, _, _)) .Times(1); EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(1); @@ -10156,7 +10270,7 @@ TEST_F(UnicastTest, UpdateMultipleBidirContextTypes_SpeedUpReconfigFlagEnabled) EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0); EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(0); EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0); - EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _)).Times(0); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0); EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0); LeAudioClient::Get()->SetInCall(true); SyncOnMainLoop(); @@ -10191,7 +10305,7 @@ TEST_F(UnicastTest, UpdateMultipleBidirContextTypes_SpeedUpReconfigFlagEnabled) EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0); EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(0); EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0); - EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _)).Times(0); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0); EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0); LeAudioClient::Get()->SetInCall(false); diff --git a/system/bta/le_audio/mock_state_machine.h b/system/bta/le_audio/mock_state_machine.h index 90077fddb4a..bee2ea65991 100644 --- a/system/bta/le_audio/mock_state_machine.h +++ b/system/bta/le_audio/mock_state_machine.h @@ -41,7 +41,8 @@ public: bluetooth::le_audio::types::LeAudioContextType context_type, const bluetooth::le_audio::types::BidirectionalPair< bluetooth::le_audio::types::AudioContexts>& metadata_context_types, - bluetooth::le_audio::types::BidirectionalPair> ccid_lists), + bluetooth::le_audio::types::BidirectionalPair> ccid_lists, + bool configure_qos), (override)); MOCK_METHOD((void), StopStream, (bluetooth::le_audio::LeAudioDeviceGroup * group), (override)); MOCK_METHOD((void), ProcessGattNotifEvent, diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 1f68c56063f..181679d40f7 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -301,13 +301,26 @@ public: bool ConfigureStream(LeAudioDeviceGroup* group, LeAudioContextType context_type, const BidirectionalPair& metadata_context_types, - BidirectionalPair> ccid_lists) override { + BidirectionalPair> ccid_lists, + bool configure_qos) override { if (group->GetState() > AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) { log::error("Stream should be stopped or in configured stream. Current state: {}", ToString(group->GetState())); return false; } + if (configure_qos) { + if (group->IsConfiguredForContext(context_type)) { + if (group->Activate(context_type, metadata_context_types, ccid_lists)) { + SetTargetState(group, AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); + if (CigCreate(group)) { + return true; + } + } + } + log::info("Could not activate device, try to configure it again"); + } + group->Deactivate(); ReleaseCisIds(group); @@ -319,7 +332,11 @@ public: } group->cig.GenerateCisIds(context_type); - SetTargetState(group, AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); + if (configure_qos) { + SetTargetState(group, AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); + } else { + SetTargetState(group, AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); + } return PrepareAndSendCodecConfigToTheGroup(group); } @@ -507,7 +524,8 @@ public: group->group_id_, ToString(group->cig.GetState()), static_cast(conn_handles.size())); - if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { + if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING && + group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { /* Group is not going to stream. It happen while CIG was creating. * Remove CIG in such a case */ @@ -2012,7 +2030,8 @@ private: /* Last node configured, process group to codec configured state */ group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); - if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { + if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING || + group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { if (group->cig.GetState() == CigState::CREATED) { /* It can happen on the earbuds switch scenario. When one device * is getting remove while other is adding to the stream and CIG is @@ -2224,7 +2243,8 @@ private: case AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED: { SetAseState(leAudioDevice, ase, AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); - if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { + if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING && + group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { log::warn("{}, ase_id: {}, target state: {}", leAudioDevice->address_, ase->id, ToString(group->GetTargetState())); group->PrintDebugState(); @@ -2252,6 +2272,12 @@ private: group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED); + if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) { + cancel_watchdog_if_needed(group->group_id_); + state_machine_callbacks_->StatusReportCb(group->group_id_, + GroupStreamStatus::CONFIGURED_BY_USER); + return; + } PrepareAndSendEnableToTheGroup(group); break; diff --git a/system/bta/le_audio/state_machine.h b/system/bta/le_audio/state_machine.h index d5b49aebf6f..19b50e68c95 100644 --- a/system/bta/le_audio/state_machine.h +++ b/system/bta/le_audio/state_machine.h @@ -57,8 +57,8 @@ public: virtual bool ConfigureStream( LeAudioDeviceGroup* group, types::LeAudioContextType context_type, const types::BidirectionalPair& metadata_context_types, - types::BidirectionalPair> ccid_lists = {.sink = {}, - .source = {}}) = 0; + types::BidirectionalPair> ccid_lists = {.sink = {}, .source = {}}, + bool configure_qos = false) = 0; virtual void StopStream(LeAudioDeviceGroup* group) = 0; virtual void ProcessGattCtpNotification(LeAudioDeviceGroup* group, uint8_t* value, uint16_t len) = 0; diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index 4250716b461..03da2ede685 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -6848,6 +6848,133 @@ TEST_F(StateMachineTest, ReconfigureGroupWhenSecondDeviceConnectsAndFirstIsInQoS testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); } +TEST_F(StateMachineTest, StartStreamAfterConfigureToQoS) { + const auto context_type = kContextTypeMedia; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); + + // Prepare multiple fake connected devices in a group + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group, 0, true); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + + InjectInitialIdleNotification(group); + + auto* leAudioDevice = group->GetFirstDevice(); + auto expected_devices_written = 0; + while (leAudioDevice) { + /* Three Writes: + * 1. Codec configure + * 2: Codec QoS + * 3: Enabling + */ + EXPECT_CALL(gatt_queue, + WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(3); + expected_devices_written++; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + ASSERT_EQ(expected_devices_written, num_devices); + + // Validate GroupStreamStatus + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER)); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + {.sink = {}, .source = {}}, true); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + + // Validate GroupStreamStatus + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); +} + +TEST_F(StateMachineTest, StopStreamAfterConfigureToQoS) { + const auto context_type = kContextTypeMedia; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); + + // Prepare multiple fake connected devices in a group + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group, 0, true); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + + InjectInitialIdleNotification(group); + + auto* leAudioDevice = group->GetFirstDevice(); + auto expected_devices_written = 0; + while (leAudioDevice) { + /* Three Writes: + * 1. Codec configure + * 2: Codec QoS + * 3: Release + */ + EXPECT_CALL(gatt_queue, + WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(3); + expected_devices_written++; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + ASSERT_EQ(expected_devices_written, num_devices); + + // Validate GroupStreamStatus + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER)); + + // Start the configuration and stream Media content + group->SetPendingConfiguration(); + LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + {.sink = {}, .source = {}}, true); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + + group->ClearPendingConfiguration(); + // Validate GroupStreamStatus (since caching is on CONFIGURE_AUTONOMOUS will be the last state) + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING)); + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS)); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StopStream(group); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); +} + TEST_F(StateMachineTest, StartStreamAfterConfigure) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; -- GitLab From efb56a2b06210158c0264cb84428b5e200e3ad9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Thu, 26 Sep 2024 14:08:31 +0000 Subject: [PATCH 067/875] leaudio: Remove reduntant context type copy With latest aligment of context type between directions, it is not necessary to set local_metadata_context_types_.sink when local_metadata_context_types_.source has changed. This actually can break future context type when we set context type with high priority e.g. CONVERSATIONAL Bug: 367894783 Flag: Exempt, regression tested with unit test Test: atest bluetooth_le_audio_client_test Change-Id: I957b331f0bfd7b8d60b971fcf0e7903004ae480f --- system/bta/le_audio/client.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 448ad8beda2..c7a48adaa92 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -4573,8 +4573,6 @@ public: /* Set the remote sink metadata context from the playback tracks metadata */ local_metadata_context_types_.source = GetAudioContextsFromSourceMetadata(source_metadata); - local_metadata_context_types_.sink = - ChooseMetadataContextType(local_metadata_context_types_.sink); local_metadata_context_types_.source = ChooseMetadataContextType(local_metadata_context_types_.source); -- GitLab From 674384c6f9625483da33098c93919560c9fda0a0 Mon Sep 17 00:00:00 2001 From: Yun-Hao Chung Date: Wed, 25 Sep 2024 08:24:46 +0000 Subject: [PATCH 068/875] Floss: Allow set log level from btclient In some cases we want to ask user to provide verbose logs but this is impossible if they are not in developer mode. This implements the commands in btclient to set and get the current log level via btclient. Bug: 369506387 Tag: #floss Test: mmm packages/modules/Bluetooth Test: Deploy to ciri and verified manually Flag: EXEMPT, Floss-only changes Change-Id: I38777d0d66c9f570b944c018389215919e8f0064 --- .../rust/linux/client/src/command_handler.rs | 47 ++++++++ system/gd/rust/linux/client/src/dbus_iface.rs | 57 ++++++++++ system/gd/rust/linux/client/src/main.rs | 12 ++- .../rust/linux/service/src/iface_logging.rs | 19 ++++ .../rust/linux/stack/src/bluetooth_logging.rs | 101 ++++++++++++------ system/gd/rust/topshim/src/syslog.rs | 24 ++++- 6 files changed, 219 insertions(+), 41 deletions(-) diff --git a/system/gd/rust/linux/client/src/command_handler.rs b/system/gd/rust/linux/client/src/command_handler.rs index a2891893ac8..6be39fa3d5a 100644 --- a/system/gd/rust/linux/client/src/command_handler.rs +++ b/system/gd/rust/linux/client/src/command_handler.rs @@ -16,12 +16,14 @@ use bt_topshim::profiles::gatt::{GattStatus, LePhy}; use bt_topshim::profiles::hid_host::BthhReportType; use bt_topshim::profiles::sdp::{BtSdpMpsRecord, BtSdpRecord}; use bt_topshim::profiles::ProfileConnectionState; +use bt_topshim::syslog::Level; use btstack::battery_manager::IBatteryManager; use btstack::bluetooth::{BluetoothDevice, IBluetooth}; use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattDbElementType, GattWriteType, IBluetoothGatt, }; +use btstack::bluetooth_logging::IBluetoothLogging; use btstack::bluetooth_media::{IBluetoothMedia, IBluetoothTelephony}; use btstack::bluetooth_qa::IBluetoothQA; use btstack::socket_manager::{IBluetoothSocketManager, SocketResult}; @@ -397,6 +399,17 @@ fn build_commands() -> HashMap { function_pointer: CommandHandler::cmd_dumpsys, }, ); + command_options.insert( + String::from("log"), + CommandOption { + rules: vec![ + String::from("log set-level "), + String::from("log get-level"), + ], + description: String::from("Get/set log level"), + function_pointer: CommandHandler::cmd_log, + }, + ); command_options } @@ -2353,6 +2366,40 @@ impl CommandHandler { Ok(()) } + + fn cmd_log(&mut self, args: &[String]) -> CommandResult { + if !self.lock_context().adapter_ready { + return Err(self.adapter_not_ready()); + } + + let command = get_arg(args, 0)?; + + match &command[..] { + "set-level" => { + let level = match &get_arg(args, 1)?[..] { + "info" => Level::Info, + "debug" => Level::Debug, + "verbose" => Level::Verbose, + _ => { + return Err("Failed to parse log level".into()); + } + }; + self.lock_context().logging_dbus.as_mut().unwrap().set_log_level(level); + } + + "get-level" => { + let level = self.lock_context().logging_dbus.as_ref().unwrap().get_log_level(); + + print_info!("log level: {:?}", level); + } + + other => { + return Err(format!("Invalid argument '{}'", other).into()); + } + } + + Ok(()) + } } #[cfg(test)] diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index 39772fc153a..a2f7ad64eaa 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -24,6 +24,7 @@ use bt_topshim::profiles::sdp::{ }; use bt_topshim::profiles::socket::SocketType; use bt_topshim::profiles::ProfileConnectionState; +use bt_topshim::syslog::Level; use btstack::battery_manager::{Battery, BatterySet, IBatteryManager, IBatteryManagerCallback}; use btstack::bluetooth::{ @@ -52,6 +53,7 @@ use btstack::socket_manager::{ }; use btstack::{RPCProxy, SuspendMode}; +use btstack::bluetooth_logging::IBluetoothLogging; use btstack::suspend::{ISuspend, ISuspendCallback, SuspendType}; use dbus::arg::RefArg; @@ -115,6 +117,7 @@ impl_dbus_arg_enum!(BthhReportType); impl_dbus_arg_enum!(BtAdapterRole); impl_dbus_arg_enum!(BtSdpType); +impl_dbus_arg_enum!(Level); #[dbus_propmap(BtSdpHeaderOverlay)] struct BtSdpHeaderOverlayDBus { @@ -3074,3 +3077,57 @@ impl IBatteryManagerCallback for IBatteryManagerCallbackDBus { #[dbus_method("OnBatteryInfoUpdated")] fn on_battery_info_updated(&mut self, remote_address: RawAddress, battery_set: BatterySet) {} } + +#[allow(dead_code)] +pub(crate) struct BluetoothLoggingDBusRPC { + client_proxy: ClientDBusProxy, +} + +#[allow(dead_code)] +pub(crate) struct BluetoothLoggingDBus { + client_proxy: ClientDBusProxy, + pub rpc: BluetoothLoggingDBusRPC, +} + +impl BluetoothLoggingDBus { + fn make_client_proxy(conn: Arc, index: i32) -> ClientDBusProxy { + ClientDBusProxy::new( + conn.clone(), + String::from("org.chromium.bluetooth"), + make_object_path(index, "logging"), + String::from("org.chromium.bluetooth.Logging"), + ) + } + + pub(crate) fn new(conn: Arc, index: i32) -> BluetoothLoggingDBus { + BluetoothLoggingDBus { + client_proxy: Self::make_client_proxy(conn.clone(), index), + rpc: BluetoothLoggingDBusRPC { + client_proxy: Self::make_client_proxy(conn.clone(), index), + }, + } + } +} + +#[generate_dbus_interface_client(BluetoothLoggingDBusRPC)] +impl IBluetoothLogging for BluetoothLoggingDBus { + #[dbus_method("IsDebugEnabled")] + fn is_debug_enabled(&self) -> bool { + dbus_generated!() + } + + #[dbus_method("SetDebugLogging")] + fn set_debug_logging(&mut self, enabled: bool) { + dbus_generated!() + } + + #[dbus_method("SetLogLevel")] + fn set_log_level(&mut self, level: Level) { + dbus_generated!() + } + + #[dbus_method("GetLogLevel")] + fn get_log_level(&self) -> Level { + dbus_generated!() + } +} diff --git a/system/gd/rust/linux/client/src/main.rs b/system/gd/rust/linux/client/src/main.rs index 8d609b7cd0f..f2e9f3c165a 100644 --- a/system/gd/rust/linux/client/src/main.rs +++ b/system/gd/rust/linux/client/src/main.rs @@ -20,9 +20,9 @@ use crate::callbacks::{ }; use crate::command_handler::{CommandHandler, SocketSchedule}; use crate::dbus_iface::{ - BatteryManagerDBus, BluetoothAdminDBus, BluetoothDBus, BluetoothGattDBus, BluetoothManagerDBus, - BluetoothMediaDBus, BluetoothQADBus, BluetoothQALegacyDBus, BluetoothSocketManagerDBus, - BluetoothTelephonyDBus, SuspendDBus, + BatteryManagerDBus, BluetoothAdminDBus, BluetoothDBus, BluetoothGattDBus, BluetoothLoggingDBus, + BluetoothManagerDBus, BluetoothMediaDBus, BluetoothQADBus, BluetoothQALegacyDBus, + BluetoothSocketManagerDBus, BluetoothTelephonyDBus, SuspendDBus, }; use crate::editor::AsyncEditor; use bt_topshim::{btif::RawAddress, topstack}; @@ -113,6 +113,9 @@ pub(crate) struct ClientContext { /// Proxy for battery manager interface. pub(crate) battery_manager_dbus: Option, + /// Proxy for logging interface. + pub(crate) logging_dbus: Option, + /// Channel to send actions to take in the foreground fg: mpsc::Sender, @@ -201,6 +204,7 @@ impl ClientContext { telephony_dbus: None, media_dbus: None, battery_manager_dbus: None, + logging_dbus: None, fg: tx, dbus_connection, dbus_crossroads, @@ -269,6 +273,8 @@ impl ClientContext { self.battery_manager_dbus = Some(BatteryManagerDBus::new(conn.clone(), idx)); + self.logging_dbus = Some(BluetoothLoggingDBus::new(conn.clone(), idx)); + // Trigger callback registration in the foreground let fg = self.fg.clone(); tokio::spawn(async move { diff --git a/system/gd/rust/linux/service/src/iface_logging.rs b/system/gd/rust/linux/service/src/iface_logging.rs index f30e30ce4f7..9bf66f47615 100644 --- a/system/gd/rust/linux/service/src/iface_logging.rs +++ b/system/gd/rust/linux/service/src/iface_logging.rs @@ -1,12 +1,21 @@ use crate::dbus_arg::DBusArg; +use bt_topshim::syslog::Level; use btstack::bluetooth_logging::IBluetoothLogging; use dbus_macros::{dbus_method, generate_dbus_exporter}; use dbus_projection::prelude::*; +use num_traits::cast::{FromPrimitive, ToPrimitive}; + +use crate::dbus_arg::DBusArgError; +use dbus::nonblock::SyncConnection; +use std::sync::Arc; + #[allow(dead_code)] struct IBluetoothLoggingDBus {} +impl_dbus_arg_enum!(Level); + #[generate_dbus_exporter(export_bluetooth_logging_dbus_intf, "org.chromium.bluetooth.Logging")] impl IBluetoothLogging for IBluetoothLoggingDBus { #[dbus_method("IsDebugEnabled")] @@ -18,4 +27,14 @@ impl IBluetoothLogging for IBluetoothLoggingDBus { fn set_debug_logging(&mut self, enabled: bool) { dbus_generated!() } + + #[dbus_method("SetLogLevel")] + fn set_log_level(&mut self, level: Level) { + dbus_generated!() + } + + #[dbus_method("GetLogLevel")] + fn get_log_level(&self) -> Level { + dbus_generated!() + } } diff --git a/system/gd/rust/linux/stack/src/bluetooth_logging.rs b/system/gd/rust/linux/stack/src/bluetooth_logging.rs index aa2a0c0e189..fea9303a333 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_logging.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_logging.rs @@ -17,17 +17,19 @@ pub trait IBluetoothLogging { /// Change whether debug logging is enabled. fn set_debug_logging(&mut self, enabled: bool); + + /// Set the log level. + fn set_log_level(&mut self, level: Level); + + /// Get the log level. + fn get_log_level(&self) -> Level; } /// Logging related implementation. pub struct BluetoothLogging { - /// Should debug logs be emitted? - is_debug: bool, - - /// If this flag is not set, we will not emit debug logs for all tags. - /// `VERBOSE_ONLY_LOG_TAGS` will be set to emit up to `INFO` only. This - /// can only be configured in the constructor (not modifiable at runtime). - is_verbose_debug: bool, + /// Current log level + /// If the level is not verbose, `VERBOSE_ONLY_LOG_TAGS` will be set to emit up to `INFO` only. + log_level: Level, /// Log to stderr? is_stderr: bool, @@ -48,14 +50,19 @@ const VERBOSE_ONLY_LOG_TAGS: &[&str] = &[ impl BluetoothLogging { pub fn new(is_debug: bool, is_verbose_debug: bool, log_output: &str) -> Self { let is_stderr = log_output == "stderr"; - Self { is_debug, is_verbose_debug, is_stderr, is_initialized: false } + + let log_level = match (is_debug, is_verbose_debug) { + (true, true) => Level::Verbose, + (true, false) => Level::Debug, + _ => Level::Info, + }; + + Self { log_level, is_stderr, is_initialized: false } } pub fn initialize(&mut self) -> Result<(), Error> { - let level = if self.is_debug { LevelFilter::Debug } else { LevelFilter::Info }; - if self.is_stderr { - env_logger::Builder::new().filter(None, level).init(); + env_logger::Builder::new().filter(None, self.get_log_level_filter()).init(); } else { let formatter = Formatter3164 { facility: Facility::LOG_USER, @@ -66,61 +73,85 @@ impl BluetoothLogging { let logger = syslog::unix(formatter)?; let _ = log::set_boxed_logger(Box::new(BasicLogger::new(logger))) - .map(|()| log::set_max_level(level)); + .map(|()| self.apply_linux_log_level()); log_panics::init(); } // Set initial log levels and filter out tags if not verbose debug. - set_default_log_level(self.get_libbluetooth_level()); - if self.is_debug && !self.is_verbose_debug { - for tag in VERBOSE_ONLY_LOG_TAGS { - set_log_level_for_tag(tag, Level::Info); - } - } + self.apply_libbluetooth_log_level(); // Initialize the underlying system as well. self.is_initialized = true; Ok(()) } - fn get_libbluetooth_level(&self) -> Level { - if self.is_debug { - if self.is_verbose_debug { - Level::Verbose - } else { - Level::Debug - } - } else { - Level::Info + fn get_log_level_filter(&self) -> LevelFilter { + match self.is_debug_enabled() { + true => LevelFilter::Debug, + false => LevelFilter::Info, + } + } + + fn apply_linux_log_level(&self) { + log::set_max_level(self.get_log_level_filter()); + } + + fn apply_libbluetooth_log_level(&self) { + set_default_log_level(self.log_level); + // Levels for verbose-only tags. + let level = match self.log_level { + Level::Verbose => Level::Verbose, + _ => Level::Info, + }; + for tag in VERBOSE_ONLY_LOG_TAGS { + log::info!("Setting log level for tag {} to {:?}", tag, level); + set_log_level_for_tag(tag, level); } } } impl IBluetoothLogging for BluetoothLogging { fn is_debug_enabled(&self) -> bool { - self.is_initialized && self.is_debug + self.is_initialized && (self.log_level == Level::Debug || self.log_level == Level::Verbose) } fn set_debug_logging(&mut self, enabled: bool) { + if enabled { + match self.log_level { + Level::Verbose => { + self.set_log_level(Level::Verbose); + } + _ => { + self.set_log_level(Level::Debug); + } + } + } else { + self.set_log_level(Level::Info); + } + } + + fn set_log_level(&mut self, level: Level) { if !self.is_initialized { return; } - self.is_debug = enabled; + self.log_level = level; // Update log level in Linux stack. - let level = if self.is_debug { LevelFilter::Debug } else { LevelFilter::Info }; - log::set_max_level(level); + self.apply_linux_log_level(); // Update log level in libbluetooth. - let level = self.get_libbluetooth_level(); - set_default_log_level(level); + self.apply_libbluetooth_log_level(); // Mark the start of debug logging with a debug print. - if self.is_debug { + if self.is_debug_enabled() { log::debug!("Debug logging successfully enabled!"); } - log::info!("Setting debug logging to {}", self.is_debug); + log::info!("Setting log level to {:?}", level); + } + + fn get_log_level(&self) -> Level { + self.log_level } } diff --git a/system/gd/rust/topshim/src/syslog.rs b/system/gd/rust/topshim/src/syslog.rs index fd575ba4856..5af01c49489 100644 --- a/system/gd/rust/topshim/src/syslog.rs +++ b/system/gd/rust/topshim/src/syslog.rs @@ -4,12 +4,12 @@ //! to filter out logs before they go to syslog. This module provides Rust apis //! to tune log levels for syslog. -use num_derive::ToPrimitive; -use num_traits::cast::ToPrimitive; +use num_derive::{FromPrimitive, ToPrimitive}; +use num_traits::cast::{FromPrimitive, ToPrimitive}; use std::ffi::CString; use std::os::raw::c_char; -#[derive(ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, Debug, Clone, Copy, PartialEq)] #[repr(u8)] /// Android framework log priority levels. /// They are defined in system/logging/liblog/include/android/log.h by @@ -23,6 +23,24 @@ pub enum Level { Fatal = 7, } +impl From for i32 { + fn from(item: Level) -> Self { + item.to_i32().unwrap_or(4) + } +} + +impl From for u8 { + fn from(item: Level) -> Self { + item.to_u8().unwrap_or(4) + } +} + +impl Default for Level { + fn default() -> Self { + Level::Info + } +} + // Defined in syslog linkage. See |vlog_syslog.cc|. extern "C" { fn SetLogLevelForTag(tag: *const c_char, level: u8); -- GitLab From af93b43c9962fae0a56bf35a19c9fe313cc16be4 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Fri, 27 Sep 2024 08:01:45 +0000 Subject: [PATCH 069/875] CS: Fix null pointer dereference when stop_distance_measurement Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 369963781 Test: m com.android.btservice Change-Id: Id9532afe0a7beb1d59b08029b124aeb46a4e8450 --- system/gd/hci/distance_measurement_manager.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index f1709f5683a..d7bcbe477d1 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -366,7 +366,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { case METHOD_CS: { if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { log::warn("Can't find CS tracker for {}", address); - } else { + } else if (cs_trackers_[connection_handle].measurement_ongoing) { cs_trackers_[connection_handle].repeating_alarm->Cancel(); send_le_cs_procedure_enable(connection_handle, Enable::DISABLED); } -- GitLab From f20f383a8948314349ee5bd61ffc3945b321699b Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Tue, 24 Sep 2024 17:13:28 +0900 Subject: [PATCH 070/875] Print warn log when rotation happens outside expected time range Bug: 344712454 Bug: 360743527 Test: m com.android.btservices Test: Manual, checked warn log by creating error in rotation time Change-Id: Ic9e10dffb7a6d6e98990ae857a6765d300b00c49 --- system/gd/hci/le_address_manager.cc | 48 ++++++++++++++++++-- system/gd/hci/le_address_manager.h | 11 ++++- system/gd/hci/le_advertising_manager.cc | 60 +++++++++++++++++++++++-- 3 files changed, 111 insertions(+), 8 deletions(-) diff --git a/system/gd/hci/le_address_manager.cc b/system/gd/hci/le_address_manager.cc index b8ac989b83d..322b8d8220d 100644 --- a/system/gd/hci/le_address_manager.cc +++ b/system/gd/hci/le_address_manager.cc @@ -19,6 +19,8 @@ #include #include +#include + #include "hci/octets.h" #include "include/macros.h" #include "os/rand.h" @@ -78,6 +80,12 @@ LeAddressManager::~LeAddressManager() { address_rotation_non_wake_alarm_->Cancel(); address_rotation_non_wake_alarm_.reset(); } + if (address_rotation_interval_min.has_value()) { + address_rotation_interval_min.reset(); + } + if (address_rotation_interval_max.has_value()) { + address_rotation_interval_max.reset(); + } } // Called on initialization, and on IRK rotation @@ -382,7 +390,8 @@ void LeAddressManager::prepare_to_rotate() { void LeAddressManager::schedule_rotate_random_address() { if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation()) { - auto privateAddressIntervalRange = GetNextPrivateAddressIntervalRange(); + 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"); }), @@ -390,6 +399,16 @@ void LeAddressManager::schedule_rotate_random_address() { 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)), @@ -513,7 +532,8 @@ std::chrono::milliseconds LeAddressManager::GetNextPrivateAddressIntervalMs() { return minimum_rotation_time_ + random_ms; } -PrivateAddressIntervalRange LeAddressManager::GetNextPrivateAddressIntervalRange() { +PrivateAddressIntervalRange LeAddressManager::GetNextPrivateAddressIntervalRange( + const std::string& client_name) { // Get both alarms' delays as following: // - Non-wake : Random between [minimum_rotation_time_, (minimum_rotation_time_ + 2 min)] // - Wake : Random between [(maximum_rotation_time_ - 2 min), maximum_rotation_time_] @@ -534,12 +554,32 @@ PrivateAddressIntervalRange LeAddressManager::GetNextPrivateAddressIntervalRange auto min_seconds = std::chrono::duration_cast(nonwake_delay - min_minutes); auto max_minutes = std::chrono::duration_cast(wake_delay); auto max_seconds = std::chrono::duration_cast(wake_delay - max_minutes); - log::info("nonwake={}m{}s, wake={}m{}s", min_minutes.count(), min_seconds.count(), - max_minutes.count(), max_seconds.count()); + log::info("client={}, nonwake={}m{}s, wake={}m{}s", client_name, min_minutes.count(), + min_seconds.count(), max_minutes.count(), max_seconds.count()); return PrivateAddressIntervalRange{nonwake_delay, wake_delay}; } +void LeAddressManager::CheckAddressRotationHappenedInExpectedTimeInterval( + const std::chrono::time_point& interval_min, + const std::chrono::time_point& interval_max, + const std::chrono::time_point& event_time, + const std::string& client_name) { + // Give some tolerance to upper limit since alarms may ring a little bit late. + auto upper_limit_tolerance = std::chrono::seconds(5); + + if (event_time < interval_min || event_time > interval_max + upper_limit_tolerance) { + log::warn("RPA rotation happened outside expected time interval. client={}", client_name); + + auto tt_interval_min = std::chrono::system_clock::to_time_t(interval_min); + auto tt_interval_max = std::chrono::system_clock::to_time_t(interval_max); + auto tt_event_time = std::chrono::system_clock::to_time_t(event_time); + log::warn("interval_min={}", ctime(&tt_interval_min)); + log::warn("interval_max={}", ctime(&tt_interval_max)); + log::warn("event_time= {}", ctime(&tt_event_time)); + } +} + uint8_t LeAddressManager::GetFilterAcceptListSize() { return accept_list_size_; } uint8_t LeAddressManager::GetResolvingListSize() { return resolving_list_size_; } diff --git a/system/gd/hci/le_address_manager.h b/system/gd/hci/le_address_manager.h index 9d2faf64425..bee15f64c96 100644 --- a/system/gd/hci/le_address_manager.h +++ b/system/gd/hci/le_address_manager.h @@ -98,7 +98,12 @@ public: void ClearResolvingList(); void OnCommandComplete(CommandCompleteView view); std::chrono::milliseconds GetNextPrivateAddressIntervalMs(); - PrivateAddressIntervalRange GetNextPrivateAddressIntervalRange(); + PrivateAddressIntervalRange GetNextPrivateAddressIntervalRange(const std::string& client_name); + void CheckAddressRotationHappenedInExpectedTimeInterval( + const std::chrono::time_point& interval_min, + const std::chrono::time_point& interval_max, + const std::chrono::time_point& event_time, + const std::string& client_name); // Unsynchronized check for testing purposes size_t NumberCachedCommands() const { return cached_commands_.size(); } @@ -177,6 +182,10 @@ private: uint8_t resolving_list_size_; std::queue cached_commands_; bool supports_ble_privacy_{false}; + + // Only used for logging error in address rotation time. + std::optional> address_rotation_interval_min; + std::optional> address_rotation_interval_max; }; } // namespace hci diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc index 8f342922ace..9abe04f83cd 100644 --- a/system/gd/hci/le_advertising_manager.cc +++ b/system/gd/hci/le_advertising_manager.cc @@ -88,6 +88,10 @@ struct Advertiser { bool is_periodic = false; std::unique_ptr address_rotation_wake_alarm_; std::unique_ptr address_rotation_non_wake_alarm_; + + // Only used for logging error in address rotation time. + std::optional> address_rotation_interval_min; + std::optional> address_rotation_interval_max; }; /** @@ -318,6 +322,12 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Cancel(); advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_.reset(); } + if (advertising_sets_[advertiser_id].address_rotation_interval_min.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_min.reset(); + } + if (advertising_sets_[advertiser_id].address_rotation_interval_max.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_max.reset(); + } enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle; @@ -359,8 +369,9 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_ = std::make_unique(module_handler_, false); + std::string client_name = "advertising_set_" + std::to_string(advertiser_id); auto privateAddressIntervalRange = - le_address_manager_->GetNextPrivateAddressIntervalRange(); + le_address_manager_->GetNextPrivateAddressIntervalRange(client_name); advertising_sets_[advertiser_id].address_rotation_wake_alarm_->Schedule( common::BindOnce( @@ -370,6 +381,13 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb 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(module_handler_); @@ -643,8 +661,9 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_sets_[id].address_rotation_non_wake_alarm_ = std::make_unique(module_handler_, false); + std::string client_name = "advertising_set_" + std::to_string(id); auto privateAddressIntervalRange = - le_address_manager_->GetNextPrivateAddressIntervalRange(); + le_address_manager_->GetNextPrivateAddressIntervalRange(client_name); advertising_sets_[id].address_rotation_wake_alarm_->Schedule( common::BindOnce([]() { @@ -655,6 +674,13 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb 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(module_handler_); @@ -762,6 +788,12 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Cancel(); advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_.reset(); } + if (advertising_sets_[advertiser_id].address_rotation_interval_min.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_min.reset(); + } + if (advertising_sets_[advertiser_id].address_rotation_interval_max.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_max.reset(); + } return; } @@ -796,7 +828,9 @@ 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()) { - auto privateAddressIntervalRange = le_address_manager_->GetNextPrivateAddressIntervalRange(); + 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"); @@ -806,6 +840,20 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb 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, @@ -1230,6 +1278,12 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Cancel(); advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_.reset(); } + if (advertising_sets_[advertiser_id].address_rotation_interval_min.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_min.reset(); + } + if (advertising_sets_[advertiser_id].address_rotation_interval_max.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_max.reset(); + } } } -- GitLab From 1dded8e0336238fdb5c7819fbef0cf729475aac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 27 Sep 2024 08:01:21 +0000 Subject: [PATCH 071/875] gatt: Fix function name Remove _le_ from function name as it misslead about transport. Transport is provided as a parameter. Bug: 355767463 Test: mmm packages/modules/Bluetooth Flag: Exempt, mechanical refactor Change-Id: I94d87bb62225e478f2814904a19c1b7debaa4f3d --- system/stack/gatt/gatt_utils.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index 1aa1923857f..ba46c75420b 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -1848,9 +1848,8 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) { } } -static void gatt_le_disconnect_complete_notify_user(const RawAddress& bda, - tGATT_DISCONN_REASON reason, - tBT_TRANSPORT transport) { +static void gatt_disconnect_complete_notify_user(const RawAddress& bda, tGATT_DISCONN_REASON reason, + tBT_TRANSPORT transport) { tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, transport); if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) { @@ -1898,7 +1897,7 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason, gatt_disconnection_reason_text(reason), bt_transport_text(transport)); /* Notify about timeout on direct connect */ - gatt_le_disconnect_complete_notify_user(bda, reason, transport); + gatt_disconnect_complete_notify_user(bda, reason, transport); return; } @@ -1936,7 +1935,7 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason, fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL); p_tcb->sr_cmd.multi_rsp_q = NULL; - gatt_le_disconnect_complete_notify_user(bda, reason, transport); + gatt_disconnect_complete_notify_user(bda, reason, transport); *p_tcb = tGATT_TCB(); log::verbose("exit"); -- GitLab From f44c37a35eca13ce9765e0bf2e014751373b84fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 27 Sep 2024 08:04:34 +0000 Subject: [PATCH 072/875] gatt: Fix invalid EATT disconnection In following scenario, EATT channels will be incorrectly disconnected 1. Connect Dual Mode device on both transports. 2. Connect EATT over LE 3. Try to connect ATT over BR/EDR 4. Remote fails to connect ATT over BR/EDR 5. Error happens -> EATT is disconnected Note, Android supports EATT only on LE. Bug: 355767463 Flag: Exempt, obvious fix Test: mmm packages/modules/Bluetooth Change-Id: Icd0bfe4dfdc0c0b9aa2345fa2370a46df68fc951 --- system/stack/gatt/gatt_utils.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index ba46c75420b..cd2fcd12bb7 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -1903,8 +1903,10 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason, gatt_set_ch_state(p_tcb, GATT_CH_CLOSE); - /* Notify EATT about disconnection. */ - EattExtension::GetInstance()->Disconnect(p_tcb->peer_bda); + if (transport == BT_TRANSPORT_LE) { + /* Notify EATT about disconnection. */ + EattExtension::GetInstance()->Disconnect(p_tcb->peer_bda); + } for (auto clcb_it = gatt_cb.clcb_queue.begin(); clcb_it != gatt_cb.clcb_queue.end();) { if (clcb_it->p_tcb != p_tcb) { -- GitLab From 05c80f7a7799b9d48d6ce9f1c953b7b2bcc3af45 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Wed, 25 Sep 2024 22:00:41 +0000 Subject: [PATCH 073/875] Log setting phone book permission For debugging issues related to phone book access permission. Flag: EXEMPT, only log no PII. Bug: 349479600 Test: atest BluetoothInstrumentationTests Change-Id: I995e83a1e2f64f6e1ebb30478f0674816ffcb4cd --- .../com/android/bluetooth/btservice/AdapterService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 5acdcd0197e..c1f8f71f25d 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -5711,6 +5711,14 @@ public class AdapterService extends Service { } public void setPhonebookAccessPermission(BluetoothDevice device, int value) { + Log.d( + TAG, + "setPhonebookAccessPermission device=" + + ((device == null) ? "null" : device.getAnonymizedAddress()) + + ", value=" + + value + + ", callingUid=" + + Binder.getCallingUid()); setDeviceAccessFromPrefs(device, value, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE); } -- GitLab From 6c59ded78a1812cbcb08513873164cfcb14a44ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 26 Sep 2024 13:17:35 +0000 Subject: [PATCH 074/875] flag: adm_verify_active_fallback_device Bug: 369799111 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: I3cf876548355024cfc327f9640640e112cd0cc9c --- flags/active_device_manager.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/active_device_manager.aconfig b/flags/active_device_manager.aconfig index aa49c7269b6..dcbd6c154cd 100644 --- a/flags/active_device_manager.aconfig +++ b/flags/active_device_manager.aconfig @@ -19,4 +19,14 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +flag { + name: "adm_verify_active_fallback_device" + namespace: "bluetooth" + description: "Verify if device selected for fallback is different then last one" + bug: "369799111" + metadata { + purpose: PURPOSE_BUGFIX + } } \ No newline at end of file -- GitLab From 3c842c7236e96dfca0259b9a0ce752b799d45199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 27 Sep 2024 11:27:25 +0000 Subject: [PATCH 075/875] leaudio: Add support for TWS with 2 bidirectional channels Bug: 369599302 Flag: Exempt, regression tested with unit test, new test added Test: atest bluetooth_le_audio_test Change-Id: I9ba31abdaff0d6a6f94e1e663e2b5d4fc3afa1bc --- system/bta/le_audio/le_audio_types.cc | 9 ++-- system/bta/le_audio/state_machine_test.cc | 56 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/system/bta/le_audio/le_audio_types.cc b/system/bta/le_audio/le_audio_types.cc index aecdc97d6b6..f14f490916f 100644 --- a/system/bta/le_audio/le_audio_types.cc +++ b/system/bta/le_audio/le_audio_types.cc @@ -88,11 +88,12 @@ void get_cis_count(LeAudioContextType context_type, int expected_device_cnt, if (is_bidirectional) { if ((avail_group_ase_snk_cnt > 0) && (avail_group_ase_src_count) > 0) { /* Prepare CIG to enable all microphones per device */ - /* TODO: Support TWS style device with two source ASEs - two - * bidirectional CISes - */ out_cis_count_bidir = expected_device_cnt; - out_cis_count_unidir_sink = expected_device_cnt; + if (avail_group_ase_src_count > 1) { + out_cis_count_bidir++; + } else { + out_cis_count_unidir_sink = expected_device_cnt; + } } else { if (avail_group_ase_snk_cnt > 0) { out_cis_count_unidir_sink = 2 * expected_device_cnt; diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index bfa0aa507ac..ea390126acf 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -2594,6 +2594,62 @@ TEST_F(StateMachineTest, testStreamMultipleMedia_OneMemberHasNoAsesAndNotConnect ASSERT_EQ(1, get_func_call_count("alarm_cancel")); } +TEST_F(StateMachineTest, testStreamSingleConversational_TwsWithTwoBidirectional) { + const auto context_type = kContextTypeConversational; + const auto leaudio_group_id = 4; + const auto num_devices = 1; + + /* Conversational to single device which has 4 ASE Sink and 2 ASE Source and channel count 1. + * This should result with CIG configured with 2 bidirectional channels . + */ + + additional_snk_ases = 3; + additional_src_ases = 1; + + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareReceiverStartReadyHandler(group); + + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4); + EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0); + EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0); + EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0); + + InjectInitialIdleNotification(group); + + auto* leAudioDevice = group->GetFirstDevice(); + auto expected_devices_written = 0; + while (leAudioDevice) { + EXPECT_CALL(gatt_queue, + WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(4); + expected_devices_written++; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + ASSERT_EQ(expected_devices_written, num_devices); + + // Validate GroupStreamStatus + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)); + + // Start the configuration and stream Media content + ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream( + group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)})); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); +} + TEST_F(StateMachineTest, testStreamMultipleConversational) { const auto context_type = kContextTypeConversational; const auto leaudio_group_id = 4; -- GitLab From 95be15213686251aaae4a3fef38b18bffca352e8 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Sat, 14 Sep 2024 18:26:47 +0200 Subject: [PATCH 076/875] Remove key_missing_broadcast Bug: 311447399 Test: mma -j32 Change-Id: Iea8f2d0c9a4de7745ff30963d51df946f84c71cf --- .../com/android/bluetooth/btservice/RemoteDevices.java | 4 ---- flags/framework.aconfig | 8 -------- framework/api/system-current.txt | 2 +- framework/java/android/bluetooth/BluetoothDevice.java | 1 - 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index a2693764b89..c48e8b8e3c4 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -1381,10 +1381,6 @@ public class RemoteDevices { Log.i(TAG, "keyMissingCallback device: " + bluetoothDevice); if (getBondState(bluetoothDevice) == BluetoothDevice.BOND_BONDED) { - if (!Flags.keyMissingBroadcast()) { - Log.d(TAG, "flag not set - don't send key missing broadcast"); - return; - } Intent intent = new Intent(BluetoothDevice.ACTION_KEY_MISSING) .putExtra(BluetoothDevice.EXTRA_DEVICE, bluetoothDevice) diff --git a/flags/framework.aconfig b/flags/framework.aconfig index c3b4e418d3a..0535c249f25 100644 --- a/flags/framework.aconfig +++ b/flags/framework.aconfig @@ -27,14 +27,6 @@ flag { bug: "319716512" } -flag { - name: "key_missing_broadcast" - is_exported: true - namespace: "bluetooth" - description: "Broadcast when remote device it lost bond" - bug: "311447399" -} - flag { name: "identity_address_null_if_not_known" namespace: "bluetooth" diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 783635e7d45..e6aa2e938bd 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -225,7 +225,7 @@ package android.bluetooth { field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_ACCESS_CANCEL = "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL"; field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_ACCESS_REPLY = "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY"; field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_ACCESS_REQUEST = "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST"; - field @FlaggedApi("com.android.bluetooth.flags.key_missing_broadcast") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_KEY_MISSING = "android.bluetooth.device.action.KEY_MISSING"; + field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_KEY_MISSING = "android.bluetooth.device.action.KEY_MISSING"; field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PAIRING_CANCEL = "android.bluetooth.device.action.PAIRING_CANCEL"; field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED"; field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_SWITCH_BUFFER_SIZE = "android.bluetooth.device.action.SWITCH_BUFFER_SIZE"; diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 206056a92e9..23b85060dcc 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -302,7 +302,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * * @hide */ - @FlaggedApi(Flags.FLAG_KEY_MISSING_BROADCAST) @SuppressLint("ActionValue") @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) -- GitLab From 543477492bab832e87611ea530efab2ff1478629 Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Thu, 26 Sep 2024 14:33:10 +0000 Subject: [PATCH 077/875] Bumble Java Android Headtracker Test Infra Changes Bug: 368045103 Test: atest -v HidHeadTrackerTest Flag: TEST_ONLY Change-Id: I035c4a59bcfb2f5e56f34daa888bec9caead34b9 --- .../interfaces/pandora_experimental/hid.proto | 11 +++++ pandora/server/bumble_experimental/hid.py | 46 +++++++++++++------ 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/pandora/interfaces/pandora_experimental/hid.proto b/pandora/interfaces/pandora_experimental/hid.proto index 709d1577ff1..a153dc41d81 100644 --- a/pandora/interfaces/pandora_experimental/hid.proto +++ b/pandora/interfaces/pandora_experimental/hid.proto @@ -7,6 +7,8 @@ option java_outer_classname = "HidProto"; import "google/protobuf/empty.proto"; service HID { + // Register service + rpc RegisterService(ServiceRequest) returns (google.protobuf.Empty); // Connect HID Host rpc ConnectHost(google.protobuf.Empty) returns (google.protobuf.Empty); // Disconnect HID Host @@ -39,6 +41,15 @@ enum HidReportId { HID_INVALID_RPT_ID = 3; } +enum HidServiceType { + SERVICE_TYPE_HID = 0; + SERVICE_TYPE_HOGP = 1; + SERVICE_TYPE_BOTH = 2; +} + +message ServiceRequest { + HidServiceType service_type = 1; +} message SendHostReportRequest { bytes address = 1; HidReportType report_type = 2; diff --git a/pandora/server/bumble_experimental/hid.py b/pandora/server/bumble_experimental/hid.py index 0b2f6867e26..c209e933ee2 100644 --- a/pandora/server/bumble_experimental/hid.py +++ b/pandora/server/bumble_experimental/hid.py @@ -18,6 +18,8 @@ from pandora_experimental.hid_pb2 import ( PROTOCOL_REPORT_MODE, PROTOCOL_BOOT_MODE, PROTOCOL_UNSUPPORTED_MODE, + SERVICE_TYPE_HID, + SERVICE_TYPE_HOGP, ) from bumble.core import ( @@ -702,29 +704,45 @@ def on_virtual_cable_unplug_cb(): hid_protoMode_queue = None +hid_device = None + + +def register_hid(self) -> None: + self.device.sdp_service_records.update(sdp_records()) + global hid_device + hid_device = HID_Device(self.device) + # Register for call backs + hid_device.register_get_report_cb(on_get_report_cb) + hid_device.register_set_report_cb(on_set_report_cb) + hid_device.register_get_protocol_cb(on_get_protocol_cb) + hid_device.register_set_protocol_cb(on_set_protocol_cb) + # Register for virtual cable unplug call back + hid_device.on('virtual_cable_unplug', on_virtual_cable_unplug_cb) # This class implements the Hid Pandora interface. class HIDService(HIDServicer): - hid_device = None - def __init__(self, device: Device) -> None: super().__init__() self.device = device - self.device.sdp_service_records.update(sdp_records()) self.event_queue: Optional[asyncio.Queue[ProtocolModeEvent]] = None - hogp_device(self.device) - logging.info(f'Hid device register: ') - global hid_device - hid_device = HID_Device(self.device) - # Register for call backs - hid_device.register_get_report_cb(on_get_report_cb) - hid_device.register_set_report_cb(on_set_report_cb) - hid_device.register_get_protocol_cb(on_get_protocol_cb) - hid_device.register_set_protocol_cb(on_set_protocol_cb) - # Register for virtual cable unplug call back - hid_device.on('virtual_cable_unplug', on_virtual_cable_unplug_cb) + + @utils.rpc + async def RegisterService(self, request: empty_pb2.Empty, context: grpc.ServicerContext) -> empty_pb2.Empty: + + if request.service_type == SERVICE_TYPE_HID: + logging.info(f'Registering HID') + register_hid(self) + elif request.service_type == SERVICE_TYPE_HOGP: + logging.info(f'Registering HOGP') + hogp_device(self.device) + else: + logging.info(f'Registering both HID and HOGP') + register_hid(self) + hogp_device(self.device) + + return empty_pb2.Empty() @utils.rpc async def ConnectHost(self, request: empty_pb2.Empty, context: grpc.ServicerContext) -> empty_pb2.Empty: -- GitLab From 6cf15457e12155070b7a996598ec93cf2340c368 Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Fri, 27 Sep 2024 13:28:14 +0000 Subject: [PATCH 078/875] Modified HidHostTest as per new hid rpc call Introduced new RPC call to support run time HID and HOGP service configuration. Modified the HidHostTest accordingly Bug: 368045103 Test: atest -v HidHostTest Change-Id: I44002eea46e91e1c0fee9985ed5d7e9fc9ba6009 --- .../tests/bumble/src/android/bluetooth/hid/HidHostTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java index 4e11e4d4af8..835480b7b2f 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java @@ -44,8 +44,10 @@ import org.junit.Test; import org.junit.runner.RunWith; import pandora.HIDGrpc; +import pandora.HidProto.HidServiceType; import pandora.HidProto.ProtocolModeEvent; import pandora.HidProto.ReportEvent; +import pandora.HidProto.ServiceRequest; import java.time.Duration; import java.util.Iterator; @@ -233,6 +235,10 @@ public class HidHostTest { mAdapter.getProfileProxy( mContext, mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); mHidBlockingStub = mBumble.hidBlocking(); + mHidBlockingStub.registerService( + ServiceRequest.newBuilder() + .setServiceType(HidServiceType.SERVICE_TYPE_HID) + .build()); mFutureConnectionIntent = SettableFuture.create(); mDevice = mBumble.getRemoteDevice(); -- GitLab From e6f0bbeb1e967f00b7ea97ba420c05d1eb972f3e Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Fri, 27 Sep 2024 13:46:43 +0000 Subject: [PATCH 079/875] Modified HidHostDualModeTest as per new hid rpc call Introduced new RPC call to support run time HID and HOGP service configuration. Modified the HidHostDualModeTest accordingly Bug: 368045103 Test: atest -v HidHostDualModeTest Change-Id: Id980c8cc86be2d0529ca690d4062f5170459fc2e --- .../src/android/bluetooth/hid/HidHostDualModeTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java index 778fc239e07..bcc2cac8b3c 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java @@ -83,6 +83,9 @@ import org.mockito.MockitoAnnotations; import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.stubbing.Answer; +import pandora.HIDGrpc; +import pandora.HidProto.HidServiceType; +import pandora.HidProto.ServiceRequest; import pandora.HostProto.AdvertiseRequest; import pandora.HostProto.OwnAddressType; @@ -106,6 +109,7 @@ public class HidHostDualModeTest { InstrumentationRegistry.getInstrumentation().getTargetContext(); private final BluetoothAdapter mAdapter = mContext.getSystemService(BluetoothManager.class).getAdapter(); + private HIDGrpc.HIDBlockingStub mHidBlockingStub; @Rule(order = 0) public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -272,6 +276,11 @@ public class HidHostDualModeTest { mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.HEADSET); BluetoothHeadset hfpService = (BluetoothHeadset) verifyProfileServiceConnected(BluetoothProfile.HEADSET); + mHidBlockingStub = mBumble.hidBlocking(); + mHidBlockingStub.registerService( + ServiceRequest.newBuilder() + .setServiceType(HidServiceType.SERVICE_TYPE_BOTH) + .build()); AdvertiseRequest request = AdvertiseRequest.newBuilder() -- GitLab From c75eee956132cb15dcf3bc94f2a7846ddff032ce Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Fri, 27 Sep 2024 13:53:35 +0000 Subject: [PATCH 080/875] Modified LeAudioServiceDiscoveryTest Introduced new RPC call to support run time HID and HOGP service configuration. Modified the LeAudioServiceDiscoveryTest accordingly Bug: 368045103 Test: atest -v LeAudioServiceDiscoveryTest Change-Id: I40beb6e2cc798fe3f2eb832b0c4e21909a633dd8 --- .../service_discovery/LeAudioServiceDiscoveryTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java index 27b0f106e45..541ea815ff4 100644 --- a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java +++ b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java @@ -269,13 +269,11 @@ public class LeAudioServiceDiscoveryTest { BluetoothDevice.EXTRA_UUID, Matchers.allOf( Matchers.hasItemInArray(BluetoothUuid.HFP), - Matchers.hasItemInArray(BluetoothUuid.HID), Matchers.hasItemInArray(BluetoothUuid.A2DP_SOURCE), Matchers.hasItemInArray(BluetoothUuid.A2DP_SINK), Matchers.hasItemInArray(BluetoothUuid.AVRCP), Matchers.hasItemInArray(BluetoothUuid.LE_AUDIO), - Matchers.hasItemInArray(BluetoothUuid.BATTERY), - Matchers.hasItemInArray(BluetoothUuid.HOGP)))); + Matchers.hasItemInArray(BluetoothUuid.BATTERY)))); unregisterIntentActions( BluetoothDevice.ACTION_UUID, BluetoothDevice.ACTION_ACL_CONNECTED, -- GitLab From ff4b0d6de40e4b40e52c2f07416a45e74cc205bd Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Fri, 27 Sep 2024 17:17:04 +0000 Subject: [PATCH 081/875] Remove reset_after_collision flag The change is in nextfood and rolled out to public, so remove the flag Bug: 325084426 Bug: 332324315 Change-Id: I94ed93b6e7e05ef810e8e25a4770c1535af54338 Flag: com::android::bluetooth::flags::reset_after_collision Test: atest net_test_bta --- flags/hfp.aconfig | 10 ---------- system/bta/ag/bta_ag_act.cc | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/flags/hfp.aconfig b/flags/hfp.aconfig index b5e1908e16e..a27c7806800 100644 --- a/flags/hfp.aconfig +++ b/flags/hfp.aconfig @@ -39,16 +39,6 @@ flag { } } -flag { - name: "reset_after_collision" - namespace: "bluetooth" - description: "Reset p_scb when collision occurred and rfcomm is not opened yet" - bug: "332324315" - metadata { - purpose: PURPOSE_BUGFIX - } -} - flag { name: "sink_audio_policy_handover" namespace: "bluetooth" diff --git a/system/bta/ag/bta_ag_act.cc b/system/bta/ag/bta_ag_act.cc index 6e58a756bfd..716ca771863 100644 --- a/system/bta/ag/bta_ag_act.cc +++ b/system/bta/ag/bta_ag_act.cc @@ -594,7 +594,7 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { log::warn("RFCOMM_RemoveConnection failed for {}, handle {}, error {}", dev_addr, ag_scb.conn_handle, status); } - } else if (com::android::bluetooth::flags::reset_after_collision()) { + } else { // As no existing outgoing rfcomm connection, then manual reset current // state, and use the incoming one bta_ag_rfc_fail(&ag_scb, tBTA_AG_DATA::kEmpty); -- GitLab From 7613d0c38945dac318def1372ecf2dc725513d8d Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Thu, 26 Sep 2024 21:32:47 +0000 Subject: [PATCH 082/875] Send preferred MTU from GattService to native GATT module Adding infrastructure to allow GattService to send application preferred ATT MTU to the native GATT module. Bug: 369329192 Test: mmm packages/modules/Bluetooth Flag: EXEMPT manual refactor Change-Id: Icdb3eecca5adb18bbac12d2883b37ea4432e32b3 --- android/app/jni/com_android_bluetooth_gatt.cpp | 7 ++++--- .../bluetooth/gatt/GattNativeInterface.java | 15 ++++++++++++--- .../com/android/bluetooth/gatt/GattService.java | 4 +++- .../android/bluetooth/gatt/GattServiceTest.java | 2 +- system/bta/dm/bta_dm_disc.cc | 12 +++++++----- system/bta/dm/bta_dm_gatt_client.cc | 5 +++-- system/bta/dm/bta_dm_gatt_client.h | 3 ++- system/bta/gatt/bta_gattc_act.cc | 6 +++--- system/bta/gatt/bta_gattc_api.cc | 10 +++++++++- system/bta/gatt/bta_gattc_int.h | 1 + system/bta/include/bta_gatt_api.h | 3 +++ system/bta/test/common/bta_gatt_api_mock.cc | 8 -------- system/btif/src/btif_gatt_client.cc | 10 ++++++---- system/gd/rust/linux/stack/src/bluetooth_gatt.rs | 1 + system/gd/rust/topshim/facade/src/gatt_service.rs | 2 +- system/gd/rust/topshim/src/profiles/gatt.rs | 4 +++- system/include/hardware/bt_gatt_client.h | 3 ++- system/stack/gatt/gatt_api.cc | 14 +++++++++++--- system/stack/gatt/gatt_cl.cc | 1 + system/stack/include/gatt_api.h | 5 ++++- system/test/mock/mock_bta_gattc_api.cc | 6 ++++++ system/test/mock/mock_stack_gatt_api.cc | 7 ++++--- system/test/mock/mock_stack_gatt_api.h | 14 ++++++++------ 23 files changed, 95 insertions(+), 48 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index e164923de84..fe17a63b8be 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -1387,13 +1387,14 @@ static void gattClientScanNative(JNIEnv* /* env */, jobject /* object */, jboole static void gattClientConnectNative(JNIEnv* env, jobject /* object */, jint clientif, jstring address, jint addressType, jboolean isDirect, - jint transport, jboolean opportunistic, jint initiating_phys) { + jint transport, jboolean opportunistic, jint initiating_phys, + jint preferred_mtu) { if (!sGattIf) { return; } sGattIf->client->connect(clientif, str2addr(env, address), addressType, isDirect, transport, - opportunistic, initiating_phys); + opportunistic, initiating_phys, preferred_mtu); } static void gattClientDisconnectNative(JNIEnv* env, jobject /* object */, jint clientIf, @@ -2842,7 +2843,7 @@ static int register_com_android_bluetooth_gatt_(JNIEnv* env) { (void*)gattClientGetDeviceTypeNative}, {"gattClientRegisterAppNative", "(JJZ)V", (void*)gattClientRegisterAppNative}, {"gattClientUnregisterAppNative", "(I)V", (void*)gattClientUnregisterAppNative}, - {"gattClientConnectNative", "(ILjava/lang/String;IZIZI)V", + {"gattClientConnectNative", "(ILjava/lang/String;IZIZII)V", (void*)gattClientConnectNative}, {"gattClientDisconnectNative", "(ILjava/lang/String;I)V", (void*)gattClientDisconnectNative}, diff --git a/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java b/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java index c0a2ca18ef4..5adbbf2b936 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java +++ b/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java @@ -293,7 +293,8 @@ public class GattNativeInterface { boolean isDirect, int transport, boolean opportunistic, - int initiatingPhys); + int initiatingPhys, + int preferredMtu); private native void gattClientDisconnectNative(int clientIf, String address, int connId); @@ -447,9 +448,17 @@ public class GattNativeInterface { boolean isDirect, int transport, boolean opportunistic, - int initiatingPhys) { + int initiatingPhys, + int preferredMtu) { gattClientConnectNative( - clientIf, address, addressType, isDirect, transport, opportunistic, initiatingPhys); + clientIf, + address, + addressType, + isDirect, + transport, + opportunistic, + initiatingPhys, + preferredMtu); } /** Disconnect from the remote Gatt server */ diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index b886b8f4d64..a6e4733150d 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -2152,8 +2152,10 @@ public class GattService extends ProfileService { clientIf, BluetoothProtoEnums.CONNECTION_STATE_CONNECTING, -1); + + int preferredMtu = 0; mNativeInterface.gattClientConnect( - clientIf, address, addressType, isDirect, transport, opportunistic, phy); + clientIf, address, addressType, isDirect, transport, opportunistic, phy, preferredMtu); } @RequiresPermission(BLUETOOTH_CONNECT) 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 b71c71d52f7..da45445ac2e 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 @@ -265,7 +265,7 @@ public class GattServiceTest { verify(mNativeInterface) .gattClientConnect( - clientIf, address, addressType, isDirect, transport, opportunistic, phy); + clientIf, address, addressType, isDirect, transport, opportunistic, phy, 0); } @Test diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc index 441a938a310..980f2d45f2d 100644 --- a/system/bta/dm/bta_dm_disc.cc +++ b/system/bta/dm/bta_dm_disc.cc @@ -111,7 +111,8 @@ struct gatt_interface_t { void (*BTA_GATTC_Close)(tCONN_ID conn_id); void (*BTA_GATTC_ServiceSearchRequest)(tCONN_ID conn_id, const bluetooth::Uuid* p_srvc_uuid); void (*BTA_GATTC_Open)(tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, bool opportunistic); + tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, + uint16_t preferred_mtu); } default_gatt_interface = { .BTA_GATTC_CancelOpen = [](tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct) { @@ -138,8 +139,9 @@ struct gatt_interface_t { }, .BTA_GATTC_Open = [](tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) { - BTA_GATTC_Open(client_if, remote_bda, connection_type, opportunistic); + tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, uint16_t preferred_mtu) { + BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type, + BT_TRANSPORT_LE, opportunistic, 1, preferred_mtu); }, }; @@ -605,14 +607,14 @@ static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr) { "transport:{} opportunistic:{:c}", bd_addr, bt_transport_text(BT_TRANSPORT_LE), (kUseOpportunistic) ? 'T' : 'F'); get_gatt_interface().BTA_GATTC_Open(bta_dm_discovery_cb.client_if, bd_addr, - BTM_BLE_DIRECT_CONNECTION, kUseOpportunistic); + BTM_BLE_DIRECT_CONNECTION, kUseOpportunistic, 0); } else { log::debug( "Opening new gatt client connection for discovery peer:{} " "transport:{} opportunistic:{:c}", bd_addr, bt_transport_text(BT_TRANSPORT_LE), (!kUseOpportunistic) ? 'T' : 'F'); get_gatt_interface().BTA_GATTC_Open(bta_dm_discovery_cb.client_if, bd_addr, - BTM_BLE_DIRECT_CONNECTION, !kUseOpportunistic); + BTM_BLE_DIRECT_CONNECTION, !kUseOpportunistic, 0); } } } diff --git a/system/bta/dm/bta_dm_gatt_client.cc b/system/bta/dm/bta_dm_gatt_client.cc index c9d7ba8e115..c9fec2d392d 100644 --- a/system/bta/dm/bta_dm_gatt_client.cc +++ b/system/bta/dm/bta_dm_gatt_client.cc @@ -98,12 +98,13 @@ gatt_interface_t default_gatt_interface = { }, .BTA_GATTC_Open = [](tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) { + tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, uint16_t preferred_mtu) { gatt_history_.Push(base::StringPrintf( "%-32s bd_addr:%s client_if:%hu type:0x%x opportunistic:%c", "GATTC_Open", ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, connection_type, (opportunistic) ? 'T' : 'F')); - BTA_GATTC_Open(client_if, remote_bda, connection_type, opportunistic); + BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type, + BT_TRANSPORT_LE, opportunistic, 1, preferred_mtu); }, }; diff --git a/system/bta/dm/bta_dm_gatt_client.h b/system/bta/dm/bta_dm_gatt_client.h index b0071fd0003..7f5540af7d3 100644 --- a/system/bta/dm/bta_dm_gatt_client.h +++ b/system/bta/dm/bta_dm_gatt_client.h @@ -37,7 +37,8 @@ struct gatt_interface_t { void (*BTA_GATTC_Close)(tCONN_ID conn_id); void (*BTA_GATTC_ServiceSearchRequest)(tCONN_ID conn_id, const bluetooth::Uuid* p_srvc_uuid); void (*BTA_GATTC_Open)(tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, bool opportunistic); + tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, + uint16_t preferred_mtu); }; // diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index bdcec86c9f4..3437f15266b 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -449,7 +449,7 @@ void bta_gattc_open(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, p_data->api_conn.remote_addr_type, BTM_BLE_DIRECT_CONNECTION, p_data->api_conn.transport, p_data->api_conn.opportunistic, - p_data->api_conn.initiating_phys)) { + p_data->api_conn.initiating_phys, p_data->api_conn.preferred_mtu)) { log::error("Connection open failure"); bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_OPEN_FAIL_EVT, p_data); return; @@ -484,8 +484,8 @@ static void bta_gattc_init_bk_conn(const tBTA_GATTC_API_OPEN* p_data, tBTA_GATTC } /* always call open to hold a connection */ - if (!GATT_Connect(p_data->client_if, p_data->remote_bda, p_data->connection_type, - p_data->transport, false)) { + if (!GATT_Connect(p_data->client_if, p_data->remote_bda, BLE_ADDR_PUBLIC, p_data->connection_type, + p_data->transport, false, 1, p_data->preferred_mtu)) { log::error("Unable to connect to remote bd_addr={}", p_data->remote_bda); bta_gattc_send_open_cback(p_clreg, GATT_ILLEGAL_PARAMETER, p_data->remote_bda, GATT_INVALID_CONN_ID, BT_TRANSPORT_LE, 0); diff --git a/system/bta/gatt/bta_gattc_api.cc b/system/bta/gatt/bta_gattc_api.cc index 2e41b2e23f7..206cc943644 100644 --- a/system/bta/gatt/bta_gattc_api.cc +++ b/system/bta/gatt/bta_gattc_api.cc @@ -142,7 +142,7 @@ void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys) { + uint8_t initiating_phys, uint16_t preferred_mtu) { tBTA_GATTC_DATA data = { .api_conn = { @@ -157,12 +157,20 @@ void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_ .initiating_phys = initiating_phys, .opportunistic = opportunistic, .remote_addr_type = addr_type, + .preferred_mtu = preferred_mtu, }, }; post_on_bt_main([data]() { bta_gattc_process_api_open(&data); }); } +void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, + tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, + uint8_t initiating_phys) { + BTA_GATTC_Open(client_if, remote_bda, addr_type, connection_type, transport, opportunistic, + initiating_phys, 0); +} + void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys) { diff --git a/system/bta/gatt/bta_gattc_int.h b/system/bta/gatt/bta_gattc_int.h index c0cfc580e57..070e9c574b0 100644 --- a/system/bta/gatt/bta_gattc_int.h +++ b/system/bta/gatt/bta_gattc_int.h @@ -110,6 +110,7 @@ typedef struct { uint8_t initiating_phys; bool opportunistic; tBT_DEVICE_TYPE remote_addr_type; + uint16_t preferred_mtu; } tBTA_GATTC_API_OPEN; typedef struct { diff --git a/system/bta/include/bta_gatt_api.h b/system/bta/include/bta_gatt_api.h index 0b55aa20744..1079e813ad9 100644 --- a/system/bta/include/bta_gatt_api.h +++ b/system/bta/include/bta_gatt_api.h @@ -505,6 +505,9 @@ void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys); +void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, + tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, + uint8_t initiating_phys, uint16_t preferred_mtu); /******************************************************************************* * diff --git a/system/bta/test/common/bta_gatt_api_mock.cc b/system/bta/test/common/bta_gatt_api_mock.cc index d84d365d3fb..e3ac011cd6f 100644 --- a/system/bta/test/common/bta_gatt_api_mock.cc +++ b/system/bta/test/common/bta_gatt_api_mock.cc @@ -41,14 +41,6 @@ void BTA_GATTC_AppDeregister(tGATT_IF client_if) { gatt_interface->AppDeregister(client_if); } -void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys) { - log::assert_that(gatt_interface != nullptr, "Mock GATT interface not set!"); - gatt_interface->Open(client_if, remote_bda, connection_type, transport, opportunistic, - initiating_phys); -} - void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) { log::assert_that(gatt_interface != nullptr, "Mock GATT interface not set!"); diff --git a/system/btif/src/btif_gatt_client.cc b/system/btif/src/btif_gatt_client.cc index bed322206b3..717e3574bca 100644 --- a/system/btif/src/btif_gatt_client.cc +++ b/system/btif/src/btif_gatt_client.cc @@ -300,7 +300,7 @@ static bt_status_t btif_gattc_unregister_app(int client_if) { void btif_gattc_open_impl(int client_if, RawAddress address, tBLE_ADDR_TYPE addr_type, bool is_direct, tBT_TRANSPORT transport, bool opportunistic, - int initiating_phys) { + int initiating_phys, int preferred_mtu) { int device_type = BT_DEVICE_TYPE_UNKNOWN; if (addr_type == BLE_ADDR_RANDOM) { @@ -358,16 +358,18 @@ void btif_gattc_open_impl(int client_if, RawAddress address, tBLE_ADDR_TYPE addr bt_transport_text(transport), DeviceTypeText(device_type), address, addr_type, initiating_phys); tBTM_BLE_CONN_TYPE type = is_direct ? BTM_BLE_DIRECT_CONNECTION : BTM_BLE_BKG_CONNECT_ALLOW_LIST; - BTA_GATTC_Open(client_if, address, addr_type, type, transport, opportunistic, initiating_phys); + BTA_GATTC_Open(client_if, address, addr_type, type, transport, opportunistic, initiating_phys, + preferred_mtu); } static bt_status_t btif_gattc_open(int client_if, const RawAddress& bd_addr, uint8_t addr_type, bool is_direct, int transport, bool opportunistic, - int initiating_phys) { + int initiating_phys, int preferred_mtu) { CHECK_BTGATT_INIT(); // Closure will own this value and free it. return do_in_jni_thread(Bind(&btif_gattc_open_impl, client_if, bd_addr, addr_type, is_direct, - to_bt_transport(transport), opportunistic, initiating_phys)); + to_bt_transport(transport), opportunistic, initiating_phys, + preferred_mtu)); } void btif_gattc_close_impl(int client_if, RawAddress address, int conn_id) { diff --git a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs index 393b18727ee..6c56ce6d9d2 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs @@ -2272,6 +2272,7 @@ impl IBluetoothGatt for BluetoothGatt { transport.into(), opportunistic, phy.into(), + 0, ); } diff --git a/system/gd/rust/topshim/facade/src/gatt_service.rs b/system/gd/rust/topshim/facade/src/gatt_service.rs index 1653f69ff5e..2baa3f1e743 100644 --- a/system/gd/rust/topshim/facade/src/gatt_service.rs +++ b/system/gd/rust/topshim/facade/src/gatt_service.rs @@ -479,7 +479,7 @@ impl GattService for GattServiceImpl { fn client_connect(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink) { let client = &mut self.gatt.lock().unwrap().client; - client.connect(0, &self.create_raw_address(), 0, true, 0, true, 0); + client.connect(0, &self.create_raw_address(), 0, true, 0, true, 0, 0); ctx.spawn(async move { sink.success(Empty::default()).await.unwrap(); }) diff --git a/system/gd/rust/topshim/src/profiles/gatt.rs b/system/gd/rust/topshim/src/profiles/gatt.rs index 72a5faa90db..a6884310b6c 100644 --- a/system/gd/rust/topshim/src/profiles/gatt.rs +++ b/system/gd/rust/topshim/src/profiles/gatt.rs @@ -1181,6 +1181,7 @@ impl GattClient { transport: i32, opportunistic: bool, initiating_phys: i32, + preferred_mtu: i32, ) -> BtStatus { BtStatus::from(ccall!( self, @@ -1191,7 +1192,8 @@ impl GattClient { is_direct, transport, opportunistic, - initiating_phys + initiating_phys, + preferred_mtu )) } diff --git a/system/include/hardware/bt_gatt_client.h b/system/include/hardware/bt_gatt_client.h index 200c00a36ba..f6c4daeca86 100644 --- a/system/include/hardware/bt_gatt_client.h +++ b/system/include/hardware/bt_gatt_client.h @@ -210,7 +210,8 @@ typedef struct { /** Create a connection to a remote LE or dual-mode device */ bt_status_t (*connect)(int client_if, const RawAddress& bd_addr, uint8_t addr_type, - bool is_direct, int transport, bool opportunistic, int initiating_phys); + bool is_direct, int transport, bool opportunistic, int initiating_phys, + int preferred_mtu); /** Disconnect a remote device or cancel a pending connection */ bt_status_t (*disconnect)(int client_if, const RawAddress& bd_addr, int conn_id); diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index 3715292f89e..aa143ee4312 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -1457,7 +1457,7 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYP bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys) { + uint8_t initiating_phys, uint16_t /* preferred_mtu */) { /* Make sure app is registered */ tGATT_REG* p_reg = gatt_get_regcb(gatt_if); if (!p_reg) { @@ -1551,13 +1551,21 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE ad tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic) { constexpr uint8_t kPhyLe1M = 0x01; // From the old controller shim. uint8_t phy = kPhyLe1M; - return GATT_Connect(gatt_if, bd_addr, addr_type, connection_type, transport, opportunistic, phy); + return GATT_Connect(gatt_if, bd_addr, addr_type, connection_type, transport, opportunistic, phy, + 0); } bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys) { return GATT_Connect(gatt_if, bd_addr, BLE_ADDR_PUBLIC, connection_type, transport, opportunistic, - initiating_phys); + initiating_phys, 0); +} + +bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYPE connection_type, + tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys, + uint16_t preferred_mtu) { + return GATT_Connect(gatt_if, bd_addr, BLE_ADDR_PUBLIC, connection_type, transport, opportunistic, + initiating_phys, preferred_mtu); } /******************************************************************************* diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc index 28ee7fb4a34..7501468aa3e 100644 --- a/system/stack/gatt/gatt_cl.cc +++ b/system/stack/gatt/gatt_cl.cc @@ -36,6 +36,7 @@ #include "stack/eatt/eatt.h" #include "stack/include/bt_types.h" #include "stack/include/btm_client_interface.h" +#include "stack/include/l2cdefs.h" #include "types/bluetooth/uuid.h" #define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */ diff --git a/system/stack/include/gatt_api.h b/system/stack/include/gatt_api.h index abda34aa156..911df290231 100644 --- a/system/stack/include/gatt_api.h +++ b/system/stack/include/gatt_api.h @@ -1178,7 +1178,10 @@ void GATT_StartIf(tGATT_IF gatt_if); tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys); - +[[nodiscard]] bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, + tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, + tBT_TRANSPORT transport, bool opportunistic, + uint8_t initiating_phys, uint16_t preferred_transport); /******************************************************************************* * * Function GATT_CancelConnect diff --git a/system/test/mock/mock_bta_gattc_api.cc b/system/test/mock/mock_bta_gattc_api.cc index 1649ce8980c..686868455cd 100644 --- a/system/test/mock/mock_bta_gattc_api.cc +++ b/system/test/mock/mock_bta_gattc_api.cc @@ -112,6 +112,12 @@ void BTA_GATTC_Open(tGATT_IF /* client_if */, const RawAddress& /* remote_bda */ uint8_t /* initiating_phys */) { inc_func_call_count(__func__); } +void BTA_GATTC_Open(tGATT_IF /* client_if */, const RawAddress& /* remote_bda */, + tBLE_ADDR_TYPE /* addr_type */, tBTM_BLE_CONN_TYPE /* connection_type */, + tBT_TRANSPORT /* transport */, bool /* opportunistic */, + uint8_t /* initiating_phys */, uint16_t /* preferred_mtu */) { + inc_func_call_count(__func__); +} void BTA_GATTC_PrepareWrite(uint16_t /* conn_id */, uint16_t /* handle */, uint16_t /* offset */, std::vector /* value */, tGATT_AUTH_REQ /* auth_req */, GATT_WRITE_OP_CB /* callback */, void* /* cb_data */) { diff --git a/system/test/mock/mock_stack_gatt_api.cc b/system/test/mock/mock_stack_gatt_api.cc index 947cc1a7288..88b7af29a0f 100644 --- a/system/test/mock/mock_stack_gatt_api.cc +++ b/system/test/mock/mock_stack_gatt_api.cc @@ -190,10 +190,11 @@ bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_dir } bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys) { + uint8_t initiating_phys, uint16_t preferred_mtu) { inc_func_call_count(__func__); return test::mock::stack_gatt_api::GATT_Connect(gatt_if, bd_addr, addr_type, connection_type, - transport, opportunistic, initiating_phys); + transport, opportunistic, initiating_phys, + preferred_mtu); } void GATT_Deregister(tGATT_IF gatt_if) { inc_func_call_count(__func__); @@ -243,7 +244,7 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYP tBT_TRANSPORT transport, bool opportunistic) { inc_func_call_count(__func__); return test::mock::stack_gatt_api::GATT_Connect(gatt_if, bd_addr, 0, connection_type, transport, - opportunistic, 0); + opportunistic, 0, 0); } // END mockcify generation diff --git a/system/test/mock/mock_stack_gatt_api.h b/system/test/mock/mock_stack_gatt_api.h index 8e1b4e5d991..74bf566f2f0 100644 --- a/system/test/mock/mock_stack_gatt_api.h +++ b/system/test/mock/mock_stack_gatt_api.h @@ -284,21 +284,23 @@ extern struct GATT_CancelConnect GATT_CancelConnect; // Name: GATT_Connect // Params: tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct, -// tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys Return: -// bool +// tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys, uint16_t preferred_mtu +// Return: bool struct GATT_Connect { static bool return_value; std::function + uint8_t initiating_phys, uint16_t preferred_mtu)> body{[](tGATT_IF /* gatt_if */, const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */, bool /* is_direct */, tBT_TRANSPORT /* transport */, bool /* opportunistic */, - uint8_t /* initiating_phys */) { return return_value; }}; + uint8_t /* initiating_phys */, + uint16_t /* preferred_mtu */) { return return_value; }}; bool operator()(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, bool is_direct, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys) { - return body(gatt_if, bd_addr, addr_type, is_direct, transport, opportunistic, initiating_phys); + uint8_t initiating_phys, uint16_t preferred_mtu) { + return body(gatt_if, bd_addr, addr_type, is_direct, transport, opportunistic, initiating_phys, + preferred_mtu); } }; extern struct GATT_Connect GATT_Connect; -- GitLab From e5e338afe3b944f0075de9c23469f3dc9c0e243c Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Fri, 27 Sep 2024 18:30:14 +0000 Subject: [PATCH 083/875] Encrypt LE link immediately on reconnection LE link must be encrypted immediately on connection if device are already bonded. This is a backport of ag/29056565, but the code needs to go in a different location because that patch relies on recent feature work. Ignore-AOSP-First: security Test: mmm packages/modules/Bluetooth Bug: 288144143 Merged-In: I607af8214f4fd9c3905f2e053ba136cd6189361f Change-Id: I8bd0ef5ae1750096fe72feb334022b9895f3b26e --- system/stack/acl/btm_acl.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 75e3fcda89b..33515d6cedf 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -1140,6 +1140,17 @@ void StackAclBtmAcl::btm_establish_continue(tACL_CONN* p_acl) { ADDRESS_TO_LOGGABLE_CSTR(p_acl->RemoteAddress())); } btm_set_link_policy(p_acl, btm_cb.acl_cb_.DefaultLinkPolicy()); + } else if (p_acl->is_transport_ble()) { + tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_acl->remote_addr); + + if (p_dev_rec == nullptr) { + LOG_WARN("No security record for %s", + ADDRESS_TO_LOGGABLE_CSTR(p_acl->RemoteAddress())); + } else if (p_dev_rec->is_le_link_key_known()) { + btm_ble_set_encryption( + p_acl->remote_addr, BTM_BLE_SEC_ENCRYPT, + p_dev_rec->role_central ? HCI_ROLE_CENTRAL : HCI_ROLE_PERIPHERAL); + } } NotifyAclLinkUp(*p_acl); } -- GitLab From 92f3a12b0b863b0c3d68ab4a715100756955002e Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Wed, 4 Sep 2024 21:54:22 +0000 Subject: [PATCH 084/875] Encrypt LE link immediately on reconnection LE link must be encrypted immediately on connection if device are already bonded. This is a backport of ag/29056565, but the code needs to go in a different location because that patch relies on recent feature work. Ignore-AOSP-First: security Test: mmm packages/modules/Bluetooth Bug: 288144143 Merged-In: I607af8214f4fd9c3905f2e053ba136cd6189361f Merged-In: I8bd0ef5ae1750096fe72feb334022b9895f3b26e Change-Id: I7147c837ecab6c67943fc6fd78a9949f3381df62 --- system/stack/acl/btm_acl.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 11f93a05298..8a2741ec4ec 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -1079,6 +1079,17 @@ void StackAclBtmAcl::btm_establish_continue(tACL_CONN* p_acl) { PRIVATE_ADDRESS(p_acl->RemoteAddress())); } btm_set_link_policy(p_acl, btm_cb.acl_cb_.DefaultLinkPolicy()); + } else if (p_acl->is_transport_ble()) { + tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_acl->remote_addr); + + if (p_dev_rec == nullptr) { + LOG_WARN("No security record for %s", + PRIVATE_ADDRESS(p_acl->RemoteAddress())); + } else if (p_dev_rec->is_le_link_key_known()) { + btm_ble_set_encryption( + p_acl->remote_addr, BTM_BLE_SEC_ENCRYPT, + p_dev_rec->role_central ? HCI_ROLE_CENTRAL : HCI_ROLE_PERIPHERAL); + } } NotifyAclLinkUp(*p_acl); } -- GitLab From e6c62c59bd3633ba650346945d91730aa17d88e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 27 Sep 2024 19:49:13 +0000 Subject: [PATCH 085/875] csis: Fix possible assert On stack closure it might happen that some other module can try to get CsisClient instance and it is perfectly fine when nullptr is returned. Bug: 369559149 Test: atest bluetooth_csis_test Flag: Exempt, trivial fix Change-Id: Ie7af284298a8f117c16c51dd87763b9db6ec8579 --- system/bta/csis/csis_client.cc | 4 +++- system/bta/csis/csis_client_test.cc | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/system/bta/csis/csis_client.cc b/system/bta/csis/csis_client.cc index d873b2f66f7..1359a0d3f1c 100644 --- a/system/bta/csis/csis_client.cc +++ b/system/bta/csis/csis_client.cc @@ -2327,7 +2327,9 @@ void CsisClient::Initialize(bluetooth::csis::CsisClientCallbacks* callbacks, Clo bool CsisClient::IsCsisClientRunning() { return instance; } CsisClient* CsisClient::Get(void) { - log::assert_that(instance != nullptr, "assert failed: instance != nullptr"); + if (instance == nullptr) { + log::error("instance not available"); + } return instance; } diff --git a/system/bta/csis/csis_client_test.cc b/system/bta/csis/csis_client_test.cc index fcb7467c1fa..3306263a8a5 100644 --- a/system/bta/csis/csis_client_test.cc +++ b/system/bta/csis/csis_client_test.cc @@ -630,7 +630,7 @@ protected: const RawAddress test_address2 = GetTestAddress(1); }; -TEST_F(CsisClientTest, test_get_uninitialized) { ASSERT_DEATH(CsisClient::Get(), ""); } +TEST_F(CsisClientTest, test_get_uninitialized) { ASSERT_EQ(CsisClient::Get(), nullptr); } TEST_F(CsisClientTest, test_initialize) { CsisClient::Initialize(callbacks.get(), base::DoNothing()); -- GitLab From ea9b83648dcb3ebc21e2e0700d70d748996dfd33 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Thu, 26 Sep 2024 22:03:04 +0000 Subject: [PATCH 086/875] Add ATT MTU preference for Tesla app Test: mmm packages/modules/Bluetooth Flag: EXEMPT IOP fix Bug: 369329192 Change-Id: Ie173cc15e888bb989f006c40f9562c6f30a6a7fa --- .../com/android/bluetooth/gatt/GattService.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index a6e4733150d..9015774554c 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -143,6 +143,10 @@ public class GattService extends ProfileService { "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000", }; + private static final Integer GATT_MTU_MAX = 517; + private static final Map EARLY_MTU_EXCHANGE_PACKAGES = + Map.of("com.teslamotors.tesla", GATT_MTU_MAX); + @VisibleForTesting static final int GATT_CLIENT_LIMIT_PER_APP = 32; public final TransitionalScanHelper mTransitionalScanHelper = @@ -2154,6 +2158,19 @@ public class GattService extends ProfileService { -1); int preferredMtu = 0; + + // Some applications expect MTU to be exchanged immediately on connections + String packageName = attributionSource.getPackageName(); + if (packageName != null && EARLY_MTU_EXCHANGE_PACKAGES.containsKey(packageName)) { + preferredMtu = EARLY_MTU_EXCHANGE_PACKAGES.get(packageName); + Log.i( + TAG, + "Early MTU exchange preference (" + + preferredMtu + + ") requested for " + + packageName); + } + mNativeInterface.gattClientConnect( clientIf, address, addressType, isDirect, transport, opportunistic, phy, preferredMtu); } -- GitLab From cc53561d4ec107b0d1ed354ccdda8270c542b0ee Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 27 Sep 2024 16:00:34 +0000 Subject: [PATCH 087/875] Skip ATT Read Blob request for name discovery before MTU exchange Some LE devices cannot handle the ATT Read Blob request. They expect that ATT MTU should be large enough to avoid ATT Read Blob request. Their companion apps are expected to send their MTU preferences. However, LE name discovery may happen earlier than MTU exchange is performed. In such case, ATT Read Blob request is used if the remote device is larger than 20 octets. This change introduces an intermediary IOP fix for such devices by skipping ATT Read Blob request for LE name discovery if their companion app had request MTU exchange but it was not performed yet. Test: mmm packages/modules/Bluetooth Flag: EXEMPT IOP fix Bug: 369329192 Change-Id: I59021fc5530bbaeffefa3c70f46218276a759bbf --- system/stack/gatt/gatt_api.cc | 11 ++++- system/stack/gatt/gatt_cl.cc | 18 +++++++++ system/stack/gatt/gatt_int.h | 7 +++- system/stack/gatt/gatt_main.cc | 9 +++++ system/stack/gatt/gatt_utils.cc | 49 +++++++++++++++++++++++ system/stack/test/gatt/stack_gatt_test.cc | 1 + 6 files changed, 93 insertions(+), 2 deletions(-) diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index aa143ee4312..13705aace0d 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -1457,7 +1457,7 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYP bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys, uint16_t /* preferred_mtu */) { + uint8_t initiating_phys, uint16_t preferred_mtu) { /* Make sure app is registered */ tGATT_REG* p_reg = gatt_get_regcb(gatt_if); if (!p_reg) { @@ -1544,6 +1544,15 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE ad } } + if (ret) { + // Save the current MTU preference for this app + p_reg->mtu_prefs.erase(bd_addr); + if (preferred_mtu > GATT_DEF_BLE_MTU_SIZE) { + log::verbose("Saving MTU preference from app {} for {}", gatt_if, bd_addr); + p_reg->mtu_prefs.insert({bd_addr, preferred_mtu}); + } + } + return ret; } diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc index 7501468aa3e..d0a7ae7c559 100644 --- a/system/stack/gatt/gatt_cl.cc +++ b/system/stack/gatt/gatt_cl.cc @@ -916,7 +916,25 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t o else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE) { p_clcb->counter = len - 2; p_clcb->s_handle = handle; + if (p_clcb->counter == (payload_size - 4)) { + /* IOP: Some devices can't handle Read Blob request. Apps for such devices send their MTU + * preference with the connect request. Expectation is that the stack would exchange MTU + * immediately on connection and thereby avoid using Read Blob request. + * However, the stack does not support exchanging MTU immediately on connection at present. + * As a workaround, GATT client instead just avoids sending Read Blob request when certain + * conditions are met. */ + tGATT_TCB* p_tcb = p_clcb->p_tcb; + if (p_tcb->transport == BT_TRANSPORT_LE && p_tcb->att_lcid == L2CAP_ATT_CID && + p_tcb->app_mtu_pref > GATT_DEF_BLE_MTU_SIZE && + p_tcb->payload_size <= GATT_DEF_BLE_MTU_SIZE && p_clcb->uuid.Is16Bit() && + p_clcb->uuid.As16Bit() == GATT_UUID_GAP_DEVICE_NAME) { + log::warn("Skipping Read Blob request for reading device name {}", p_tcb->peer_bda); + gatt_end_operation(p_clcb, GATT_SUCCESS, (void*)p); + return; + } + + /* Continue reading rest of value */ p_clcb->op_subtype = GATT_READ_BY_HANDLE; if (!p_clcb->p_attr_buf) { p_clcb->p_attr_buf = (uint8_t*)osi_malloc(GATT_MAX_ATTR_LEN); diff --git a/system/stack/gatt/gatt_int.h b/system/stack/gatt/gatt_int.h index 8525953ceb6..10689e39faa 100644 --- a/system/stack/gatt/gatt_int.h +++ b/system/stack/gatt/gatt_int.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -194,6 +195,7 @@ typedef struct { bool eatt_support{false}; std::string name; std::set direct_connect_request; + std::map mtu_prefs; } tGATT_REG; struct tGATT_CLCB; @@ -340,7 +342,7 @@ typedef struct { std::list conn_ids_waiting_for_mtu_exchange; /* Used to set proper TX DATA LEN on the controller*/ uint16_t max_user_mtu; - + uint16_t app_mtu_pref; // Holds consolidated MTU preference from apps at the time of connection } tGATT_TCB; /* logic channel */ @@ -634,6 +636,9 @@ tGATT_TCB* gatt_allocate_tcb_by_bdaddr(const RawAddress& bda, tBT_TRANSPORT tran tGATT_TCB* gatt_get_tcb_by_idx(uint8_t tcb_idx); tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& bda, tBT_TRANSPORT transport); bool gatt_send_ble_burst_data(const RawAddress& remote_bda, BT_HDR* p_buf); +uint16_t gatt_get_mtu_pref(const tGATT_REG* p_reg, const RawAddress& bda); +uint16_t gatt_get_apps_preferred_mtu(const RawAddress& bda); +void gatt_remove_apps_mtu_prefs(const RawAddress& bda); /* GATT client functions */ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid); diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index 8e0c4d0b937..bbec4b65003 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -598,6 +598,15 @@ static void gatt_le_connect_cback(uint16_t /* chan */, const RawAddress& bd_addr log::info("Start EATT before encryption"); EattExtension::GetInstance()->Connect(bd_addr); } + + /* TODO: This preference should be used to exchange MTU with the peer device before the apps are + * notified of the connection. */ + uint16_t app_mtu_pref = gatt_get_apps_preferred_mtu(bd_addr); + gatt_remove_apps_mtu_prefs(bd_addr); + p_tcb->app_mtu_pref = app_mtu_pref; + if (app_mtu_pref > GATT_DEF_BLE_MTU_SIZE) { + log::verbose("Combined app MTU prefs for {}: {}", bd_addr, app_mtu_pref); + } } bool check_cached_model_name(const RawAddress& bd_addr) { diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index 1aa1923857f..a421ca2f28e 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -1993,3 +1993,52 @@ tCONN_ID gatt_create_conn_id(tTCB_IDX tcb_idx, tGATT_IF gatt_if) { tTCB_IDX gatt_get_tcb_idx(tCONN_ID conn_id) { return (uint8_t)(conn_id >> 8); } tGATT_IF gatt_get_gatt_if(tCONN_ID conn_id) { return (tGATT_IF)conn_id; } + +uint16_t gatt_get_mtu_pref(const tGATT_REG* p_reg, const RawAddress& bda) { + auto mtu_pref = p_reg->mtu_prefs.find(bda); + if (mtu_pref != p_reg->mtu_prefs.cend()) { + return mtu_pref->second; + } + return 0; +} + +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)); + } + } else { + for (auto& reg : gatt_cb.cl_rcb) { + if (!reg.in_use) { + continue; + } + + preferred_mtu = std::max(preferred_mtu, gatt_get_mtu_pref(®, 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); + } + } +} diff --git a/system/stack/test/gatt/stack_gatt_test.cc b/system/stack/test/gatt/stack_gatt_test.cc index 3ae3ea11698..2a6b243d43e 100644 --- a/system/stack/test/gatt/stack_gatt_test.cc +++ b/system/stack/test/gatt/stack_gatt_test.cc @@ -122,6 +122,7 @@ TEST_F(StackGattTest, lifecycle_tGATT_REG) { // Restore the complex structure after memset memset(®1.name, 0, sizeof(std::string)); memset(®1.direct_connect_request, 0, sizeof(std::set)); + memset(®1.mtu_prefs, 0, sizeof(std::map)); reg1 = {}; ASSERT_EQ(0, memcmp(reg0.get(), ®1, actual_sizeof_tGATT_REG())); } -- GitLab From 4e41e7ca9d06986e95965e28cde90f44fef1f190 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 27 Sep 2024 21:16:27 +0000 Subject: [PATCH 088/875] Reducing Gatt_Connect overloads Test: mmm packages/modules/Bluetooth Flag: EXEMPT manual refactor Bug: 369329192 Change-Id: I35c7aa3830f5dd6760955a14728440839c3a3c59 --- system/bta/dm/bta_dm_disc.cc | 2 +- system/bta/dm/bta_dm_gatt_client.cc | 2 +- system/bta/gatt/bta_gattc_act.cc | 2 +- system/bta/gatt/bta_gattc_api.cc | 19 ++--------------- system/bta/gatt/bta_gatts_act.cc | 2 +- system/bta/include/bta_gatt_api.h | 6 ------ system/stack/gatt/gatt_api.cc | 26 ++---------------------- system/stack/include/gatt_api.h | 27 +++++++++++++------------ system/test/mock/mock_bta_gattc_api.cc | 11 ---------- system/test/mock/mock_stack_gatt_api.cc | 2 +- 10 files changed, 23 insertions(+), 76 deletions(-) diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc index 980f2d45f2d..f22870f9009 100644 --- a/system/bta/dm/bta_dm_disc.cc +++ b/system/bta/dm/bta_dm_disc.cc @@ -141,7 +141,7 @@ struct gatt_interface_t { [](tGATT_IF client_if, const RawAddress& remote_bda, tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, uint16_t preferred_mtu) { BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type, - BT_TRANSPORT_LE, opportunistic, 1, preferred_mtu); + BT_TRANSPORT_LE, opportunistic, LE_PHY_1M, preferred_mtu); }, }; diff --git a/system/bta/dm/bta_dm_gatt_client.cc b/system/bta/dm/bta_dm_gatt_client.cc index c9fec2d392d..63ef540afa2 100644 --- a/system/bta/dm/bta_dm_gatt_client.cc +++ b/system/bta/dm/bta_dm_gatt_client.cc @@ -104,7 +104,7 @@ gatt_interface_t default_gatt_interface = { ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, connection_type, (opportunistic) ? 'T' : 'F')); BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type, - BT_TRANSPORT_LE, opportunistic, 1, preferred_mtu); + BT_TRANSPORT_LE, opportunistic, LE_PHY_1M, preferred_mtu); }, }; diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index 3437f15266b..636951cb8cf 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -485,7 +485,7 @@ static void bta_gattc_init_bk_conn(const tBTA_GATTC_API_OPEN* p_data, tBTA_GATTC /* always call open to hold a connection */ if (!GATT_Connect(p_data->client_if, p_data->remote_bda, BLE_ADDR_PUBLIC, p_data->connection_type, - p_data->transport, false, 1, p_data->preferred_mtu)) { + p_data->transport, false, LE_PHY_1M, p_data->preferred_mtu)) { log::error("Unable to connect to remote bd_addr={}", p_data->remote_bda); bta_gattc_send_open_cback(p_clreg, GATT_ILLEGAL_PARAMETER, p_data->remote_bda, GATT_INVALID_CONN_ID, BT_TRANSPORT_LE, 0); diff --git a/system/bta/gatt/bta_gattc_api.cc b/system/bta/gatt/bta_gattc_api.cc index 206cc943644..d4dfc500b1a 100644 --- a/system/bta/gatt/bta_gattc_api.cc +++ b/system/bta/gatt/bta_gattc_api.cc @@ -133,13 +133,6 @@ void BTA_GATTC_AppDeregister(tGATT_IF client_if) { * opportunistic, and don't impact the disconnection timer * ******************************************************************************/ -void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) { - constexpr uint8_t kPhyLe1M = 0x01; // From the old controller shim. - uint8_t phy = kPhyLe1M; - BTA_GATTC_Open(client_if, remote_bda, connection_type, BT_TRANSPORT_LE, opportunistic, phy); -} - void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys, uint16_t preferred_mtu) { @@ -164,18 +157,10 @@ void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_ post_on_bt_main([data]() { bta_gattc_process_api_open(&data); }); } -void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys) { - BTA_GATTC_Open(client_if, remote_bda, addr_type, connection_type, transport, opportunistic, - initiating_phys, 0); -} - void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys) { + tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) { BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type, BT_TRANSPORT_LE, - opportunistic, initiating_phys); + opportunistic, LE_PHY_1M, 0); } /******************************************************************************* diff --git a/system/bta/gatt/bta_gatts_act.cc b/system/bta/gatt/bta_gatts_act.cc index 47abf7106d1..78bfb8bfcf3 100644 --- a/system/bta/gatt/bta_gatts_act.cc +++ b/system/bta/gatt/bta_gatts_act.cc @@ -419,7 +419,7 @@ void bta_gatts_open(tBTA_GATTS_CB* /* p_cb */, tBTA_GATTS_DATA* p_msg) { if (com::android::bluetooth::flags::ble_gatt_server_use_address_type_in_connection()) { success = GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda, p_msg->api_open.remote_addr_type, p_msg->api_open.connection_type, - p_msg->api_open.transport, false); + p_msg->api_open.transport, false, LE_PHY_1M, 0); } else { success = GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda, p_msg->api_open.connection_type, p_msg->api_open.transport, false); diff --git a/system/bta/include/bta_gatt_api.h b/system/bta/include/bta_gatt_api.h index 1079e813ad9..ba60da6ee4e 100644 --- a/system/bta/include/bta_gatt_api.h +++ b/system/bta/include/bta_gatt_api.h @@ -499,12 +499,6 @@ void BTA_GATTC_AppDeregister(tGATT_IF client_if); ******************************************************************************/ void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBTM_BLE_CONN_TYPE connection_type, bool opportunistic); -void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys); -void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys); void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys, uint16_t preferred_mtu); diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index 13705aace0d..a5a863708f1 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -1448,13 +1448,6 @@ void GATT_StartIf(tGATT_IF gatt_if) { * failure. * ******************************************************************************/ -bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYPE connection_type, - tBT_TRANSPORT transport, bool opportunistic) { - constexpr uint8_t kPhyLe1M = 0x01; // From the old controller shim. - uint8_t phy = kPhyLe1M; - return GATT_Connect(gatt_if, bd_addr, connection_type, transport, opportunistic, phy); -} - bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys, uint16_t preferred_mtu) { @@ -1556,25 +1549,10 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE ad return ret; } -bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic) { - constexpr uint8_t kPhyLe1M = 0x01; // From the old controller shim. - uint8_t phy = kPhyLe1M; - return GATT_Connect(gatt_if, bd_addr, addr_type, connection_type, transport, opportunistic, phy, - 0); -} - -bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYPE connection_type, - tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys) { - return GATT_Connect(gatt_if, bd_addr, BLE_ADDR_PUBLIC, connection_type, transport, opportunistic, - initiating_phys, 0); -} - bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYPE connection_type, - tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys, - uint16_t preferred_mtu) { + tBT_TRANSPORT transport, bool opportunistic) { return GATT_Connect(gatt_if, bd_addr, BLE_ADDR_PUBLIC, connection_type, transport, opportunistic, - initiating_phys, preferred_mtu); + LE_PHY_1M, 0); } /******************************************************************************* diff --git a/system/stack/include/gatt_api.h b/system/stack/include/gatt_api.h index 911df290231..e51ddc08255 100644 --- a/system/stack/include/gatt_api.h +++ b/system/stack/include/gatt_api.h @@ -298,6 +298,16 @@ inline std::string gatt_disconnection_reason_text(const tGATT_DISCONN_REASON& re } } +/* LE PHY bits */ +constexpr uint8_t LE_PHY_1M_BIT = 0; +constexpr uint8_t LE_PHY_2M_BIT = 1; +constexpr uint8_t LE_PHY_CODED_BIT = 2; + +/* LE PHY bit mask values */ +constexpr uint8_t LE_PHY_1M = (1 << LE_PHY_1M_BIT); +constexpr uint8_t LE_PHY_2M = (1 << LE_PHY_2M_BIT); +constexpr uint8_t LE_PHY_CODED = (1 << LE_PHY_CODED_BIT); + /* MAX GATT MTU size */ #ifndef GATT_MAX_MTU_SIZE @@ -1165,23 +1175,14 @@ void GATT_StartIf(tGATT_IF gatt_if); * Returns true if connection started; else false * ******************************************************************************/ -[[nodiscard]] bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, - bool opportunistic); -[[nodiscard]] bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, - tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, - bool opportunistic, uint8_t initiating_phys); -[[nodiscard]] bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, - tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, - tBT_TRANSPORT transport, bool opportunistic); -[[nodiscard]] bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, - tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, - tBT_TRANSPORT transport, bool opportunistic, - uint8_t initiating_phys); [[nodiscard]] bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys, uint16_t preferred_transport); +[[nodiscard]] bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, + tBTM_BLE_CONN_TYPE connection_type, tBT_TRANSPORT transport, + bool opportunistic); + /******************************************************************************* * * Function GATT_CancelConnect diff --git a/system/test/mock/mock_bta_gattc_api.cc b/system/test/mock/mock_bta_gattc_api.cc index 686868455cd..7bea0245cea 100644 --- a/system/test/mock/mock_bta_gattc_api.cc +++ b/system/test/mock/mock_bta_gattc_api.cc @@ -101,17 +101,6 @@ void BTA_GATTC_Open(tGATT_IF /* client_if */, const RawAddress& /* remote_bda */ tBTM_BLE_CONN_TYPE /* connection_type */, bool /* opportunistic */) { inc_func_call_count(__func__); } -void BTA_GATTC_Open(tGATT_IF /* client_if */, const RawAddress& /* remote_bda */, - tBTM_BLE_CONN_TYPE /* connection_type */, tBT_TRANSPORT /* transport */, - bool /* opportunistic */, uint8_t /* initiating_phys */) { - inc_func_call_count(__func__); -} -void BTA_GATTC_Open(tGATT_IF /* client_if */, const RawAddress& /* remote_bda */, - tBLE_ADDR_TYPE /* addr_type */, tBTM_BLE_CONN_TYPE /* connection_type */, - tBT_TRANSPORT /* transport */, bool /* opportunistic */, - uint8_t /* initiating_phys */) { - inc_func_call_count(__func__); -} void BTA_GATTC_Open(tGATT_IF /* client_if */, const RawAddress& /* remote_bda */, tBLE_ADDR_TYPE /* addr_type */, tBTM_BLE_CONN_TYPE /* connection_type */, tBT_TRANSPORT /* transport */, bool /* opportunistic */, diff --git a/system/test/mock/mock_stack_gatt_api.cc b/system/test/mock/mock_stack_gatt_api.cc index 88b7af29a0f..cde6c3fa6b3 100644 --- a/system/test/mock/mock_stack_gatt_api.cc +++ b/system/test/mock/mock_stack_gatt_api.cc @@ -244,7 +244,7 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYP tBT_TRANSPORT transport, bool opportunistic) { inc_func_call_count(__func__); return test::mock::stack_gatt_api::GATT_Connect(gatt_if, bd_addr, 0, connection_type, transport, - opportunistic, 0, 0); + opportunistic, LE_PHY_1M, 0); } // END mockcify generation -- GitLab From 85259a993019e080d6454616904a57eb070bbe9c Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Sat, 28 Sep 2024 12:48:09 -0700 Subject: [PATCH 089/875] Fixes for errorprone update When updating errorprone from 2.23.0 -> 2.32.0, more issues are found. Bug: 253827323 Test: m RUN_ERROR_PRONE=true javac-check Change-Id: Iac9b4741bfc289abdcf0da67eee4104552032930 --- .../android/bluetooth/audio_util/MediaBrowserWrapper.java | 5 ++--- .../src/com/android/bluetooth/opp/BluetoothOppService.java | 4 ++-- framework/java/android/bluetooth/le/ScanFilter.java | 6 ++---- 3 files changed, 6 insertions(+), 9 deletions(-) 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 7a8e0dc8180..f45fc0b1898 100644 --- a/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java +++ b/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java @@ -189,8 +189,7 @@ class MediaBrowserWrapper { + mediaId + ": adding callback and subscribing."); mSubscribedIds.put(mediaId, new ArrayList<>(Arrays.asList(callback))); - mWrappedBrowser.subscribe( - mediaId, new BrowserSubscriptionCallback(mLooper, mediaId)); + mWrappedBrowser.subscribe(mediaId, new BrowserSubscriptionCallback(mediaId)); }); } @@ -319,7 +318,7 @@ class MediaBrowserWrapper { private final Runnable mTimeoutRunnable; private boolean mCallbacksExecuted = false; - public BrowserSubscriptionCallback(Looper looper, String mediaId) { + BrowserSubscriptionCallback(String mediaId) { mTimeoutRunnable = () -> { executeCallbacks(mediaId, new ArrayList<>()); diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java index ee98f5df289..559654de4fa 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java @@ -244,12 +244,12 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti @Override protected IProfileServiceBinder initBinder() { - return new OppBinder(this); + return new OppBinder(); } private static class OppBinder extends Binder implements IProfileServiceBinder { - OppBinder(BluetoothOppService service) {} + OppBinder() {} @Override public void cleanup() {} diff --git a/framework/java/android/bluetooth/le/ScanFilter.java b/framework/java/android/bluetooth/le/ScanFilter.java index 77beb3cde38..8571b7e0f55 100644 --- a/framework/java/android/bluetooth/le/ScanFilter.java +++ b/framework/java/android/bluetooth/le/ScanFilter.java @@ -303,11 +303,9 @@ public final class ScanFilter implements Parcelable { // Advertising data type int advertisingDataType = in.readInt(); if (in.readInt() == 1) { - byte[] advertisingData = null; - byte[] advertisingDataMask = null; - int advertisingDataLength = in.readInt(); - advertisingData = new byte[advertisingDataLength]; + byte[] advertisingData = new byte[advertisingDataLength]; + byte[] advertisingDataMask = null; in.readByteArray(advertisingData); if (in.readInt() == 1) { int advertisingDataMaskLength = in.readInt(); -- GitLab From 8db8e6777c41aacac4647d8e0c3ae7b7b654b33d Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Fri, 27 Sep 2024 17:45:56 +0900 Subject: [PATCH 090/875] Fix ConcurrentModificationException in AdvertiseManager.mAdvertisers Bug: 365034146 Test: atest BluetoothInstrumentationTests Flag: EXEMPT, only adding synchronizations Change-Id: I5175e41c6e3f95de1ee0d95ff25d12295e73838c --- .../bluetooth/gatt/AdvertiseManager.java | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java index 0cacbd83010..7ca12908c39 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java @@ -31,9 +31,9 @@ import android.os.RemoteException; import android.util.Log; import com.android.bluetooth.btservice.AdapterService; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -47,8 +47,11 @@ public class AdvertiseManager { private final GattService mService; private final AdvertiseManagerNativeInterface mNativeInterface; private final AdvertiserMap mAdvertiserMap; + + @GuardedBy("itself") + private final Map mAdvertisers = new HashMap<>(); + private Handler mHandler; - Map mAdvertisers = Collections.synchronizedMap(new HashMap<>()); static int sTempRegistrationId = -1; AdvertiseManager(GattService service) { @@ -81,7 +84,9 @@ public class AdvertiseManager { void cleanup() { Log.d(TAG, "cleanup()"); mNativeInterface.cleanup(); - mAdvertisers.clear(); + synchronized (mAdvertisers) { + mAdvertisers.clear(); + } sTempRegistrationId = -1; if (mHandler != null) { @@ -138,10 +143,12 @@ public class AdvertiseManager { Map.Entry findAdvertiser(int advertiserId) { Map.Entry entry = null; - for (Map.Entry e : mAdvertisers.entrySet()) { - if (e.getValue().id == advertiserId) { - entry = e; - break; + synchronized (mAdvertisers) { + for (Map.Entry e : mAdvertisers.entrySet()) { + if (e.getValue().id == advertiserId) { + entry = e; + break; + } } } return entry; @@ -176,11 +183,17 @@ public class AdvertiseManager { } else { IBinder binder = entry.getKey(); binder.unlinkToDeath(entry.getValue().deathRecipient, 0); - mAdvertisers.remove(binder); + synchronized (mAdvertisers) { + mAdvertisers.remove(binder); + } AppAdvertiseStats stats = mAdvertiserMap.getAppAdvertiseStatsById(regId); if (stats != null) { - stats.recordAdvertiseStop(mAdvertisers.size()); + int instanceCount; + synchronized (mAdvertisers) { + instanceCount = mAdvertisers.size(); + } + stats.recordAdvertiseStop(instanceCount); stats.recordAdvertiseErrorCount(status); } mAdvertiserMap.removeAppAdvertiseStats(regId); @@ -215,7 +228,11 @@ public class AdvertiseManager { if (!enable && status != 0) { AppAdvertiseStats stats = mAdvertiserMap.getAppAdvertiseStatsById(advertiserId); if (stats != null) { - stats.recordAdvertiseStop(mAdvertisers.size()); + int instanceCount; + synchronized (mAdvertisers) { + instanceCount = mAdvertisers.size(); + } + stats.recordAdvertiseStop(instanceCount); } } } @@ -271,7 +288,9 @@ public class AdvertiseManager { AdvertiseHelper.advertiseDataToBytes(periodicData, deviceName); int cbId = --sTempRegistrationId; - mAdvertisers.put(binder, new AdvertiserInfo(cbId, deathRecipient, callback)); + synchronized (mAdvertisers) { + mAdvertisers.put(binder, new AdvertiserInfo(cbId, deathRecipient, callback)); + } Log.d(TAG, "startAdvertisingSet() - reg_id=" + cbId + ", callback: " + binder); @@ -336,7 +355,10 @@ public class AdvertiseManager { IBinder binder = toBinder(callback); Log.d(TAG, "stopAdvertisingSet() " + binder); - AdvertiserInfo adv = mAdvertisers.remove(binder); + AdvertiserInfo adv; + synchronized (mAdvertisers) { + adv = mAdvertisers.remove(binder); + } if (adv == null) { Log.e(TAG, "stopAdvertisingSet() - no client found for callback"); return; -- GitLab From 993217392462079359ac3a0b28a936ed68ff601e Mon Sep 17 00:00:00 2001 From: Jakub Rotkiewicz Date: Mon, 30 Sep 2024 07:17:23 +0000 Subject: [PATCH 091/875] TbsGatt: test null URI for incoming call Test if provided nulled URI doesn't cause crash Bug: 358527937 Test: atest TbsGenericTest Flag: EXEMPT, test only Change-Id: I2ccceb3e1d5a6a17f52c00447557be58134863c0 --- .../com/android/bluetooth/tbs/TbsCall.java | 5 ++- .../android/bluetooth/tbs/TbsGenericTest.java | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/android/app/src/com/android/bluetooth/tbs/TbsCall.java b/android/app/src/com/android/bluetooth/tbs/TbsCall.java index bcf1bb31f83..9432643ff65 100644 --- a/android/app/src/com/android/bluetooth/tbs/TbsCall.java +++ b/android/app/src/com/android/bluetooth/tbs/TbsCall.java @@ -127,7 +127,10 @@ public class TbsCall { } public String getSafeUri() { - return Uri.parse(mUri).toSafeString(); + if (mUri != null) { + return Uri.parse(mUri).toSafeString(); + } + return null; } public int getFlags() { diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java index 3944a12b0cd..d7ed9eee6ca 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java @@ -222,6 +222,38 @@ public class TbsGenericTest { assertThat(capturedTbsCall.getFriendlyName()).isEqualTo("aFriendlyCaller"); } + @Test + public void testCallAddedWithNullUri() { + Integer ccid = prepareTestBearer(); + reset(mTbsGatt); + + BluetoothLeCall tbsCall = + new BluetoothLeCall( + UUID.randomUUID(), + null, + "aFriendlyCaller", + BluetoothLeCall.STATE_INCOMING, + 0); + mTbsGeneric.callAdded(ccid, tbsCall); + + ArgumentCaptor callIndexCaptor = ArgumentCaptor.forClass(Integer.class); + verify(mTbsGatt).setIncomingCall(callIndexCaptor.capture(), eq(null)); + Integer capturedCallIndex = callIndexCaptor.getValue(); + verify(mTbsGatt).setCallFriendlyName(eq(capturedCallIndex), eq("aFriendlyCaller")); + ArgumentCaptor currentCallsCaptor = ArgumentCaptor.forClass(Map.class); + verify(mTbsGatt).setCallState(currentCallsCaptor.capture()); + Map capturedCurrentCalls = currentCallsCaptor.getValue(); + assertThat(capturedCurrentCalls.size()).isEqualTo(1); + TbsCall capturedTbsCall = capturedCurrentCalls.get(capturedCallIndex); + assertThat(capturedTbsCall).isNotNull(); + assertThat(capturedTbsCall.getState()).isEqualTo(BluetoothLeCall.STATE_INCOMING); + assertThat(capturedTbsCall.getUri()).isEqualTo(null); + assertThat(capturedTbsCall.getSafeUri()).isEqualTo(null); + assertThat(capturedTbsCall.getFlags()).isEqualTo(0); + assertThat(capturedTbsCall.isIncoming()).isTrue(); + assertThat(capturedTbsCall.getFriendlyName()).isEqualTo("aFriendlyCaller"); + } + @Test public void testCallRemoved() { Integer ccid = prepareTestBearer(); -- GitLab From 893fdced511c0d6ab263b5a48eb04281a79eefce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 27 Mar 2024 09:03:15 +0000 Subject: [PATCH 092/875] BluetoothLeAudio: Add MONO location Due to errata audio location 0x0000 is not "invalid" anymore but instead "Mono Audio (no specified Audio Location)" https://www.bluetooth.com/specifications/assigned-numbers/ 6.12.1 Audio Location Definitions Also new Unknown location is added which is used only when Bluetooth is not available. Bug: 330847930 Bug: 331139722 Test: mmm packages/modules/Bluetooth Change-Id: Ibadaee63edd123ba4b31edade524344d6689135e --- framework/api/system-current.txt | 2 + .../android/bluetooth/BluetoothLeAudio.java | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 783635e7d45..5d5b4dd4553 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -483,6 +483,7 @@ package android.bluetooth { field public static final int AUDIO_LOCATION_LEFT_SURROUND = 67108864; // 0x4000000 field public static final int AUDIO_LOCATION_LOW_FREQ_EFFECTS_ONE = 8; // 0x8 field public static final int AUDIO_LOCATION_LOW_FREQ_EFFECTS_TWO = 512; // 0x200 + field @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata") public static final int AUDIO_LOCATION_MONO = 0; // 0x0 field public static final int AUDIO_LOCATION_RIGHT_SURROUND = 134217728; // 0x8000000 field public static final int AUDIO_LOCATION_SIDE_LEFT = 1024; // 0x400 field public static final int AUDIO_LOCATION_SIDE_RIGHT = 2048; // 0x800 @@ -495,6 +496,7 @@ package android.bluetooth { field public static final int AUDIO_LOCATION_TOP_FRONT_RIGHT = 8192; // 0x2000 field public static final int AUDIO_LOCATION_TOP_SIDE_LEFT = 262144; // 0x40000 field public static final int AUDIO_LOCATION_TOP_SIDE_RIGHT = 524288; // 0x80000 + field @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata") public static final int AUDIO_LOCATION_UNKNOWN = -2147483648; // 0x80000000 field public static final String EXTRA_LE_AUDIO_GROUP_ID = "android.bluetooth.extra.LE_AUDIO_GROUP_ID"; field public static final int GROUP_STREAM_STATUS_IDLE = 0; // 0x0 field public static final int GROUP_STREAM_STATUS_STREAMING = 1; // 0x1 diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index 28a7964d078..b9f9952578a 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -23,6 +23,7 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static java.util.Objects.requireNonNull; import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; @@ -33,8 +34,11 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.app.compat.CompatChanges; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.content.AttributionSource; import android.content.Context; import android.os.IBinder; @@ -43,6 +47,8 @@ import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.bluetooth.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Collections; @@ -346,6 +352,14 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { /** This represents an invalid group ID. */ public static final int GROUP_ID_INVALID = IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; + /** + * This ChangeId allows to use new Mono audio location as per + * https://www.bluetooth.com/specifications/assigned-numbers/ 6.12.1 Audio Location Definitions + */ + @ChangeId + @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM) + static final long LEAUDIO_MONO_LOCATION_ERRATA = 330847930L; + /** * This represents an invalid audio location. * @@ -353,6 +367,24 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { */ @SystemApi public static final int AUDIO_LOCATION_INVALID = 0; + /** + * This represents an Mono audio location. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA) + @SystemApi + public static final int AUDIO_LOCATION_MONO = 0; + + /** + * This represents an Unknown audio location which will be returned only when Bluetooth is OFF. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA) + @SystemApi + public static final int AUDIO_LOCATION_UNKNOWN = 0x01 << 31; + /** * This represents an audio location front left. * @@ -550,11 +582,13 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @SystemApi public static final int AUDIO_LOCATION_RIGHT_SURROUND = 0x01 << 27; /** @hide */ + @SuppressLint("UniqueConstants") @IntDef( flag = true, prefix = "AUDIO_LOCATION_", value = { AUDIO_LOCATION_INVALID, + AUDIO_LOCATION_MONO, AUDIO_LOCATION_FRONT_LEFT, AUDIO_LOCATION_FRONT_RIGHT, AUDIO_LOCATION_FRONT_CENTER, @@ -583,6 +617,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { AUDIO_LOCATION_FRONT_RIGHT_WIDE, AUDIO_LOCATION_LEFT_SURROUND, AUDIO_LOCATION_RIGHT_SURROUND, + AUDIO_LOCATION_UNKNOWN, }) @Retention(RetentionPolicy.SOURCE) public @interface AudioLocation {} @@ -1140,8 +1175,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { * Front Left: 0x00000001 Front Right: 0x00000002 Front Left | Front Right: 0x00000003 * * @param device the bluetooth device - * @return The bit field of audio location for the device, if bluetooth is off, return - * AUDIO_LOCATION_INVALID. + * @return The bit field of audio location for the device. * @hide */ @SystemApi @@ -1160,6 +1194,12 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } + + if (Flags.leaudioMonoLocationErrata() + && CompatChanges.isChangeEnabled(LEAUDIO_MONO_LOCATION_ERRATA)) { + return AUDIO_LOCATION_UNKNOWN; + } + return AUDIO_LOCATION_INVALID; } -- GitLab From 639478bd4072c5568bf94ffd76c290c27d79da5d Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Mon, 30 Sep 2024 15:45:44 +0800 Subject: [PATCH 093/875] floss: Deprecated InitFlags The InitFlags argument is not used in btif so this patch has no logical change. Bug: 370387120 Tag: #floss Test: mmm packages/modules/Bluetooth Test: USE=floss_upstream emerge-zork floss Flag: EXEMPT, no logical change Change-Id: I9e02024959486a14dca14875b2adaa31183d332c --- system/gd/rust/linux/client/src/dbus_iface.rs | 2 +- .../rust/linux/service/src/iface_bluetooth.rs | 2 +- system/gd/rust/linux/service/src/main.rs | 10 +-- system/gd/rust/linux/stack/src/bluetooth.rs | 10 +-- system/gd/rust/topshim/Android.bp | 3 - system/gd/rust/topshim/BUILD.gn | 3 - system/gd/rust/topshim/btif/btif_shim.cc | 67 ------------------- system/gd/rust/topshim/btif/btif_shim.h | 45 ------------- .../topshim/facade/src/adapter_service.rs | 9 ++- system/gd/rust/topshim/src/btif.rs | 27 +------- 10 files changed, 12 insertions(+), 166 deletions(-) delete mode 100644 system/gd/rust/topshim/btif/btif_shim.cc delete mode 100644 system/gd/rust/topshim/btif/btif_shim.h diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index a2f7ad64eaa..c1368aeff2d 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -772,7 +772,7 @@ impl IBluetooth for BluetoothDBus { dbus_generated!() } - fn init(&mut self, _init_flags: Vec, _hci_index: i32) -> bool { + fn init(&mut self, _hci_index: i32) -> bool { // Not implemented by server true } diff --git a/system/gd/rust/linux/service/src/iface_bluetooth.rs b/system/gd/rust/linux/service/src/iface_bluetooth.rs index 260e26df469..3de32bbbb5e 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth.rs @@ -499,7 +499,7 @@ impl IBluetooth for IBluetoothDBus { } // Not exposed over D-Bus. The stack is automatically initialized when the daemon starts. - fn init(&mut self, _init_flags: Vec, _hci_index: i32) -> bool { + fn init(&mut self, _hci_index: i32) -> bool { dbus_generated!() } diff --git a/system/gd/rust/linux/service/src/main.rs b/system/gd/rust/linux/service/src/main.rs index 441a60f604b..df781794a19 100644 --- a/system/gd/rust/linux/service/src/main.rs +++ b/system/gd/rust/linux/service/src/main.rs @@ -59,7 +59,6 @@ const INIT_LOGGING_MAX_RETRY: u8 = 3; /// Runs the Bluetooth daemon serving D-Bus IPC. fn main() -> Result<(), Box> { let matches = App::new("Bluetooth Adapter Daemon") - // Allows multiple INIT_ flags to be given at the end of the arguments. .setting(AppSettings::TrailingVarArg) .arg( Arg::with_name("hci") @@ -82,7 +81,6 @@ fn main() -> Result<(), Box> { .short("v") .help("Enables VERBOSE and additional tags for debug logging. Use with --debug."), ) - .arg(Arg::from_usage("[init-flags] 'Fluoride INIT_ flags'").multiple(true)) .arg( Arg::with_name("log-output") .long("log-output") @@ -100,12 +98,6 @@ fn main() -> Result<(), Box> { let virt_index = matches.value_of("index").map_or(0, |idx| idx.parse::().unwrap_or(0)); let hci_index = matches.value_of("hci").map_or(0, |idx| idx.parse::().unwrap_or(0)); - // The remaining flags are passed down to Fluoride as is. - let init_flags: Vec = match matches.values_of("init-flags") { - Some(args) => args.map(String::from).collect(), - None => vec![], - }; - let logging = Arc::new(Mutex::new(Box::new(BluetoothLogging::new( is_debug, is_verbose_debug, @@ -178,7 +170,7 @@ fn main() -> Result<(), Box> { let battery_provider_manager = Arc::new(Mutex::new(Box::new(BatteryProviderManager::new(tx.clone())))); - bluetooth.lock().unwrap().init(init_flags, hci_index); + bluetooth.lock().unwrap().init(hci_index); bluetooth.lock().unwrap().enable(); // These constructions require |intf| to be already init-ed. diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index d65c85458ce..f2a91d929fc 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -97,7 +97,7 @@ pub trait IBluetooth { fn unregister_connection_callback(&mut self, callback_id: u32) -> bool; /// Inits the bluetooth interface. Should always be called before enable. - fn init(&mut self, init_flags: Vec, hci_index: i32) -> bool; + fn init(&mut self, hci_index: i32) -> bool; /// Enables the adapter. /// @@ -2223,12 +2223,8 @@ impl IBluetooth for Bluetooth { self.connection_callbacks.remove_callback(callback_id) } - fn init(&mut self, init_flags: Vec, hci_index: i32) -> bool { - self.intf.lock().unwrap().initialize( - get_bt_dispatcher(self.tx.clone()), - init_flags, - hci_index, - ) + fn init(&mut self, hci_index: i32) -> bool { + self.intf.lock().unwrap().initialize(get_bt_dispatcher(self.tx.clone()), hci_index) } fn enable(&mut self) -> bool { diff --git a/system/gd/rust/topshim/Android.bp b/system/gd/rust/topshim/Android.bp index 391017ac961..1ce52154411 100644 --- a/system/gd/rust/topshim/Android.bp +++ b/system/gd/rust/topshim/Android.bp @@ -45,7 +45,6 @@ cc_library_static { srcs: [ "btav/btav_shim.cc", "btav_sink/btav_sink_shim.cc", - "btif/btif_shim.cc", "controller/controller_shim.cc", "csis/csis_shim.cc", "gatt/gatt_ble_advertiser_shim.cc", @@ -83,7 +82,6 @@ gensrcs { tools: ["cxxbridge"], cmd: "$(location cxxbridge) $(in) --header > $(out)", srcs: [ - "src/btif.rs", "src/controller.rs", "src/profiles/a2dp.rs", "src/profiles/avrcp.rs", @@ -102,7 +100,6 @@ gensrcs { tools: ["cxxbridge"], cmd: "$(location cxxbridge) $(in) > $(out)", srcs: [ - "src/btif.rs", "src/controller.rs", "src/profiles/a2dp.rs", "src/profiles/avrcp.rs", diff --git a/system/gd/rust/topshim/BUILD.gn b/system/gd/rust/topshim/BUILD.gn index cc3d48ad255..a20dbeee532 100644 --- a/system/gd/rust/topshim/BUILD.gn +++ b/system/gd/rust/topshim/BUILD.gn @@ -22,7 +22,6 @@ config("rust_topshim_config") { cxxbridge_header("btif_bridge_header") { sources = [ - "src/btif.rs", "src/controller.rs", "src/metrics.rs", "src/profiles/a2dp.rs", @@ -39,7 +38,6 @@ cxxbridge_header("btif_bridge_header") { cxxbridge_cc("btif_bridge_code") { sources = [ - "src/btif.rs", "src/controller.rs", "src/metrics.rs", "src/profiles/a2dp.rs", @@ -64,7 +62,6 @@ source_set("btif_cxx_bridge_code") { sources = [ "btav/btav_shim.cc", "btav_sink/btav_sink_shim.cc", - "btif/btif_shim.cc", "controller/controller_shim.cc", "csis/csis_shim.cc", "gatt/gatt_ble_advertiser_shim.cc", diff --git a/system/gd/rust/topshim/btif/btif_shim.cc b/system/gd/rust/topshim/btif/btif_shim.cc deleted file mode 100644 index ed31a15e9a5..00000000000 --- a/system/gd/rust/topshim/btif/btif_shim.cc +++ /dev/null @@ -1,67 +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 "rust/topshim/btif/btif_shim.h" - -#include -#include -#include -#include - -#include "rust/cxx.h" -#include "src/btif.rs.h" - -namespace bluetooth { -namespace topshim { -namespace rust { - -InitFlags::InitFlags() {} -InitFlags::~InitFlags() { - if (flags_) { - for (int i = 0; flags_[i] != nullptr; ++i) { - std::free(const_cast(static_cast(flags_[i]))); - } - - std::free(const_cast(static_cast(flags_))); - } -} - -void InitFlags::Convert(::rust::Vec<::rust::String>& initFlags) { - // Allocate number of flags + 1 (last entry must be null to signify end) - // Must be calloc so our cleanup correctly frees everything - flags_ = static_cast(std::calloc(initFlags.size() + 1, sizeof(char*))); - if (!flags_) { - return; - } - - for (size_t i = 0; i < initFlags.size(); ++i) { - flags_[i] = strndup(initFlags[i].data(), initFlags[i].size()); - if (!flags_[i]) { - return; - } - } -} - -std::unique_ptr ConvertFlags(::rust::Vec<::rust::String> flags) { - auto ret = std::make_unique(); - ret->Convert(flags); - - return ret; -} - -} // namespace rust -} // namespace topshim -} // namespace bluetooth diff --git a/system/gd/rust/topshim/btif/btif_shim.h b/system/gd/rust/topshim/btif/btif_shim.h deleted file mode 100644 index b04baf871f0..00000000000 --- a/system/gd/rust/topshim/btif/btif_shim.h +++ /dev/null @@ -1,45 +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. - */ -#ifndef GD_RUST_TOPSHIM_BTIF_BTIF_SHIM_H -#define GD_RUST_TOPSHIM_BTIF_BTIF_SHIM_H - -#include - -#include "rust/cxx.h" - -namespace bluetooth { -namespace topshim { -namespace rust { - -class InitFlags { -public: - InitFlags(); - ~InitFlags(); - - void Convert(::rust::Vec<::rust::String>& flags); - const char** GetFlagsPtr() const { return flags_; } - -private: - const char** flags_; -}; - -std::unique_ptr ConvertFlags(::rust::Vec<::rust::String> flags); - -} // namespace rust -} // namespace topshim -} // namespace bluetooth - -#endif // GD_RUST_TOPSHIM_BTIF_BTIF_SHIM_H diff --git a/system/gd/rust/topshim/facade/src/adapter_service.rs b/system/gd/rust/topshim/facade/src/adapter_service.rs index 43338b9f0e1..bd56ea5bad7 100644 --- a/system/gd/rust/topshim/facade/src/adapter_service.rs +++ b/system/gd/rust/topshim/facade/src/adapter_service.rs @@ -91,11 +91,10 @@ impl AdapterServiceImpl { /// Create a new instance of the root facade service pub fn create(rt: Arc, btif_intf: Arc>) -> grpcio::Service { let (event_tx, rx) = mpsc::channel(10); - btif_intf.lock().unwrap().initialize( - get_bt_dispatcher(btif_intf.clone(), event_tx.clone()), - vec!["INIT_gd_hci=true".to_string()], - 0, - ); + btif_intf + .lock() + .unwrap() + .initialize(get_bt_dispatcher(btif_intf.clone(), event_tx.clone()), 0); create_adapter_service(Self { rt, btif_intf, diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index 0837f5fcfb4..b5df64fb7e8 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -928,20 +928,6 @@ impl From for Vec { } } -#[cxx::bridge(namespace = bluetooth::topshim::rust)] -mod ffi { - unsafe extern "C++" { - include!("btif/btif_shim.h"); - - // For converting init flags from Vec to const char ** - type InitFlags; - - // Convert flgas into an InitFlags object - fn ConvertFlags(flags: Vec) -> UniquePtr; - fn GetFlagsPtr(self: &InitFlags) -> *mut *const c_char; - } -} - /// Generate impl cxx::ExternType for RawAddress and Uuid. /// /// To make use of RawAddress and Uuid in cxx::bridge C++ blocks, @@ -1231,16 +1217,7 @@ impl BluetoothInterface { /// * `callbacks` - Dispatcher struct that accepts [`BaseCallbacks`] /// * `init_flags` - List of flags sent to libbluetooth for init. /// * `hci_index` - Index of the hci adapter in use - pub fn initialize( - &mut self, - callbacks: BaseCallbacksDispatcher, - init_flags: Vec, - hci_index: i32, - ) -> bool { - // Init flags need to be converted from string to null terminated bytes - let converted: cxx::UniquePtr = ffi::ConvertFlags(init_flags); - let flags = (*converted).GetFlagsPtr(); - + pub fn initialize(&mut self, callbacks: BaseCallbacksDispatcher, hci_index: i32) -> bool { if get_dispatchers().lock().unwrap().set::(Arc::new(Mutex::new(callbacks))) { panic!("Tried to set dispatcher for BaseCallbacks but it already existed"); } @@ -1286,7 +1263,7 @@ impl BluetoothInterface { guest_mode, is_common_criteria_mode, config_compare_result, - flags, + std::ptr::null_mut(), is_atv, std::ptr::null() ); -- GitLab From 41ed374f0750e7976f81b35ae7b94877dd4b0ea7 Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Mon, 30 Sep 2024 14:04:50 +0000 Subject: [PATCH 094/875] Remove leaudio_multiple_vocs_instances_api flag Bug: 322779934 Bug: 323156655 Test: atest VolumeControlServiceTest BluetoothVolumeControlTest Change-Id: I6ee66a2d094bf009085ec06be360ecb5aabb0a0a --- .../bluetooth/vc/VolumeControlService.java | 50 ++++++++----------- .../vc/VolumeControlServiceTest.java | 2 - framework/api/system-current.txt | 10 ++-- .../bluetooth/BluetoothVolumeControl.java | 9 +--- framework/lint-baseline.xml | 44 ---------------- 5 files changed, 28 insertions(+), 87 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index be358982c7e..a7de3ae84a4 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -635,10 +635,8 @@ public class VolumeControlService extends ProfileService { + (", description: " + description)); try { callback.onVolumeOffsetChanged(device, id, offset); - if (Flags.leaudioMultipleVocsInstancesApi()) { - callback.onVolumeOffsetAudioLocationChanged(device, id, location); - callback.onVolumeOffsetAudioDescriptionChanged(device, id, description); - } + callback.onVolumeOffsetAudioLocationChanged(device, id, location); + callback.onVolumeOffsetAudioDescriptionChanged(device, id, description); } catch (RemoteException e) { // Dead client -- continue } @@ -1048,20 +1046,18 @@ public class VolumeControlService extends ProfileService { } offsets.setLocation(id, location); - if (Flags.leaudioMultipleVocsInstancesApi()) { - synchronized (mCallbacks) { - int n = mCallbacks.beginBroadcast(); - for (int i = 0; i < n; i++) { - try { - mCallbacks - .getBroadcastItem(i) - .onVolumeOffsetAudioLocationChanged(device, id, location); - } catch (RemoteException e) { - continue; - } + synchronized (mCallbacks) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks + .getBroadcastItem(i) + .onVolumeOffsetAudioLocationChanged(device, id, location); + } catch (RemoteException e) { + continue; } - mCallbacks.finishBroadcast(); } + mCallbacks.finishBroadcast(); } } @@ -1076,20 +1072,18 @@ public class VolumeControlService extends ProfileService { } offsets.setDescription(id, description); - if (Flags.leaudioMultipleVocsInstancesApi()) { - synchronized (mCallbacks) { - int n = mCallbacks.beginBroadcast(); - for (int i = 0; i < n; i++) { - try { - mCallbacks - .getBroadcastItem(i) - .onVolumeOffsetAudioDescriptionChanged(device, id, description); - } catch (RemoteException e) { - continue; - } + synchronized (mCallbacks) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks + .getBroadcastItem(i) + .onVolumeOffsetAudioDescriptionChanged(device, id, description); + } catch (RemoteException e) { + continue; } - mCallbacks.finishBroadcast(); } + mCallbacks.finishBroadcast(); } } 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 e9588adb0c0..e08a4b182f8 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 @@ -1177,8 +1177,6 @@ public class VolumeControlServiceTest { @Test public void testServiceBinderRegisterCallbackWhenDeviceAlreadyConnected() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_MULTIPLE_VOCS_INSTANCES_API); - int groupId = 1; int groupVolume = 56; diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 783635e7d45..5362b5e3f20 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -1118,23 +1118,23 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List getDevicesMatchingConnectionStates(int[]); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_multiple_vocs_instances_api") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getNumberOfVolumeOffsetInstances(@NonNull android.bluetooth.BluetoothDevice); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getNumberOfVolumeOffsetInstances(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isVolumeOffsetAvailable(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothVolumeControl.Callback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_volume_control_for_connected_devices") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setDeviceVolume(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int, boolean); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolumeOffset(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0xffffff01, to=255) int); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_multiple_vocs_instances_api") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolumeOffset(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolumeOffset(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull android.bluetooth.BluetoothVolumeControl.Callback); field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED"; } public static interface BluetoothVolumeControl.Callback { method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_volume_control_for_connected_devices") public default void onDeviceVolumeChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_multiple_vocs_instances_api") public default void onVolumeOffsetAudioDescriptionChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @NonNull String); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_multiple_vocs_instances_api") public default void onVolumeOffsetAudioLocationChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); + method public default void onVolumeOffsetAudioDescriptionChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @NonNull String); + method public default void onVolumeOffsetAudioLocationChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); method @Deprecated public default void onVolumeOffsetChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0xffffff01, to=255) int); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_multiple_vocs_instances_api") public default void onVolumeOffsetChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); + method public default void onVolumeOffsetChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); } public final class BufferConstraint implements android.os.Parcelable { diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index a27992a3ca7..4d8c4b2a6ac 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -108,7 +108,6 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose * @param volumeOffset latest volume offset for this VOCS instance * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MULTIPLE_VOCS_INSTANCES_API) @SystemApi default void onVolumeOffsetChanged( @NonNull BluetoothDevice device, @@ -128,7 +127,6 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose * @param audioLocation latest audio location for this VOCS instance * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MULTIPLE_VOCS_INSTANCES_API) @SystemApi default void onVolumeOffsetAudioLocationChanged( @NonNull BluetoothDevice device, @@ -144,7 +142,6 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose * @param audioDescription latest audio description for this VOCS instance * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MULTIPLE_VOCS_INSTANCES_API) @SystemApi default void onVolumeOffsetAudioDescriptionChanged( @NonNull BluetoothDevice device, @@ -189,9 +186,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose public void onVolumeOffsetChanged( @NonNull BluetoothDevice device, int instanceId, int volumeOffset) { Attributable.setAttributionSource(device, mAttributionSource); - if (Flags.leaudioMultipleVocsInstancesApi()) { - forEach((cb) -> cb.onVolumeOffsetChanged(device, instanceId, volumeOffset)); - } + forEach((cb) -> cb.onVolumeOffsetChanged(device, instanceId, volumeOffset)); } @Override @@ -547,7 +542,6 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose * @param volumeOffset volume offset to be set on VOCS instance * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MULTIPLE_VOCS_INSTANCES_API) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission( @@ -650,7 +644,6 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose * @return number of VOCS instances. When Bluetooth is off, the return value is 0. * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MULTIPLE_VOCS_INSTANCES_API) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission( diff --git a/framework/lint-baseline.xml b/framework/lint-baseline.xml index 6ad73e7c9c4..b87c402f980 100644 --- a/framework/lint-baseline.xml +++ b/framework/lint-baseline.xml @@ -276,28 +276,6 @@ column="18"/> - - - - - - - - - - - - - - - - Date: Mon, 30 Sep 2024 14:24:31 +0000 Subject: [PATCH 095/875] fix for BT crash caused by factoryReset pandora API. clearBluetooth() was called when HFP is in `CONNECTING` state leads to BT Crash. Bug: 366643930 Test: atest avatar Flag: TEST_ONLY Change-Id: Ia71f922bc6020e6aa176fba97b09d002bba0149c --- android/pandora/server/src/Host.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/android/pandora/server/src/Host.kt b/android/pandora/server/src/Host.kt index 38cbb7e3b89..185bde86cfc 100644 --- a/android/pandora/server/src/Host.kt +++ b/android/pandora/server/src/Host.kt @@ -21,6 +21,7 @@ import android.bluetooth.BluetoothAssignedNumbers import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothDevice.ADDRESS_TYPE_PUBLIC import android.bluetooth.BluetoothDevice.BOND_BONDED +import android.bluetooth.BluetoothDevice.BOND_NONE import android.bluetooth.BluetoothDevice.TRANSPORT_BREDR import android.bluetooth.BluetoothDevice.TRANSPORT_LE import android.bluetooth.BluetoothManager @@ -166,6 +167,15 @@ class Host( // remove bond for each device to avoid auto connection if remote resets faster for (device in bluetoothAdapter.bondedDevices) { device.removeBond() + Log.i(TAG, "wait for remove bond to complete : device=$device") + flow + .filter { it.action == BluetoothDevice.ACTION_BOND_STATE_CHANGED } + .filter { it.getBluetoothDeviceExtra() == device } + .map { + it.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothAdapter.ERROR) + } + .filter { it == BOND_NONE } + .first() } val stateFlow = -- GitLab From 1faa8d4cf1122162912150b2a5d4d3b1609bbbf7 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 25 Sep 2024 23:47:54 +0000 Subject: [PATCH 096/875] system/bta/av: Fix -Wmissing-prototypes errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor fixes Change-Id: Ia8e80b055d1a948239951d3bd5b313ff71778b44 --- system/bta/av/bta_av_aact.cc | 9 +++------ system/bta/av/bta_av_act.cc | 17 +++++++---------- system/bta/av/bta_av_cfg.cc | 6 ++---- system/bta/av/bta_av_ci.cc | 5 ++--- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index 66aef9a8e6a..739fd2b3861 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -61,9 +61,6 @@ #include "types/hci_role.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; namespace { @@ -3003,7 +3000,7 @@ void bta_av_open_at_inc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { } } -void offload_vendor_callback(tBTM_VSC_CMPL* param) { +static void offload_vendor_callback(tBTM_VSC_CMPL* param) { tBTA_AV value{0}; uint8_t sub_opcode = 0; if (param->param_len) { @@ -3041,7 +3038,7 @@ void offload_vendor_callback(tBTM_VSC_CMPL* param) { } } -void bta_av_vendor_offload_start(tBTA_AV_SCB* p_scb, tBT_A2DP_OFFLOAD* offload_start) { +static void bta_av_vendor_offload_start(tBTA_AV_SCB* p_scb, tBT_A2DP_OFFLOAD* offload_start) { uint8_t param[sizeof(tBT_A2DP_OFFLOAD)]; log::verbose(""); @@ -3072,7 +3069,7 @@ void bta_av_vendor_offload_start(tBTA_AV_SCB* p_scb, tBT_A2DP_OFFLOAD* offload_s param, offload_vendor_callback); } -void bta_av_vendor_offload_start_v2(tBTA_AV_SCB* p_scb, A2dpCodecConfigExt* offload_codec) { +static void bta_av_vendor_offload_start_v2(tBTA_AV_SCB* p_scb, A2dpCodecConfigExt* offload_codec) { log::verbose(""); uint16_t connection_handle = get_btm_client_interface().peer.BTM_GetHCIConnHandle( diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc index a82211fd47a..ed475e065a9 100644 --- a/system/bta/av/bta_av_act.cc +++ b/system/bta/av/bta_av_act.cc @@ -49,9 +49,6 @@ #include "stack/include/sdp_status.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; @@ -828,7 +825,7 @@ static tAVRC_STS bta_av_chk_notif_evt_id(tAVRC_MSG_VENDOR* p_vendor) { return status; } -void bta_av_proc_rsp(tAVRC_RESPONSE* p_rc_rsp) { +static void bta_av_proc_rsp(tAVRC_RESPONSE* p_rc_rsp) { uint16_t rc_ver = 0x105; const tBTA_AV_CFG* p_src_cfg = NULL; if (rc_ver != 0x103) { @@ -862,8 +859,8 @@ void bta_av_proc_rsp(tAVRC_RESPONSE* p_rc_rsp) { * Returns true to respond immediately * ******************************************************************************/ -tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE* p_rc_rsp, tBTA_AV_RC_MSG* p_msg, - uint8_t* p_ctype) { +static tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE* p_rc_rsp, tBTA_AV_RC_MSG* p_msg, + uint8_t* p_ctype) { tBTA_AV_EVT evt = BTA_AV_META_MSG_EVT; uint8_t u8, pdu, *p; uint16_t u16; @@ -1785,7 +1782,7 @@ static void bta_av_store_peer_rc_version() { * Returns tBTA_AV_FEAT peer device feature mask * ******************************************************************************/ -tBTA_AV_FEAT bta_av_check_peer_features(uint16_t service_uuid) { +static tBTA_AV_FEAT bta_av_check_peer_features(uint16_t service_uuid) { tBTA_AV_FEAT peer_features = 0; tBTA_AV_CB* p_cb = &bta_av_cb; tSDP_DISC_REC* p_rec = NULL; @@ -1860,7 +1857,7 @@ tBTA_AV_FEAT bta_av_check_peer_features(uint16_t service_uuid) { * Returns tBTA_AV_FEAT peer device feature mask * ******************************************************************************/ -tBTA_AV_FEAT bta_avk_check_peer_features(uint16_t service_uuid) { +static tBTA_AV_FEAT bta_avk_check_peer_features(uint16_t service_uuid) { tBTA_AV_FEAT peer_features = 0; tBTA_AV_CB* p_cb = &bta_av_cb; @@ -1949,7 +1946,7 @@ tBTA_AV_FEAT bta_avk_check_peer_features(uint16_t service_uuid) { * one does not exist. * *****************************************************************************/ -uint16_t bta_avk_get_cover_art_psm() { +static uint16_t bta_avk_get_cover_art_psm() { log::verbose("searching for cover art psm"); /* Cover Art L2CAP PSM is only available on a target device */ tBTA_AV_CB* p_cb = &bta_av_cb; @@ -2031,7 +2028,7 @@ uint16_t bta_avk_get_cover_art_psm() { return 0x0000; } -void bta_av_rc_disc_done_all(tBTA_AV_DATA* /* p_data */) { +static void bta_av_rc_disc_done_all(tBTA_AV_DATA* /* p_data */) { tBTA_AV_CB* p_cb = &bta_av_cb; tBTA_AV_SCB* p_scb = NULL; tBTA_AV_LCB* p_lcb; diff --git a/system/bta/av/bta_av_cfg.cc b/system/bta/av/bta_av_cfg.cc index 87ecee4568e..f420ddba5bc 100644 --- a/system/bta/av/bta_av_cfg.cc +++ b/system/bta/av/bta_av_cfg.cc @@ -27,6 +27,7 @@ #include +#include "bta/av/bta_av_int.h" #include "bta/include/bta_av_api.h" #include "internal_include/bt_target.h" #include "stack/include/avrc_api.h" @@ -39,9 +40,6 @@ #define BTA_AV_RC_PASS_RSP_CODE AVRC_RSP_NOT_IMPL #endif -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; const uint32_t bta_av_meta_caps_co_ids[] = {AVRC_CO_METADATA, AVRC_CO_BROADCOM}; @@ -97,7 +95,7 @@ const uint8_t bta_av_meta_caps_evt_ids[] = { (sizeof(bta_av_meta_caps_evt_ids) / sizeof(bta_av_meta_caps_evt_ids[0])) #endif /* BTA_AV_NUM_RC_EVT_IDS */ -const uint8_t* get_bta_avk_meta_caps_evt_ids() { +static const uint8_t* get_bta_avk_meta_caps_evt_ids() { if (avrcp_absolute_volume_is_enabled()) { static const uint8_t bta_avk_meta_caps_evt_ids[] = { AVRC_EVT_VOLUME_CHANGE, diff --git a/system/bta/av/bta_av_ci.cc b/system/bta/av/bta_av_ci.cc index e7bddf4b1f4..2fa1afb0799 100644 --- a/system/bta/av/bta_av_ci.cc +++ b/system/bta/av/bta_av_ci.cc @@ -25,6 +25,8 @@ #define LOG_TAG "bluetooth-a2dp" +#include "bta/include/bta_av_ci.h" + #include #include "bta/av/bta_av_int.h" @@ -32,9 +34,6 @@ #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /******************************************************************************* -- GitLab From 76cdc9533a29a566c82318c75dd8edc09df56b47 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 26 Sep 2024 16:55:32 +0000 Subject: [PATCH 097/875] system/stack/avdt: Fix -Wmissing-prototypes errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor fixes Change-Id: I1ed61b827bfb4df16831fdacfa887ed5287a50d6 --- system/stack/avdt/avdt_int.h | 1 + system/stack/avdt/avdt_msg.cc | 5 +---- system/stack/avdt/avdt_scb_act.cc | 5 +---- system/stack/test/stack_avdtp_test.cc | 1 - 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/system/stack/avdt/avdt_int.h b/system/stack/avdt/avdt_int.h index 6b2b354b062..c1f29110dc2 100644 --- a/system/stack/avdt/avdt_int.h +++ b/system/stack/avdt/avdt_int.h @@ -884,6 +884,7 @@ void avdt_scb_hdl_open_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); void avdt_scb_hdl_open_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); void avdt_scb_hdl_open_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); void avdt_scb_hdl_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); +void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); void avdt_scb_drop_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); void avdt_scb_hdl_reconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); void avdt_scb_hdl_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); diff --git a/system/stack/avdt/avdt_msg.cc b/system/stack/avdt/avdt_msg.cc index 28535033d2c..d8d52693405 100644 --- a/system/stack/avdt/avdt_msg.cc +++ b/system/stack/avdt/avdt_msg.cc @@ -41,9 +41,6 @@ #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -1176,7 +1173,7 @@ bool avdt_msg_send(AvdtpCcb* p_ccb, BT_HDR* p_msg) { * available. * ******************************************************************************/ -BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) { +static BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) { uint8_t* p; uint8_t pkt_type; BT_HDR* p_ret; diff --git a/system/stack/avdt/avdt_scb_act.cc b/system/stack/avdt/avdt_scb_act.cc index 4eec721d465..d16f963ab13 100644 --- a/system/stack/avdt/avdt_scb_act.cc +++ b/system/stack/avdt/avdt_scb_act.cc @@ -39,9 +39,6 @@ #include "stack/include/l2cap_interface.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /* This table is used to lookup the callback event that matches a particular @@ -309,7 +306,7 @@ length_error: * Returns Nothing. * ******************************************************************************/ -uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { +static uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) { uint16_t result = AVDT_SUCCESS; uint8_t* p_start = p; uint32_t ssrc; diff --git a/system/stack/test/stack_avdtp_test.cc b/system/stack/test/stack_avdtp_test.cc index 651eea12c1b..3ecc82f0505 100644 --- a/system/stack/test/stack_avdtp_test.cc +++ b/system/stack/test/stack_avdtp_test.cc @@ -310,7 +310,6 @@ TEST_F(StackAvdtpTest, test_SDES_reporting_handler) { ASSERT_EQ(get_func_call_count("AvdtReportCallback"), 1); } -void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data); // regression tests for b/258057241 (CVE-2022-40503) // The regression tests are divided into 2 tests: // avdt_scb_hdl_pkt_no_frag_regression_test1 verifies that -- GitLab From 831f837b2c1a31ddec716d22cc5ca8291061723e Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 26 Sep 2024 17:13:22 +0000 Subject: [PATCH 098/875] system/btif/src: Fix -Wmissing-prototypes errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor fixes Change-Id: I0c744366ac688d7ebd0ed20e359ebfeadab1a2b3 --- system/bta/av/bta_av_act.cc | 8 +------ system/btif/include/btif_av.h | 4 ++-- system/btif/src/btif_a2dp_source.cc | 8 +++---- system/btif/src/btif_av.cc | 15 ++++-------- system/btif/test/btif_core_test.cc | 36 ----------------------------- system/test/mock/mock_btif_av.cc | 6 ----- system/test/mock/mock_btif_av.h | 10 -------- 7 files changed, 10 insertions(+), 77 deletions(-) diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc index ed475e065a9..fdc2cfcb981 100644 --- a/system/bta/av/bta_av_act.cc +++ b/system/bta/av/bta_av_act.cc @@ -33,6 +33,7 @@ #include "bta/include/bta_ar_api.h" #include "bta/include/utl.h" #include "btif/avrcp/avrcp_service.h" +#include "btif/include/btif_av.h" #include "device/include/device_iot_config.h" #include "device/include/interop.h" #include "internal_include/bt_target.h" @@ -72,13 +73,6 @@ static void bta_av_accept_signalling_timer_cback(void* data); #define AVRC_MIN_META_CMD_LEN 20 #endif -extern bool btif_av_is_source_enabled(void); -extern bool btif_av_both_enable(void); -extern bool btif_av_src_sink_coexist_enabled(void); -extern bool btif_av_is_sink_enabled(void); -extern bool btif_av_peer_is_connected_sink(const RawAddress& peer_address); -extern const RawAddress& btif_av_find_by_handle(tBTA_AV_HNDL bta_handle); - /******************************************************************************* * * Function bta_av_get_rcb_by_shdl diff --git a/system/btif/include/btif_av.h b/system/btif/include/btif_av.h index b8f4d4e7f71..ca04f2c4f22 100644 --- a/system/btif/include/btif_av.h +++ b/system/btif/include/btif_av.h @@ -26,6 +26,7 @@ #include #include +#include "bta/include/bta_av_api.h" #include "include/hardware/bt_av.h" #include "types/raw_address.h" @@ -288,13 +289,12 @@ void btif_av_connect_sink_delayed(uint8_t handle, const RawAddress& peer_address /** * Check whether A2DP Source is enabled. */ -bool btif_av_is_source_enabled(void); bool btif_av_both_enable(void); bool btif_av_src_sink_coexist_enabled(void); -bool btif_av_is_sink_enabled(void); bool btif_av_peer_is_connected_sink(const RawAddress& peer_address); bool btif_av_peer_is_connected_source(const RawAddress& peer_address); bool btif_av_peer_is_sink(const RawAddress& peer_address); bool btif_av_peer_is_source(const RawAddress& peer_address); +const RawAddress& btif_av_find_by_handle(tBTA_AV_HNDL bta_handle); #endif /* BTIF_AV_H */ diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 6f925864199..2ca83110878 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -54,9 +54,6 @@ #include "stack/include/btm_status.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::audio::a2dp::BluetoothAudioStatus; using bluetooth::common::A2dpSessionMetrics; using bluetooth::common::BluetoothMetricsLogger; @@ -269,7 +266,8 @@ static void btm_read_rssi_cb(void* data); static void btm_read_failed_contact_counter_cb(void* data); static void btm_read_tx_power_cb(void* data); -void btif_a2dp_source_accumulate_scheduling_stats(SchedulingStats* src, SchedulingStats* dst) { +static void btif_a2dp_source_accumulate_scheduling_stats(SchedulingStats* src, + SchedulingStats* dst) { dst->total_updates += src->total_updates; dst->last_update_us = src->last_update_us; dst->overdue_scheduling_count += src->overdue_scheduling_count; @@ -284,7 +282,7 @@ void btif_a2dp_source_accumulate_scheduling_stats(SchedulingStats* src, Scheduli dst->total_scheduling_time_us += src->total_scheduling_time_us; } -void btif_a2dp_source_accumulate_stats(BtifMediaStats* src, BtifMediaStats* dst) { +static void btif_a2dp_source_accumulate_stats(BtifMediaStats* src, BtifMediaStats* dst) { dst->tx_queue_total_frames += src->tx_queue_total_frames; dst->tx_queue_max_frames_per_packet = std::max(dst->tx_queue_max_frames_per_packet, src->tx_queue_max_frames_per_packet); diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 57fb6dd073c..44d799394bf 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -67,9 +67,6 @@ #include #endif -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -885,7 +882,7 @@ const RawAddress& btif_av_find_by_handle(tBTA_AV_HNDL bta_handle) { * Local helper functions *****************************************************************************/ -const char* dump_av_sm_event_name(btif_av_sm_event_t event) { +static const char* dump_av_sm_event_name(btif_av_sm_event_t event) { switch (static_cast(event)) { CASE_RETURN_STR(BTA_AV_ENABLE_EVT) CASE_RETURN_STR(BTA_AV_REGISTER_EVT) @@ -929,10 +926,6 @@ const char* dump_av_sm_event_name(btif_av_sm_event_t event) { } } -const char* dump_av_sm_event_name(int event) { - return dump_av_sm_event_name(static_cast(event)); -} - BtifAvEvent::BtifAvEvent(uint32_t event, const void* p_data, size_t data_length) : event_(event), data_(nullptr), data_length_(0) { DeepCopy(event, p_data, data_length); @@ -953,7 +946,7 @@ BtifAvEvent::~BtifAvEvent() { DeepFree(); } std::string BtifAvEvent::ToString() const { return BtifAvEvent::EventName(event_); } std::string BtifAvEvent::EventName(uint32_t event) { - std::string name = dump_av_sm_event_name((btif_av_sm_event_t)event); + std::string name = dump_av_sm_event_name(static_cast(event)); std::stringstream ss_value; ss_value << "(0x" << std::hex << event << ")"; return name + ss_value.str(); @@ -3298,7 +3291,7 @@ static void btif_av_handle_bta_av_event(uint8_t peer_sep, const BtifAvEvent& bti bool btif_av_both_enable(void) { return btif_av_sink.Enabled() && btif_av_source.Enabled(); } -bool is_a2dp_source_property_enabled(void) { +static bool is_a2dp_source_property_enabled(void) { #ifdef __ANDROID__ return android::sysprop::BluetoothProperties::isProfileA2dpSourceEnabled().value_or(false); #else @@ -3306,7 +3299,7 @@ bool is_a2dp_source_property_enabled(void) { #endif } -bool is_a2dp_sink_property_enabled(void) { +static bool is_a2dp_sink_property_enabled(void) { #ifdef __ANDROID__ return android::sysprop::BluetoothProperties::isProfileA2dpSinkEnabled().value_or(false); #else diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc index 16125b4e803..bfd49059195 100644 --- a/system/btif/test/btif_core_test.cc +++ b/system/btif/test/btif_core_test.cc @@ -293,42 +293,6 @@ TEST_F(BtifCoreTest, test_post_on_bt_jni_simple3) { ASSERT_EQ(val, future.get()); } -extern const char* dump_av_sm_event_name(int event); -TEST_F(BtifUtilsTest, dump_av_sm_event_name) { - std::vector> events = { - std::make_pair(BTA_AV_ENABLE_EVT, "BTA_AV_ENABLE_EVT"), - std::make_pair(BTA_AV_REGISTER_EVT, "BTA_AV_REGISTER_EVT"), - std::make_pair(BTA_AV_OPEN_EVT, "BTA_AV_OPEN_EVT"), - std::make_pair(BTA_AV_CLOSE_EVT, "BTA_AV_CLOSE_EVT"), - std::make_pair(BTA_AV_START_EVT, "BTA_AV_START_EVT"), - std::make_pair(BTA_AV_STOP_EVT, "BTA_AV_STOP_EVT"), - std::make_pair(BTA_AV_PROTECT_REQ_EVT, "BTA_AV_PROTECT_REQ_EVT"), - std::make_pair(BTA_AV_PROTECT_RSP_EVT, "BTA_AV_PROTECT_RSP_EVT"), - std::make_pair(BTA_AV_RC_OPEN_EVT, "BTA_AV_RC_OPEN_EVT"), - std::make_pair(BTA_AV_RC_CLOSE_EVT, "BTA_AV_RC_CLOSE_EVT"), - std::make_pair(BTA_AV_RC_BROWSE_OPEN_EVT, "BTA_AV_RC_BROWSE_OPEN_EVT"), - std::make_pair(BTA_AV_RC_BROWSE_CLOSE_EVT, "BTA_AV_RC_BROWSE_CLOSE_EVT"), - std::make_pair(BTA_AV_REMOTE_CMD_EVT, "BTA_AV_REMOTE_CMD_EVT"), - std::make_pair(BTA_AV_REMOTE_RSP_EVT, "BTA_AV_REMOTE_RSP_EVT"), - std::make_pair(BTA_AV_VENDOR_CMD_EVT, "BTA_AV_VENDOR_CMD_EVT"), - std::make_pair(BTA_AV_VENDOR_RSP_EVT, "BTA_AV_VENDOR_RSP_EVT"), - std::make_pair(BTA_AV_RECONFIG_EVT, "BTA_AV_RECONFIG_EVT"), - std::make_pair(BTA_AV_SUSPEND_EVT, "BTA_AV_SUSPEND_EVT"), - std::make_pair(BTA_AV_PENDING_EVT, "BTA_AV_PENDING_EVT"), - std::make_pair(BTA_AV_META_MSG_EVT, "BTA_AV_META_MSG_EVT"), - std::make_pair(BTA_AV_REJECT_EVT, "BTA_AV_REJECT_EVT"), - std::make_pair(BTA_AV_RC_FEAT_EVT, "BTA_AV_RC_FEAT_EVT"), - std::make_pair(BTA_AV_RC_PSM_EVT, "BTA_AV_RC_PSM_EVT"), - std::make_pair(BTA_AV_OFFLOAD_START_RSP_EVT, "BTA_AV_OFFLOAD_START_RSP_EVT"), - }; - for (const auto& event : events) { - ASSERT_EQ(event.second, dump_av_sm_event_name(event.first)); - } - std::ostringstream oss; - oss << "UNKNOWN_EVENT"; - ASSERT_EQ(oss.str(), dump_av_sm_event_name(std::numeric_limits::max())); -} - TEST_F(BtifUtilsTest, dump_dm_search_event) { std::vector> events = { std::make_pair(BTA_DM_INQ_RES_EVT, "BTA_DM_INQ_RES_EVT"), diff --git a/system/test/mock/mock_btif_av.cc b/system/test/mock/mock_btif_av.cc index 9b4a7065720..560c5e1a781 100644 --- a/system/test/mock/mock_btif_av.cc +++ b/system/test/mock/mock_btif_av.cc @@ -76,7 +76,6 @@ struct btif_av_stream_started_ready btif_av_stream_started_ready; struct btif_av_stream_stop btif_av_stream_stop; struct btif_av_stream_suspend btif_av_stream_suspend; struct btif_debug_av_dump btif_debug_av_dump; -struct dump_av_sm_event_name dump_av_sm_event_name; } // namespace btif_av } // namespace mock @@ -111,7 +110,6 @@ bt_status_t btif_av_source_execute_service::return_value = BT_STATUS_SUCCESS; bool btif_av_src_sink_coexist_enabled::return_value = false; bool btif_av_stream_ready::return_value = false; bool btif_av_stream_started_ready::return_value = false; -const char* dump_av_sm_event_name::return_value = nullptr; } // namespace btif_av } // namespace mock @@ -268,9 +266,5 @@ void btif_debug_av_dump(int fd) { inc_func_call_count(__func__); test::mock::btif_av::btif_debug_av_dump(fd); } -const char* dump_av_sm_event_name(int event) { - inc_func_call_count(__func__); - return test::mock::btif_av::dump_av_sm_event_name(event); -} // Mocked functions complete // END mockcify generation diff --git a/system/test/mock/mock_btif_av.h b/system/test/mock/mock_btif_av.h index f95013c06fb..679c6679cd5 100644 --- a/system/test/mock/mock_btif_av.h +++ b/system/test/mock/mock_btif_av.h @@ -464,16 +464,6 @@ struct btif_debug_av_dump { }; extern struct btif_debug_av_dump btif_debug_av_dump; -// Name: dump_av_sm_event_name -// Params: int event -// Return: const char* -struct dump_av_sm_event_name { - static const char* return_value; - std::function body{[](int /* event */) { return return_value; }}; - const char* operator()(int event) { return body(event); } -}; -extern struct dump_av_sm_event_name dump_av_sm_event_name; - } // namespace btif_av } // namespace mock } // namespace test -- GitLab From 7802b148b99f9b6b2ac8c896c44138f71f4d0fc6 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 26 Sep 2024 23:10:11 +0000 Subject: [PATCH 099/875] system/audio_hal_interface: Fix -Wmissing-prototypes errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor fixes Change-Id: I17cfac8328d8028fb25f7a37624b8dcc7d438eee --- .../aidl/hfp_client_interface_aidl.cc | 7 ++--- .../aidl/le_audio_software_aidl.cc | 7 ++--- .../aidl/le_audio_utils.cc | 14 ++++----- .../audio_hal_interface/aidl/provider_info.cc | 5 +--- .../hal_version_manager.cc | 3 -- .../audio_hal_interface/hal_version_manager.h | 3 ++ .../hfp_client_interface.cc | 29 ++++++++++--------- .../hfp_client_interface_unittest.cc | 7 ----- .../hidl/client_interface_hidl_unittest.cc | 13 ++++----- .../audio_hal_interface/le_audio_software.cc | 9 ++---- .../le_audio_software_host.cc | 5 ---- .../le_audio_software_unittest.cc | 7 ----- 12 files changed, 37 insertions(+), 72 deletions(-) diff --git a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc index 76a86bda8da..b35cda1746c 100644 --- a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc @@ -32,9 +32,6 @@ #include "provider_info.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace bluetooth { namespace audio { namespace aidl { @@ -49,7 +46,7 @@ std::map status_to_ack_map = { {BT_STATUS_UNSUPPORTED, BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED}, }; -std::string command_to_text(tHFP_CTRL_CMD cmd) { +static std::string command_to_text(tHFP_CTRL_CMD cmd) { switch (cmd) { case HFP_CTRL_CMD_NONE: return "none"; @@ -74,7 +71,7 @@ std::string command_to_text(tHFP_CTRL_CMD cmd) { } } -tBTA_AG_SCB* get_hfp_active_device_callback() { +static tBTA_AG_SCB* get_hfp_active_device_callback() { const RawAddress& addr = bta_ag_get_active_device(); if (addr.IsEmpty()) { log::error("No active device found"); 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 304f2908988..72ebc9ecb36 100644 --- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc +++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc @@ -31,9 +31,6 @@ #include "hal_version_manager.h" #include "os/log.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace bluetooth { namespace audio { namespace aidl { @@ -587,8 +584,8 @@ bool hal_ucast_capability_to_stack_format(const UnicastCapability& hal_capabilit return true; } -bool hal_bcast_capability_to_stack_format(const BroadcastCapability& hal_bcast_capability, - CodecConfigSetting& stack_capability) { +static bool hal_bcast_capability_to_stack_format(const BroadcastCapability& hal_bcast_capability, + CodecConfigSetting& stack_capability) { if (hal_bcast_capability.codecType != CodecType::LC3) { log::warn("Unsupported codecType: {}", toString(hal_bcast_capability.codecType)); return false; diff --git a/system/audio_hal_interface/aidl/le_audio_utils.cc b/system/audio_hal_interface/aidl/le_audio_utils.cc index cd1b2964a7d..b24e89a3752 100644 --- a/system/audio_hal_interface/aidl/le_audio_utils.cc +++ b/system/audio_hal_interface/aidl/le_audio_utils.cc @@ -22,9 +22,6 @@ #include "hardware/bt_le_audio.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace bluetooth { namespace audio { namespace aidl { @@ -81,7 +78,7 @@ namespace aidl { return codec; } -std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv> +static std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv> GetAidlCodecCapabilitiesFromStack(const ::bluetooth::le_audio::types::LeAudioLtvMap& in) { std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv> ltvs; auto stack_caps = in.GetAsCoreCodecCapabilities(); @@ -409,7 +406,7 @@ GetStackBroadcastConfigurationFromAidlFormat( return std::move(cfg); } -::bluetooth::le_audio::set_configurations::QosConfigSetting GetStackQosConfigSettingFromAidl( +static ::bluetooth::le_audio::set_configurations::QosConfigSetting GetStackQosConfigSettingFromAidl( const std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseQosConfiguration>& aidl_qos, ::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration::TargetLatency @@ -426,7 +423,7 @@ GetStackBroadcastConfigurationFromAidlFormat( return config; } -::bluetooth::le_audio::set_configurations::CodecConfigSetting GetCodecConfigSettingFromAidl( +static ::bluetooth::le_audio::set_configurations::CodecConfigSetting GetCodecConfigSettingFromAidl( const std::optional<::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration>& ase_config) { auto stack_config = ::bluetooth::le_audio::set_configurations::CodecConfigSetting(); @@ -496,7 +493,7 @@ GetStackBroadcastConfigurationFromAidlFormat( // The number of source entries is the total count of ASEs within the group to // be configured -::bluetooth::le_audio::set_configurations::AseConfiguration GetStackAseConfigurationFromAidl( +static ::bluetooth::le_audio::set_configurations::AseConfiguration GetStackAseConfigurationFromAidl( const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseConfigurationSetting::AseDirectionConfiguration& source) { auto stack_qos = GetStackQosConfigSettingFromAidl(source.qosConfiguration, @@ -510,7 +507,8 @@ GetStackBroadcastConfigurationFromAidlFormat( return config; } -::bluetooth::le_audio::set_configurations::AudioSetConfiguration GetStackConfigSettingFromAidl( +static ::bluetooth::le_audio::set_configurations::AudioSetConfiguration +GetStackConfigSettingFromAidl( ::bluetooth::le_audio::types::LeAudioContextType ctx_type, const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseConfigurationSetting& aidl_ase_config) { diff --git a/system/audio_hal_interface/aidl/provider_info.cc b/system/audio_hal_interface/aidl/provider_info.cc index c93e545b09e..3b51bf4103b 100644 --- a/system/audio_hal_interface/aidl/provider_info.cc +++ b/system/audio_hal_interface/aidl/provider_info.cc @@ -25,15 +25,12 @@ #include "client_interface_aidl.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace bluetooth::audio::aidl { using ::aidl::android::hardware::bluetooth::audio::CodecId; using ::aidl::android::hardware::bluetooth::audio::CodecInfo; using ::aidl::android::hardware::bluetooth::audio::SessionType; -::hfp::sco_config recordHfpCodecInfo(CodecInfo codecInfo) { +static ::hfp::sco_config recordHfpCodecInfo(CodecInfo codecInfo) { auto hfp_transport = codecInfo.transport.get(); ::hfp::sco_config config{ .inputDataPath = hfp_transport.inputDataPath, diff --git a/system/audio_hal_interface/hal_version_manager.cc b/system/audio_hal_interface/hal_version_manager.cc index a085d21ce1d..19c48c58da2 100644 --- a/system/audio_hal_interface/hal_version_manager.cc +++ b/system/audio_hal_interface/hal_version_manager.cc @@ -26,9 +26,6 @@ #include "aidl/audio_aidl_interfaces.h" #include "os/log.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace bluetooth { namespace audio { diff --git a/system/audio_hal_interface/hal_version_manager.h b/system/audio_hal_interface/hal_version_manager.h index d19785f0782..51319958b4e 100644 --- a/system/audio_hal_interface/hal_version_manager.h +++ b/system/audio_hal_interface/hal_version_manager.h @@ -127,5 +127,8 @@ private: BluetoothAudioHalTransport hal_transport_; }; +// Return the supported AIDL version. +BluetoothAudioHalVersion GetAidlInterfaceVersion(); + } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index f554b96ae5d..9a61e6722b6 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -27,9 +27,6 @@ #include "os/log.h" #include "osi/include/properties.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using ::bluetooth::audio::aidl::hfp::HfpDecodingTransport; using ::bluetooth::audio::aidl::hfp::HfpEncodingTransport; using AudioConfiguration = ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; @@ -42,20 +39,23 @@ namespace bluetooth { namespace audio { namespace hfp { -// Helper functions -aidl::BluetoothAudioSourceClientInterface* get_decode_client_interface() { +static aidl::BluetoothAudioSourceClientInterface* get_decode_client_interface() { return HfpDecodingTransport::active_hal_interface; } -aidl::BluetoothAudioSinkClientInterface* get_encode_client_interface() { +static aidl::BluetoothAudioSinkClientInterface* get_encode_client_interface() { return HfpEncodingTransport::active_hal_interface; } -HfpDecodingTransport* get_decode_transport_instance() { return HfpDecodingTransport::instance_; } +static HfpDecodingTransport* get_decode_transport_instance() { + return HfpDecodingTransport::instance_; +} -HfpDecodingTransport* get_encode_transport_instance() { return HfpDecodingTransport::instance_; } +static HfpDecodingTransport* get_encode_transport_instance() { + return HfpDecodingTransport::instance_; +} -PcmConfiguration get_default_pcm_configuration() { +static PcmConfiguration get_default_pcm_configuration() { PcmConfiguration pcm_config{ .sampleRateHz = 8000, .channelMode = ChannelMode::MONO, @@ -65,7 +65,7 @@ PcmConfiguration get_default_pcm_configuration() { return pcm_config; } -HfpConfiguration get_default_hfp_configuration() { +static HfpConfiguration get_default_hfp_configuration() { HfpConfiguration hfp_config{ .codecId = CodecId::Core::CVSD, .connectionHandle = 6, @@ -75,7 +75,7 @@ HfpConfiguration get_default_hfp_configuration() { return hfp_config; } -CodecId sco_codec_to_hal_codec(tBTA_AG_UUID_CODEC sco_codec) { +static CodecId sco_codec_to_hal_codec(tBTA_AG_UUID_CODEC sco_codec) { switch (sco_codec) { case tBTA_AG_UUID_CODEC::UUID_CODEC_LC3: return CodecId::Core::LC3; @@ -90,7 +90,8 @@ CodecId sco_codec_to_hal_codec(tBTA_AG_UUID_CODEC sco_codec) { } } -AudioConfiguration offload_config_to_hal_audio_config(const ::hfp::offload_config& offload_config) { +static AudioConfiguration offload_config_to_hal_audio_config( + const ::hfp::offload_config& offload_config) { HfpConfiguration hfp_config{ .codecId = sco_codec_to_hal_codec(offload_config.sco_codec), .connectionHandle = offload_config.connection_handle, @@ -100,13 +101,13 @@ AudioConfiguration offload_config_to_hal_audio_config(const ::hfp::offload_confi return AudioConfiguration(hfp_config); } -AudioConfiguration pcm_config_to_hal_audio_config(const ::hfp::pcm_config& pcm_config) { +static AudioConfiguration pcm_config_to_hal_audio_config(const ::hfp::pcm_config& pcm_config) { PcmConfiguration config = get_default_pcm_configuration(); config.sampleRateHz = pcm_config.sample_rate_hz; return AudioConfiguration(config); } -bool is_aidl_support_hfp() { +static bool is_aidl_support_hfp() { return HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::AIDL && HalVersionManager::GetHalVersion() >= BluetoothAudioHalVersion::VERSION_AIDL_V4; } diff --git a/system/audio_hal_interface/hfp_client_interface_unittest.cc b/system/audio_hal_interface/hfp_client_interface_unittest.cc index 1013b25f505..64f31265bca 100644 --- a/system/audio_hal_interface/hfp_client_interface_unittest.cc +++ b/system/audio_hal_interface/hfp_client_interface_unittest.cc @@ -26,19 +26,12 @@ #include "aidl/transport_instance.h" #include "audio_hal_interface/hal_version_manager.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" #pragma GCC diagnostic ignored "-Wunused-private-field" using testing::Test; using bluetooth::audio::hfp::HfpClientInterface; -extern "C" { -struct android_namespace_t* android_get_exported_namespace(const char*) { return nullptr; } -void* android_load_sphal_library(const char* /*name*/, int /*flag*/) { return nullptr; } -} - // Mock bool bta_ag_get_sco_offload_enabled() { return true; } diff --git a/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc b/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc index 295ca5f2a64..13ed21c06f6 100644 --- a/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc +++ b/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc @@ -24,9 +24,6 @@ #include "codec_status_hidl.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace { using ::android::hardware::bluetooth::audio::V2_0::AacObjectType; @@ -380,7 +377,7 @@ struct CodecOffloadingPreference { std::vector preference_; }; -std::vector CodecOffloadingPreferenceGenerator( +static std::vector CodecOffloadingPreferenceGenerator( btav_a2dp_codec_index_t target_codec_index) { std::vector codec_offloading_preferences = { {.is_target_codec_included_ = false, @@ -402,7 +399,7 @@ std::vector CodecOffloadingPreferenceGenerator( return codec_offloading_preferences; } -std::vector SbcCodecConfigurationsGenerator() { +static std::vector SbcCodecConfigurationsGenerator() { std::vector sbc_codec_configs; CodecConfiguration codec_config = {}; SbcBlockLength block_lengths[4] = {SbcBlockLength::BLOCKS_4, SbcBlockLength::BLOCKS_8, @@ -478,7 +475,7 @@ TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadSbcSession) { } } -std::vector AacCodecConfigurationsGenerator() { +static std::vector AacCodecConfigurationsGenerator() { std::vector aac_codec_configs; CodecConfiguration codec_config = {}; AacObjectType object_types[4] = {AacObjectType::MPEG2_LC, AacObjectType::MPEG4_LC, @@ -546,7 +543,7 @@ TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAacSession) { } } -std::vector LdacCodecConfigurationsGenerator() { +static std::vector LdacCodecConfigurationsGenerator() { std::vector ldac_codec_configs; CodecConfiguration codec_config = {}; LdacQualityIndex quality_indexes[4] = { @@ -612,7 +609,7 @@ TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadLdacSession) { } } -std::vector AptxCodecConfigurationsGenerator(CodecType codec_type) { +static std::vector AptxCodecConfigurationsGenerator(CodecType codec_type) { std::vector aptx_codec_configs; if (codec_type != CodecType::APTX && codec_type != CodecType::APTX_HD) { return aptx_codec_configs; diff --git a/system/audio_hal_interface/le_audio_software.cc b/system/audio_hal_interface/le_audio_software.cc index bc16ae1352b..7061f865e68 100644 --- a/system/audio_hal_interface/le_audio_software.cc +++ b/system/audio_hal_interface/le_audio_software.cc @@ -34,9 +34,6 @@ #include "os/log.h" #include "osi/include/properties.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace bluetooth { namespace audio { @@ -70,7 +67,7 @@ OffloadCapabilities get_offload_capabilities() { return aidl::le_audio::get_offload_capabilities(); } -aidl::BluetoothAudioSinkClientInterface* get_aidl_client_interface(bool is_broadcaster) { +static aidl::BluetoothAudioSinkClientInterface* get_aidl_client_interface(bool is_broadcaster) { if (is_broadcaster) { return aidl::le_audio::LeAudioSinkTransport::interface_broadcast_; } @@ -78,7 +75,7 @@ aidl::BluetoothAudioSinkClientInterface* get_aidl_client_interface(bool is_broad return aidl::le_audio::LeAudioSinkTransport::interface_unicast_; } -aidl::le_audio::LeAudioSinkTransport* get_aidl_transport_instance(bool is_broadcaster) { +static aidl::le_audio::LeAudioSinkTransport* get_aidl_transport_instance(bool is_broadcaster) { if (is_broadcaster) { return aidl::le_audio::LeAudioSinkTransport::instance_broadcast_; } @@ -86,7 +83,7 @@ aidl::le_audio::LeAudioSinkTransport* get_aidl_transport_instance(bool is_broadc return aidl::le_audio::LeAudioSinkTransport::instance_unicast_; } -bool is_aidl_offload_encoding_session(bool is_broadcaster) { +static bool is_aidl_offload_encoding_session(bool is_broadcaster) { return get_aidl_client_interface(is_broadcaster)->GetTransportInstance()->GetSessionType() == aidl::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || get_aidl_client_interface(is_broadcaster)->GetTransportInstance()->GetSessionType() == diff --git a/system/audio_hal_interface/le_audio_software_host.cc b/system/audio_hal_interface/le_audio_software_host.cc index 268e3841576..cc8e561bfac 100644 --- a/system/audio_hal_interface/le_audio_software_host.cc +++ b/system/audio_hal_interface/le_audio_software_host.cc @@ -33,9 +33,6 @@ // TODO(b/198260375): Make LEA data owner group configurable. #define LEA_HOST_DATA_GROUP "bluetooth-audio" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; namespace { @@ -194,8 +191,6 @@ OffloadCapabilities get_offload_capabilities() { std::vector(0)}; } -int GetAidlInterfaceVersion() { return 0; } - void LeAudioClientInterface::Sink::Cleanup() { log::info(""); diff --git a/system/audio_hal_interface/le_audio_software_unittest.cc b/system/audio_hal_interface/le_audio_software_unittest.cc index dec62e6a5cd..fdf03dd65c1 100644 --- a/system/audio_hal_interface/le_audio_software_unittest.cc +++ b/system/audio_hal_interface/le_audio_software_unittest.cc @@ -31,8 +31,6 @@ #include "gmock/gmock.h" #include "hidl/le_audio_software_hidl.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" #pragma GCC diagnostic ignored "-Wunused-private-field" using testing::Return; @@ -41,11 +39,6 @@ using testing::Test; using bluetooth::audio::le_audio::LeAudioClientInterface; using bluetooth::audio::le_audio::StreamCallbacks; -extern "C" { -struct android_namespace_t* android_get_exported_namespace(const char*) { return nullptr; } -void* android_load_sphal_library(const char* /*name*/, int /*flag*/) { return nullptr; } -} - // MOCKS namespace { class MockHalVersionManager { -- GitLab From 85cc8f60dca123540ea29fa705a973c9b8a72004 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Thu, 26 Sep 2024 22:38:57 +0000 Subject: [PATCH 100/875] Do not send write requestif tcb is closed If tcb is closed, the mtu resets to 0. Although I couldn't find a exact path but gatt_send_write can be invoked after a tcb is closed. This change prevents this scenario by rejecting the request. Flag: strict bound check Bug: 365910287 Test: atest GattClientTest Change-Id: I1943dff545cba51bdc50a2d22dd335c1bdb5eaa6 --- .../src/android/bluetooth/GattClientTest.java | 28 +++++++++++++++++++ system/stack/gatt/gatt_cl.cc | 11 ++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java index 2af75c96625..dae16c604b3 100644 --- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java +++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java @@ -637,4 +637,32 @@ public class GattClientTest { // We should fail because we reached the limit. assertThat(failed).isTrue(); } + + @Test + public void writeCharacteristic_disconnected_shouldNotCrash() { + registerGattService(); + + BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); + + BluetoothGatt gatt = connectGattAndWaitConnection(gattCallback); + + try { + gatt.discoverServices(); + verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); + + BluetoothGattCharacteristic characteristic = + gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID); + + byte[] newValue = new byte[] {13}; + + gatt.writeCharacteristic( + characteristic, newValue, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); + // TODO(b/370607862): disconnect from the remote + gatt.disconnect(); + gatt.close(); + } finally { + // it's okay to close twice. + gatt.close(); + } + } } diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc index d0a7ae7c559..61fb47fa406 100644 --- a/system/stack/gatt/gatt_cl.cc +++ b/system/stack/gatt/gatt_cl.cc @@ -249,7 +249,7 @@ void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) { } case GATT_WRITE: { - if (attr.len <= (payload_size - GATT_HDR_SIZE)) { + if ((attr.len + GATT_HDR_SIZE) <= payload_size) { p_clcb->s_handle = attr.handle; tGATT_STATUS rt = gatt_send_write_msg(tcb, p_clcb, GATT_REQ_WRITE, attr.handle, attr.len, 0, @@ -346,7 +346,14 @@ void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb) { uint16_t to_send = p_attr->len - p_attr->offset; uint16_t payload_size = gatt_tcb_get_payload_size(tcb, p_clcb->cid); - if (to_send > (payload_size - GATT_WRITE_LONG_HDR_SIZE)) { /* 2 = uint16_t offset bytes */ + + if (payload_size <= GATT_WRITE_LONG_HDR_SIZE) { + log::error("too small mtu size {}, possibly due to disconnection", payload_size); + gatt_end_operation(p_clcb, GATT_ERROR, NULL); + return; + } + + if (to_send > (payload_size - GATT_WRITE_LONG_HDR_SIZE)) { to_send = payload_size - GATT_WRITE_LONG_HDR_SIZE; } -- GitLab From a32525f02cd1da2b0dbc07200384e819e66c3952 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 17 Sep 2024 01:09:57 +0000 Subject: [PATCH 101/875] audio_hal_interface: Inject a2dp dependencies through BluetoothAudioPort Implements the following methods: - StartStream: invoke AVDTP start if the stream is not already started and neither SCO nor ISO are active - SuspendStream: invoke AVDTP suspend if the stream is not already suspended - SetLatencyMode: configure the latency mode Removes the dependency from audio_hal_interface to: - bluetooth::headset::IsCallIdle - hci::IsoManager::GetInstance - hci::IsoManager::GetNumberOfActiveIso - btif_av_stream_started_ready - btif_av_stream_ready - btif_av_stream_start_with_latency - btif_av_stream_suspend - btif_av_clear_remote_suspend_flag - btif_av_set_low_latency Bug: 365022887 Flag: EXEMPT, no logical change Test: m com.android.btservices Test: Manually validate a2dp sofware and offload paths Change-Id: Ie240f60d1ae79e91d99412c2cd82750487648290 --- system/audio_hal_interface/a2dp_encoding.cc | 7 +- system/audio_hal_interface/a2dp_encoding.h | 22 ++- .../audio_hal_interface/a2dp_encoding_host.cc | 8 +- .../aidl/a2dp_encoding_aidl.cc | 144 +++++++----------- .../aidl/a2dp_encoding_aidl.h | 7 +- .../libbt_audio_hal_a2dp_encoding_fuzzer.cpp | 13 +- .../hidl/a2dp_encoding_hidl.cc | 130 +++++++--------- .../hidl/a2dp_encoding_hidl.h | 3 +- system/btif/Android.bp | 6 +- system/btif/src/btif_a2dp_source.cc | 63 +++++++- .../mock_audio_hal_interface_a2dp_encoding.cc | 44 +++--- .../mock_audio_hal_interface_a2dp_encoding.h | 24 ++- system/test/mock/mock_frameworks_libaudio.cc | 2 + 13 files changed, 273 insertions(+), 200 deletions(-) diff --git a/system/audio_hal_interface/a2dp_encoding.cc b/system/audio_hal_interface/a2dp_encoding.cc index 1a8de2f2920..ae0b26d22f5 100644 --- a/system/audio_hal_interface/a2dp_encoding.cc +++ b/system/audio_hal_interface/a2dp_encoding.cc @@ -53,11 +53,12 @@ bool is_hal_offloading() { } // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop) { +bool init(bluetooth::common::MessageLoopThread* message_loop, + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { if (HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::HIDL) { - return hidl::a2dp::init(message_loop); + return hidl::a2dp::init(message_loop, audio_port); } - return aidl::a2dp::init(message_loop); + return aidl::a2dp::init(message_loop, audio_port); } // Clean up BluetoothAudio HAL diff --git a/system/audio_hal_interface/a2dp_encoding.h b/system/audio_hal_interface/a2dp_encoding.h index 722051a749b..11215f0bf23 100644 --- a/system/audio_hal_interface/a2dp_encoding.h +++ b/system/audio_hal_interface/a2dp_encoding.h @@ -31,7 +31,7 @@ namespace audio { namespace a2dp { /// Loosely copied after the definition from the Bluetooth Audio interface: -/// hardware/interfaces/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl +/// audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl enum class BluetoothAudioStatus { SUCCESS = 0, UNKNOWN, @@ -40,6 +40,24 @@ enum class BluetoothAudioStatus { PENDING, }; +/// Loosely copied after the definition from the Bluetooth Audio interface: +/// audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl +/// +/// Implements callbacks for the BT Audio HAL to start, suspend and configure +/// the audio stream. Completion of the requested operation is indicated +/// by the methods ack_stream_started, ack_stream_suspended. +class BluetoothAudioPort { +public: + virtual ~BluetoothAudioPort() {} + virtual BluetoothAudioStatus StartStream(bool /*low_latency*/) const { + return BluetoothAudioStatus::FAILURE; + } + virtual BluetoothAudioStatus SuspendStream() const { return BluetoothAudioStatus::FAILURE; } + virtual BluetoothAudioStatus SetLatencyMode(bool /*low_latency*/) const { + return BluetoothAudioStatus::FAILURE; + } +}; + bool update_codec_offloading_capabilities( const std::vector& framework_preference, bool supports_a2dp_hw_offload_v2); @@ -51,7 +69,7 @@ bool is_hal_enabled(); bool is_hal_offloading(); // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop); +bool init(bluetooth::common::MessageLoopThread* message_loop, BluetoothAudioPort const* audio_port); // Clean up BluetoothAudio HAL void cleanup(); diff --git a/system/audio_hal_interface/a2dp_encoding_host.cc b/system/audio_hal_interface/a2dp_encoding_host.cc index 767ec9cecea..ab395f52295 100644 --- a/system/audio_hal_interface/a2dp_encoding_host.cc +++ b/system/audio_hal_interface/a2dp_encoding_host.cc @@ -227,12 +227,17 @@ bool is_hal_enabled() { return true; } // Check if new bluetooth_audio is running with offloading encoders bool is_hal_offloading() { return false; } +static BluetoothAudioPort null_audio_port; +static BluetoothAudioPort const* bluetooth_audio_port = &null_audio_port; + // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop) { +bool init(bluetooth::common::MessageLoopThread* message_loop, + BluetoothAudioPort const* audio_port) { a2dp_uipc = UIPC_Init(); total_bytes_read_ = 0; data_position_ = {}; remote_delay_report_ = 0; + bluetooth_audio_port = audio_port; return true; } @@ -240,6 +245,7 @@ bool init(bluetooth::common::MessageLoopThread* message_loop) { // Clean up BluetoothAudio HAL void cleanup() { end_session(); + bluetooth_audio_port = &null_audio_port; if (a2dp_uipc != nullptr) { UIPC_Close(*a2dp_uipc, UIPC_CH_ID_ALL); diff --git a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc index 6e715c4a758..5f8f73daa58 100644 --- a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc @@ -25,9 +25,7 @@ #include "a2dp_provider_info.h" #include "a2dp_transport.h" #include "audio_aidl_interfaces.h" -#include "bta/av/bta_av_int.h" -#include "btif/include/btif_common.h" -#include "btm_iso_api.h" +#include "btif/include/btif_av.h" #include "codec_status_aidl.h" #include "transport_instance.h" @@ -45,8 +43,12 @@ namespace audio { namespace aidl { namespace a2dp { +using ::bluetooth::audio::a2dp::BluetoothAudioPort; using ::bluetooth::audio::a2dp::BluetoothAudioStatus; +static BluetoothAudioPort null_audio_port; +static BluetoothAudioPort const* bluetooth_audio_port_ = &null_audio_port; + namespace { using ::aidl::android::hardware::bluetooth::audio::A2dpStreamConfiguration; @@ -67,6 +69,21 @@ using ::bluetooth::audio::aidl::codec::A2dpLdacToHalConfig; using ::bluetooth::audio::aidl::codec::A2dpOpusToHalConfig; using ::bluetooth::audio::aidl::codec::A2dpSbcToHalConfig; +static BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(BluetoothAudioStatus ack) { + switch (ack) { + case BluetoothAudioStatus::SUCCESS: + return BluetoothAudioCtrlAck::SUCCESS_FINISHED; + case BluetoothAudioStatus::PENDING: + return BluetoothAudioCtrlAck::PENDING; + case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: + return BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED; + case BluetoothAudioStatus::UNKNOWN: + case BluetoothAudioStatus::FAILURE: + default: + return BluetoothAudioCtrlAck::FAILURE; + } +} + /*** * * A2dpTransport functions and variables @@ -74,6 +91,7 @@ using ::bluetooth::audio::aidl::codec::A2dpSbcToHalConfig; ***/ tA2DP_CTRL_CMD A2dpTransport::a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; + uint16_t A2dpTransport::remote_delay_report_ = 0; A2dpTransport::A2dpTransport(SessionType sessionType) @@ -85,92 +103,59 @@ A2dpTransport::A2dpTransport(SessionType sessionType) } BluetoothAudioCtrlAck A2dpTransport::StartRequest(bool is_low_latency) { - // Check if a previous request is not finished + // Check if a previous Start request is ongoing. if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_START) { - log::info("A2DP_CTRL_CMD_START in progress"); + log::warn("unable to start stream: already pending"); return BluetoothAudioCtrlAck::PENDING; - } else if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { - log::warn("busy in pending_cmd={}", a2dp_pending_cmd_); - return BluetoothAudioCtrlAck::FAILURE; } - // Don't send START request to stack while we are in a call - if (!bluetooth::headset::IsCallIdle()) { - log::error("call state is busy"); - return BluetoothAudioCtrlAck::FAILURE_BUSY; + // Check if a different request is ongoing. + if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { + log::warn("unable to start stream: busy with pending command {}", a2dp_pending_cmd_); + return BluetoothAudioCtrlAck::FAILURE; } - if (com::android::bluetooth::flags::a2dp_check_lea_iso_channel()) { - // Don't send START request to stack while LEA sessions are in use - if (hci::IsoManager::GetInstance()->GetNumberOfActiveIso() > 0) { - log::error("LEA currently has active ISO channels"); - return BluetoothAudioCtrlAck::FAILURE; - } - } + log::info(""); - if (btif_av_stream_started_ready(A2dpType::kSource)) { - // Already started, ACK back immediately. - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; - } - if (btif_av_stream_ready(A2dpType::kSource)) { - // check if codec needs to be switched prior to stream start - invoke_switch_codec_cb(is_low_latency); - /* - * Post start event and wait for audio path to open. - * If we are the source, the ACK will be sent after the start - * procedure is completed, othewise send it now. - */ - a2dp_pending_cmd_ = A2DP_CTRL_CMD_START; - btif_av_stream_start_with_latency(is_low_latency); - if (btif_av_get_peer_sep(A2dpType::kSource) != AVDT_TSEP_SRC) { - log::info("accepted"); - return BluetoothAudioCtrlAck::PENDING; - } - a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; - } - log::error("AV stream is not ready to start"); - return BluetoothAudioCtrlAck::FAILURE; + auto status = bluetooth_audio_port_->StartStream(is_low_latency); + a2dp_pending_cmd_ = + status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_START : A2DP_CTRL_CMD_NONE; + + return a2dp_ack_to_bt_audio_ctrl_ack(status); } BluetoothAudioCtrlAck A2dpTransport::SuspendRequest() { - // Previous request is not finished + // Check if a previous Suspend request is ongoing. if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_SUSPEND) { - log::info("A2DP_CTRL_CMD_SUSPEND in progress"); + log::warn("unable to suspend stream: already pending"); return BluetoothAudioCtrlAck::PENDING; - } else if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { - log::warn("busy in pending_cmd={}", a2dp_pending_cmd_); - return BluetoothAudioCtrlAck::FAILURE; } - // Local suspend - if (btif_av_stream_started_ready(A2dpType::kSource)) { - log::info("accepted"); - a2dp_pending_cmd_ = A2DP_CTRL_CMD_SUSPEND; - btif_av_stream_suspend(); - return BluetoothAudioCtrlAck::PENDING; + + // Check if a different request is ongoing. + if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { + log::warn("unable to suspend stream: busy with pending command {}", a2dp_pending_cmd_); + return BluetoothAudioCtrlAck::FAILURE; } - /* If we are not in started state, just ack back ok and let - * audioflinger close the channel. This can happen if we are - * remotely suspended, clear REMOTE SUSPEND flag. - */ - btif_av_clear_remote_suspend_flag(A2dpType::kSource); - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; + + log::info(""); + + auto status = bluetooth_audio_port_->SuspendStream(); + a2dp_pending_cmd_ = + status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_SUSPEND : A2DP_CTRL_CMD_NONE; + + return a2dp_ack_to_bt_audio_ctrl_ack(status); } void A2dpTransport::StopRequest() { - if (btif_av_get_peer_sep(A2dpType::kSource) == AVDT_TSEP_SNK && - !btif_av_stream_started_ready(A2dpType::kSource)) { - btif_av_clear_remote_suspend_flag(A2dpType::kSource); - return; - } - log::info("handling"); - a2dp_pending_cmd_ = A2DP_CTRL_CMD_STOP; - btif_av_stream_stop(RawAddress::kEmpty); + log::info(""); + + auto status = bluetooth_audio_port_->SuspendStream(); + a2dp_pending_cmd_ = + status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_STOP : A2DP_CTRL_CMD_NONE; } void A2dpTransport::SetLatencyMode(LatencyMode latency_mode) { - bool is_low_latency = latency_mode == LatencyMode::LOW_LATENCY ? true : false; - btif_av_set_low_latency(is_low_latency); + bluetooth_audio_port_->SetLatencyMode(latency_mode == LatencyMode::LOW_LATENCY); } bool A2dpTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns, @@ -239,21 +224,6 @@ uint16_t remote_delay = 0; bool is_low_latency_mode_allowed = false; -static BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(BluetoothAudioStatus ack) { - switch (ack) { - case BluetoothAudioStatus::SUCCESS: - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; - case BluetoothAudioStatus::PENDING: - return BluetoothAudioCtrlAck::PENDING; - case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: - return BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED; - case BluetoothAudioStatus::UNKNOWN: - case BluetoothAudioStatus::FAILURE: - default: - return BluetoothAudioCtrlAck::FAILURE; - } -} - bool a2dp_get_selected_hal_codec_config(A2dpCodecConfig* a2dp_config, uint16_t peer_mtu, CodecConfiguration* codec_config) { btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig(); @@ -376,8 +346,10 @@ static void delete_hal_interface(BluetoothAudioSinkClientInterface* hal_interfac } // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* /*message_loop*/) { +bool init(bluetooth::common::MessageLoopThread* /*message_loop*/, + BluetoothAudioPort const* audio_port) { log::info(""); + log::assert_that(audio_port != nullptr, "audio_port != nullptr"); if (software_hal_interface != nullptr) { return true; @@ -403,6 +375,7 @@ bool init(bluetooth::common::MessageLoopThread* /*message_loop*/) { } } + bluetooth_audio_port_ = audio_port; active_hal_interface = (offloading_hal_interface != nullptr ? offloading_hal_interface : software_hal_interface); @@ -438,6 +411,7 @@ void cleanup() { delete a2dp_sink; } + bluetooth_audio_port_ = &null_audio_port; remote_delay = 0; } diff --git a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h index dd168d03099..54cde295e32 100644 --- a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h @@ -20,10 +20,6 @@ #include "a2dp_encoding.h" #include "a2dp_sbc_constants.h" -#include "btif/include/btif_a2dp_source.h" -#include "btif/include/btif_av.h" -#include "btif/include/btif_av_co.h" -#include "btif/include/btif_hf.h" #include "common/message_loop_thread.h" #include "hardware/bt_av.h" #include "os/log.h" @@ -52,7 +48,8 @@ bool is_hal_offloading(); /*** * Initialize BluetoothAudio HAL: openProvider ***/ -bool init(bluetooth::common::MessageLoopThread* message_loop); +bool init(bluetooth::common::MessageLoopThread* message_loop, + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port); /*** * Clean up BluetoothAudio HAL diff --git a/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp b/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp index 1e21353bf30..0ffc909e405 100644 --- a/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp +++ b/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp @@ -73,7 +73,18 @@ public: static A2dpCodecConfig* mCodec; }; +class TestAudioPort : public bluetooth::audio::a2dp::BluetoothAudioPort { + BluetoothAudioStatus StartStream(bool /*low_latency*/) const override { + return BluetoothAudioStatus::PENDING; + } + BluetoothAudioStatus SuspendStream() const override { return BluetoothAudioStatus::PENDING; } + BluetoothAudioStatus SetLatencyMode(bool /*low_latency*/) const override { + return BluetoothAudioStatus::SUCCESS; + } +}; + A2dpCodecConfig* A2dpEncodingFuzzer::mCodec{nullptr}; +const TestAudioPort test_audio_port; void A2dpEncodingFuzzer::process(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); @@ -95,7 +106,7 @@ void A2dpEncodingFuzzer::process(const uint8_t* data, size_t size) { uint16_t delayReport = fdp.ConsumeIntegral(); bluetooth::audio::a2dp::set_remote_delay(delayReport); - if (!bluetooth::audio::a2dp::init(&messageLoopThread)) { + if (!bluetooth::audio::a2dp::init(&messageLoopThread, &test_audio_port)) { return; } diff --git a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc index bc968a25a87..b5c33360221 100644 --- a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc +++ b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc @@ -22,10 +22,7 @@ #include #include "a2dp_sbc_constants.h" -#include "btif/include/btif_a2dp_source.h" #include "btif/include/btif_av.h" -#include "btif/include/btif_av_co.h" -#include "btif/include/btif_hf.h" #include "client_interface_hidl.h" #include "codec_status_hidl.h" #include "osi/include/properties.h" @@ -57,6 +54,9 @@ namespace audio { namespace hidl { namespace a2dp { +static bluetooth::audio::a2dp::BluetoothAudioPort null_audio_port; +static bluetooth::audio::a2dp::BluetoothAudioPort const* bluetooth_audio_port_; + namespace { using ::bluetooth::audio::hidl::AudioCapabilities; @@ -80,6 +80,21 @@ using ::bluetooth::audio::hidl::codec::CodecConfiguration; using ::bluetooth::audio::a2dp::BluetoothAudioStatus; +static BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(BluetoothAudioStatus ack) { + switch (ack) { + case BluetoothAudioStatus::SUCCESS: + return BluetoothAudioCtrlAck::SUCCESS_FINISHED; + case BluetoothAudioStatus::PENDING: + return BluetoothAudioCtrlAck::PENDING; + case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: + return BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED; + case BluetoothAudioStatus::UNKNOWN: + case BluetoothAudioStatus::FAILURE: + default: + return BluetoothAudioCtrlAck::FAILURE; + } +} + // Provide call-in APIs for the Bluetooth Audio HAL class A2dpTransport : public ::bluetooth::audio::hidl::IBluetoothSinkTransportInstance { public: @@ -92,77 +107,55 @@ public: } BluetoothAudioCtrlAck StartRequest() override { - // Check if a previous request is not finished + // Check if a previous Start request is ongoing. if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_START) { - log::info("A2DP_CTRL_CMD_START in progress"); + log::warn("unable to start stream: already pending"); return BluetoothAudioCtrlAck::PENDING; - } else if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { - log::warn("busy in pending_cmd={}", a2dp_pending_cmd_); - return BluetoothAudioCtrlAck::FAILURE; } - // Don't send START request to stack while we are in a call - if (!bluetooth::headset::IsCallIdle()) { - log::error("call state is busy"); - return BluetoothAudioCtrlAck::FAILURE_BUSY; + // Check if a different request is ongoing. + if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { + log::warn("unable to start stream: busy with pending command {}", a2dp_pending_cmd_); + return BluetoothAudioCtrlAck::FAILURE; } - if (btif_av_stream_started_ready(A2dpType::kSource)) { - // Already started, ACK back immediately. - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; - } - if (btif_av_stream_ready(A2dpType::kSource)) { - /* - * Post start event and wait for audio path to open. - * If we are the source, the ACK will be sent after the start - * procedure is completed, othewise send it now. - */ - a2dp_pending_cmd_ = A2DP_CTRL_CMD_START; - btif_av_stream_start(A2dpType::kSource); - if (btif_av_get_peer_sep(A2dpType::kSource) != AVDT_TSEP_SRC) { - log::info("accepted"); - return BluetoothAudioCtrlAck::PENDING; - } - a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; - } - log::error("AV stream is not ready to start"); - return BluetoothAudioCtrlAck::FAILURE; + log::info(""); + + auto status = bluetooth_audio_port_->StartStream(false); + a2dp_pending_cmd_ = + status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_START : A2DP_CTRL_CMD_NONE; + + return a2dp_ack_to_bt_audio_ctrl_ack(status); } BluetoothAudioCtrlAck SuspendRequest() override { - // Previous request is not finished + // Check if a previous Suspend request is ongoing. if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_SUSPEND) { - log::info("A2DP_CTRL_CMD_SUSPEND in progress"); + log::warn("unable to suspend stream: already pending"); return BluetoothAudioCtrlAck::PENDING; - } else if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { - log::warn("busy in pending_cmd={}", a2dp_pending_cmd_); - return BluetoothAudioCtrlAck::FAILURE; } - // Local suspend - if (btif_av_stream_started_ready(A2dpType::kSource)) { - log::info("accepted"); - a2dp_pending_cmd_ = A2DP_CTRL_CMD_SUSPEND; - btif_av_stream_suspend(); - return BluetoothAudioCtrlAck::PENDING; + + // Check if a different request is ongoing. + if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { + log::warn("unable to suspend stream: busy with pending command {}", a2dp_pending_cmd_); + return BluetoothAudioCtrlAck::FAILURE; } - /* If we are not in started state, just ack back ok and let - * audioflinger close the channel. This can happen if we are - * remotely suspended, clear REMOTE SUSPEND flag. - */ - btif_av_clear_remote_suspend_flag(A2dpType::kSource); - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; + + log::info(""); + + auto status = bluetooth_audio_port_->SuspendStream(); + a2dp_pending_cmd_ = + status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_SUSPEND : A2DP_CTRL_CMD_NONE; + + return a2dp_ack_to_bt_audio_ctrl_ack(status); } void StopRequest() override { - if (btif_av_get_peer_sep(A2dpType::kSource) == AVDT_TSEP_SNK && - !btif_av_stream_started_ready(A2dpType::kSource)) { - btif_av_clear_remote_suspend_flag(A2dpType::kSource); - return; - } - log::info("handling"); - a2dp_pending_cmd_ = A2DP_CTRL_CMD_STOP; - btif_av_stream_stop(RawAddress::kEmpty); + log::info(""); + + auto status = bluetooth_audio_port_->SuspendStream(); + a2dp_pending_cmd_ = + status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_STOP : A2DP_CTRL_CMD_NONE; } bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, @@ -226,21 +219,6 @@ BluetoothAudioSinkClientInterface* active_hal_interface = nullptr; // initialized uint16_t remote_delay = 0; -static BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(BluetoothAudioStatus ack) { - switch (ack) { - case BluetoothAudioStatus::SUCCESS: - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; - case BluetoothAudioStatus::PENDING: - return BluetoothAudioCtrlAck::PENDING; - case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: - return BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED; - case BluetoothAudioStatus::UNKNOWN: - case BluetoothAudioStatus::FAILURE: - default: - return BluetoothAudioCtrlAck::FAILURE; - } -} - static bool a2dp_get_selected_hal_codec_config(A2dpCodecConfig* a2dp_config, uint16_t peer_mtu, CodecConfiguration* codec_config) { btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig(); @@ -323,8 +301,10 @@ bool is_hal_2_0_offloading() { } // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop) { +bool init(bluetooth::common::MessageLoopThread* message_loop, + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { log::info(""); + log::assert_that(audio_port != nullptr, "audio_port != nullptr"); auto a2dp_sink = new A2dpTransport(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH); software_hal_interface = new BluetoothAudioSinkClientInterface(a2dp_sink, message_loop); @@ -352,6 +332,7 @@ bool init(bluetooth::common::MessageLoopThread* message_loop) { } } + bluetooth_audio_port_ = audio_port; active_hal_interface = (offloading_hal_interface != nullptr ? offloading_hal_interface : software_hal_interface); @@ -387,6 +368,7 @@ void cleanup() { delete a2dp_sink; } + bluetooth_audio_port_ = &null_audio_port; remote_delay = 0; } diff --git a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h index 7bd9575bad5..ed084dd14d7 100644 --- a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h +++ b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h @@ -37,7 +37,8 @@ bool is_hal_2_0_enabled(); bool is_hal_2_0_offloading(); // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop); +bool init(bluetooth::common::MessageLoopThread* message_loop, + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port); // Clean up BluetoothAudio HAL void cleanup(); diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 9b1bc412956..8d02f5a3b81 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -344,6 +344,7 @@ cc_test { android: { shared_libs: [ "libPlatformProperties", + "libaaudio", "libbinder_ndk", "libstatssocket", ], @@ -354,7 +355,9 @@ cc_test { "android.hardware.common.fmq-V1-ndk", "android.system.suspend-V1-ndk", "android.system.suspend.control-V1-ndk", - "libaaudio", + "libexpresslog", + "libstatslog_express", + "libtextclassifier_hash_static", ], }, host: { @@ -696,6 +699,7 @@ cc_test { ":TestMockBtaVc", ":TestMockBtcore", ":TestMockBtu", + ":TestMockFrameworks", ":TestMockHci", ":TestMockMainShim", ":TestMockMainShimDumpsys", diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index f67527da8bd..4fda9ca0860 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -38,7 +38,10 @@ #include "btif_a2dp_source.h" #include "btif_av.h" #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" @@ -319,13 +322,69 @@ bool btif_a2dp_source_init(void) { return true; } +class A2dpAudioPort : public bluetooth::audio::a2dp::BluetoothAudioPort { + BluetoothAudioStatus StartStream(bool low_latency) const override { + // Check if a phone call is currently active. + if (!bluetooth::headset::IsCallIdle()) { + log::error("unable to start stream: call is active"); + return BluetoothAudioStatus::FAILURE; + } + + // Check if LE Audio is currently active. + if (com::android::bluetooth::flags::a2dp_check_lea_iso_channel() && + hci::IsoManager::GetInstance()->GetNumberOfActiveIso() > 0) { + log::error("unable to start stream: LEA is active"); + return BluetoothAudioStatus::FAILURE; + } + + // Check if the stream has already been started. + if (btif_av_stream_started_ready(A2dpType::kSource)) { + return BluetoothAudioStatus::SUCCESS; + } + + // Check if the stream is ready to start. + if (!btif_av_stream_ready(A2dpType::kSource)) { + log::error("unable to start stream: not ready"); + return BluetoothAudioStatus::FAILURE; + } + + // Check if codec needs to be switched prior to stream start. + invoke_switch_codec_cb(low_latency); + + // Post start event. The start request is pending, completion will be + // notified to bluetooth::audio::a2dp::ack_stream_started. + btif_av_stream_start_with_latency(low_latency); + return BluetoothAudioStatus::PENDING; + } + + BluetoothAudioStatus SuspendStream() const override { + // Check if the stream is already suspended. + if (!btif_av_stream_started_ready(A2dpType::kSource)) { + btif_av_clear_remote_suspend_flag(A2dpType::kSource); + return BluetoothAudioStatus::SUCCESS; + } + + // Post suspend event. The suspend request is pending, completion will + // be notified to bluetooth::audio::a2dp::ack_stream_suspended. + btif_av_stream_suspend(); + return BluetoothAudioStatus::PENDING; + } + + BluetoothAudioStatus SetLatencyMode(bool low_latency) const override { + btif_av_set_low_latency(low_latency); + return BluetoothAudioStatus::SUCCESS; + } +}; + +static const A2dpAudioPort a2dp_audio_port; + static void btif_a2dp_source_init_delayed(void) { log::info(""); // When codec extensibility is enabled in the audio HAL interface, // the provider needs to be initialized earlier in order to ensure // get_a2dp_configuration and parse_a2dp_configuration can be // invoked before the stream is started. - bluetooth::audio::a2dp::init(&btif_a2dp_source_thread); + bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port); } bool btif_a2dp_source_startup(void) { @@ -353,7 +412,7 @@ static void btif_a2dp_source_startup_delayed() { log::fatal("unable to enable real time scheduling"); #endif } - if (!bluetooth::audio::a2dp::init(&btif_a2dp_source_thread)) { + if (!bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port)) { log::warn("Failed to setup the bluetooth audio HAL"); } btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateRunning); diff --git a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc index 09d095627e1..e4ff3ef9eee 100644 --- a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc +++ b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc @@ -28,6 +28,8 @@ #include "test/common/mock_functions.h" +#pragma GCC diagnostic error "-Wmissing-prototypes" + // Original usings // Mocked internal structures, if any @@ -87,6 +89,8 @@ bool update_codec_offloading_capabilities::return_value = false; } // namespace mock } // namespace test +namespace bluetooth::audio::a2dp { + // Mocked functions, if any void ack_stream_started(BluetoothAudioStatus status) { inc_func_call_count(__func__); @@ -100,14 +104,12 @@ void cleanup() { inc_func_call_count(__func__); test::mock::audio_hal_interface_a2dp_encoding::cleanup(); } -std::optional bluetooth::audio::a2dp::provider::codec_index_str( - btav_a2dp_codec_index_t codec_index) { +std::optional provider::codec_index_str(btav_a2dp_codec_index_t codec_index) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::codec_index_str(codec_index); } -bool bluetooth::audio::a2dp::provider::codec_info(btav_a2dp_codec_index_t codec_index, - uint64_t* codec_id, uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_config) { +bool provider::codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, + uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::codec_info(codec_index, codec_id, codec_info, codec_config); @@ -116,16 +118,17 @@ void end_session() { inc_func_call_count(__func__); test::mock::audio_hal_interface_a2dp_encoding::end_session(); } -std::optional bluetooth::audio::a2dp::provider::get_a2dp_configuration( +std::optional provider::get_a2dp_configuration( RawAddress peer_address, std::vector const& remote_seps, btav_a2dp_codec_config_t const& user_preferences) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::get_a2dp_configuration( peer_address, remote_seps, user_preferences); } -bool init(bluetooth::common::MessageLoopThread* message_loop) { +bool init(bluetooth::common::MessageLoopThread* message_loop, + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { inc_func_call_count(__func__); - return test::mock::audio_hal_interface_a2dp_encoding::init(message_loop); + return test::mock::audio_hal_interface_a2dp_encoding::init(message_loop, audio_port); } bool is_hal_enabled() { inc_func_call_count(__func__); @@ -139,10 +142,10 @@ bool is_opus_supported() { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::is_opus_supported(); } -tA2DP_STATUS bluetooth::audio::a2dp::provider::parse_a2dp_configuration( - btav_a2dp_codec_index_t codec_index, const uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_parameters, - std::vector* vendor_specific_parameters) { +tA2DP_STATUS provider::parse_a2dp_configuration(btav_a2dp_codec_index_t codec_index, + const uint8_t* codec_info, + btav_a2dp_codec_config_t* codec_parameters, + std::vector* vendor_specific_parameters) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::parse_a2dp_configuration( codec_index, codec_info, codec_parameters, vendor_specific_parameters); @@ -159,17 +162,17 @@ void set_remote_delay(uint16_t delay_report) { inc_func_call_count(__func__); test::mock::audio_hal_interface_a2dp_encoding::set_remote_delay(delay_report); } -bool setup_codec(A2dpCodecConfig* a2dp_config) { +bool setup_codec(A2dpCodecConfig* a2dp_config, uint16_t peer_mtu, + int preferred_encoding_interval_us) { inc_func_call_count(__func__); - return test::mock::audio_hal_interface_a2dp_encoding::setup_codec(a2dp_config); + return test::mock::audio_hal_interface_a2dp_encoding::setup_codec(a2dp_config, peer_mtu, + preferred_encoding_interval_us); } -std::optional bluetooth::audio::a2dp::provider::sink_codec_index( - const uint8_t* p_codec_info) { +std::optional provider::sink_codec_index(const uint8_t* p_codec_info) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::sink_codec_index(p_codec_info); } -std::optional bluetooth::audio::a2dp::provider::source_codec_index( - const uint8_t* p_codec_info) { +std::optional provider::source_codec_index(const uint8_t* p_codec_info) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::source_codec_index(p_codec_info); } @@ -177,7 +180,7 @@ void start_session() { inc_func_call_count(__func__); test::mock::audio_hal_interface_a2dp_encoding::start_session(); } -bool bluetooth::audio::a2dp::provider::supports_codec(btav_a2dp_codec_index_t codec_index) { +bool provider::supports_codec(btav_a2dp_codec_index_t codec_index) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::supports_codec(codec_index); } @@ -188,5 +191,8 @@ bool update_codec_offloading_capabilities( return test::mock::audio_hal_interface_a2dp_encoding::update_codec_offloading_capabilities( framework_preference, supports_a2dp_hw_offload_v2); } + +} // namespace bluetooth::audio::a2dp + // Mocked functions complete // END mockcify generation diff --git a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h index 698d9d5c473..f56ac74365e 100644 --- a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h +++ b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h @@ -136,9 +136,16 @@ extern struct get_a2dp_configuration get_a2dp_configuration; // Return: bool struct init { static bool return_value; - std::function body{ - [](bluetooth::common::MessageLoopThread* /* message_loop */) { return return_value; }}; - bool operator()(bluetooth::common::MessageLoopThread* message_loop) { return body(message_loop); } + std::function + body{[](bluetooth::common::MessageLoopThread* /* message_loop */, + bluetooth::audio::a2dp::BluetoothAudioPort const* /* audio_port */) { + return return_value; + }}; + bool operator()(bluetooth::common::MessageLoopThread* message_loop, + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { + return body(message_loop, audio_port); + } }; extern struct init init; @@ -226,9 +233,14 @@ extern struct set_remote_delay set_remote_delay; // Return: bool struct setup_codec { static bool return_value; - std::function body{ - [](A2dpCodecConfig* /* a2dp_config */) { return return_value; }}; - bool operator()(A2dpCodecConfig* a2dp_config) { return body(a2dp_config); } + std::function + body{[](A2dpCodecConfig* /* a2dp_config */, uint16_t /* peer_mtu */, + int /* preferred_encoding_interval_us */) { return return_value; }}; + bool operator()(A2dpCodecConfig* a2dp_config, uint16_t peer_mtu, + int preferred_encoding_interval_us) { + return body(a2dp_config, peer_mtu, preferred_encoding_interval_us); + } }; extern struct setup_codec setup_codec; diff --git a/system/test/mock/mock_frameworks_libaudio.cc b/system/test/mock/mock_frameworks_libaudio.cc index 230658d74da..fb75d42c815 100644 --- a/system/test/mock/mock_frameworks_libaudio.cc +++ b/system/test/mock/mock_frameworks_libaudio.cc @@ -28,6 +28,8 @@ #include #include +#pragma GCC diagnostic ignored "-Wunused-parameter" + aaudio_allowed_capture_policy_t AAudioStream_getAllowedCapturePolicy(AAudioStream* stream) { inc_func_call_count(__func__); return 0; -- GitLab From b21d88309a0540ad7f535bf268ca597834040b74 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 19 Sep 2024 00:56:34 +0000 Subject: [PATCH 102/875] audio_hal_interface: Pass a2dp_offload_enabled flag to bluetooth::audio::a2dp::init Removes the dependecy from audio_hal_interface on - btif_av_is_a2dp_offload_enabled Bug: 365022887 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I835baafdf83e14762d548b286e45457fa9e39387 --- system/audio_hal_interface/a2dp_encoding.cc | 6 +++--- system/audio_hal_interface/a2dp_encoding.h | 3 ++- system/audio_hal_interface/a2dp_encoding_host.cc | 4 ++-- .../audio_hal_interface/aidl/a2dp_encoding_aidl.cc | 5 ++--- system/audio_hal_interface/aidl/a2dp_encoding_aidl.h | 2 +- .../fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp | 6 ++---- .../audio_hal_interface/hidl/a2dp_encoding_hidl.cc | 5 ++--- system/audio_hal_interface/hidl/a2dp_encoding_hidl.h | 2 +- system/btif/src/btif_a2dp_source.cc | 6 ++++-- .../mock/mock_audio_hal_interface_a2dp_encoding.cc | 5 +++-- .../mock/mock_audio_hal_interface_a2dp_encoding.h | 12 ++++++------ 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/system/audio_hal_interface/a2dp_encoding.cc b/system/audio_hal_interface/a2dp_encoding.cc index ae0b26d22f5..d98b99fbcfa 100644 --- a/system/audio_hal_interface/a2dp_encoding.cc +++ b/system/audio_hal_interface/a2dp_encoding.cc @@ -54,11 +54,11 @@ bool is_hal_offloading() { // Initialize BluetoothAudio HAL: openProvider bool init(bluetooth::common::MessageLoopThread* message_loop, - bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port, bool offload_enabled) { if (HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::HIDL) { - return hidl::a2dp::init(message_loop, audio_port); + return hidl::a2dp::init(message_loop, audio_port, offload_enabled); } - return aidl::a2dp::init(message_loop, audio_port); + return aidl::a2dp::init(message_loop, audio_port, offload_enabled); } // Clean up BluetoothAudio HAL diff --git a/system/audio_hal_interface/a2dp_encoding.h b/system/audio_hal_interface/a2dp_encoding.h index 11215f0bf23..d23d023e35b 100644 --- a/system/audio_hal_interface/a2dp_encoding.h +++ b/system/audio_hal_interface/a2dp_encoding.h @@ -69,7 +69,8 @@ bool is_hal_enabled(); bool is_hal_offloading(); // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop, BluetoothAudioPort const* audio_port); +bool init(bluetooth::common::MessageLoopThread* message_loop, BluetoothAudioPort const* audio_port, + bool offload_enabled); // Clean up BluetoothAudio HAL void cleanup(); diff --git a/system/audio_hal_interface/a2dp_encoding_host.cc b/system/audio_hal_interface/a2dp_encoding_host.cc index ab395f52295..9ec22cbbdd6 100644 --- a/system/audio_hal_interface/a2dp_encoding_host.cc +++ b/system/audio_hal_interface/a2dp_encoding_host.cc @@ -231,8 +231,8 @@ static BluetoothAudioPort null_audio_port; static BluetoothAudioPort const* bluetooth_audio_port = &null_audio_port; // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop, - BluetoothAudioPort const* audio_port) { +bool init(bluetooth::common::MessageLoopThread* message_loop, BluetoothAudioPort const* audio_port, + bool /*offload_enabled*/) { a2dp_uipc = UIPC_Init(); total_bytes_read_ = 0; data_position_ = {}; diff --git a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc index 5f8f73daa58..38b7edc5883 100644 --- a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc @@ -25,7 +25,6 @@ #include "a2dp_provider_info.h" #include "a2dp_transport.h" #include "audio_aidl_interfaces.h" -#include "btif/include/btif_av.h" #include "codec_status_aidl.h" #include "transport_instance.h" @@ -347,7 +346,7 @@ static void delete_hal_interface(BluetoothAudioSinkClientInterface* hal_interfac // Initialize BluetoothAudio HAL: openProvider bool init(bluetooth::common::MessageLoopThread* /*message_loop*/, - BluetoothAudioPort const* audio_port) { + BluetoothAudioPort const* audio_port, bool offload_enabled) { log::info(""); log::assert_that(audio_port != nullptr, "audio_port != nullptr"); @@ -365,7 +364,7 @@ bool init(bluetooth::common::MessageLoopThread* /*message_loop*/, return false; } - if (btif_av_is_a2dp_offload_enabled() && offloading_hal_interface == nullptr) { + if (offload_enabled && offloading_hal_interface == nullptr) { offloading_hal_interface = new_hal_interface(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); if (offloading_hal_interface == nullptr) { diff --git a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h index 54cde295e32..32ef7923d81 100644 --- a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h @@ -49,7 +49,7 @@ bool is_hal_offloading(); * Initialize BluetoothAudio HAL: openProvider ***/ bool init(bluetooth::common::MessageLoopThread* message_loop, - bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port); + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port, bool offload_enabled); /*** * Clean up BluetoothAudio HAL diff --git a/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp b/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp index 0ffc909e405..a35b12523f3 100644 --- a/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp +++ b/system/audio_hal_interface/fuzzer/libbt_audio_hal_a2dp_encoding_fuzzer.cpp @@ -92,9 +92,7 @@ void A2dpEncodingFuzzer::process(const uint8_t* data, size_t size) { mCodec = A2dpCodecConfig::createCodec(fdp.PickValueInArray(kCodecIndices)); } - osi_property_set("persist.bluetooth.a2dp_offload.disabled", - fdp.PickValueInArray({"true", "false"})); - + bool offload_enabled = fdp.ConsumeBool(); std::string name = fdp.ConsumeRandomLengthString(kRandomStringLength); uint16_t peer_mtu = fdp.ConsumeIntegral(); int preferred_encoding_interval_us = fdp.ConsumeIntegral(); @@ -106,7 +104,7 @@ void A2dpEncodingFuzzer::process(const uint8_t* data, size_t size) { uint16_t delayReport = fdp.ConsumeIntegral(); bluetooth::audio::a2dp::set_remote_delay(delayReport); - if (!bluetooth::audio::a2dp::init(&messageLoopThread, &test_audio_port)) { + if (!bluetooth::audio::a2dp::init(&messageLoopThread, &test_audio_port, offload_enabled)) { return; } diff --git a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc index b5c33360221..2926e73b969 100644 --- a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc +++ b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc @@ -22,7 +22,6 @@ #include #include "a2dp_sbc_constants.h" -#include "btif/include/btif_av.h" #include "client_interface_hidl.h" #include "codec_status_hidl.h" #include "osi/include/properties.h" @@ -302,7 +301,7 @@ bool is_hal_2_0_offloading() { // Initialize BluetoothAudio HAL: openProvider bool init(bluetooth::common::MessageLoopThread* message_loop, - bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port, bool offload_enabled) { log::info(""); log::assert_that(audio_port != nullptr, "audio_port != nullptr"); @@ -316,7 +315,7 @@ bool init(bluetooth::common::MessageLoopThread* message_loop, return false; } - if (btif_av_is_a2dp_offload_enabled()) { + if (offload_enabled) { a2dp_sink = new A2dpTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); offloading_hal_interface = new BluetoothAudioSinkClientInterface(a2dp_sink, message_loop); if (!offloading_hal_interface->IsValid()) { diff --git a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h index ed084dd14d7..154bf3bfbe0 100644 --- a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h +++ b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h @@ -38,7 +38,7 @@ bool is_hal_2_0_offloading(); // Initialize BluetoothAudio HAL: openProvider bool init(bluetooth::common::MessageLoopThread* message_loop, - bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port); + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port, bool offload_enabled); // Clean up BluetoothAudio HAL void cleanup(); diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 4fda9ca0860..b269b477ec5 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -384,7 +384,8 @@ static void btif_a2dp_source_init_delayed(void) { // the provider needs to be initialized earlier in order to ensure // get_a2dp_configuration and parse_a2dp_configuration can be // invoked before the stream is started. - bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port); + bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port, + btif_av_is_a2dp_offload_enabled()); } bool btif_a2dp_source_startup(void) { @@ -412,7 +413,8 @@ static void btif_a2dp_source_startup_delayed() { log::fatal("unable to enable real time scheduling"); #endif } - if (!bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port)) { + if (!bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port, + btif_av_is_a2dp_offload_enabled())) { log::warn("Failed to setup the bluetooth audio HAL"); } btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateRunning); diff --git a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc index e4ff3ef9eee..ad155c7c190 100644 --- a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc +++ b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc @@ -126,9 +126,10 @@ std::optional provider::get_a2dp_configuration( peer_address, remote_seps, user_preferences); } bool init(bluetooth::common::MessageLoopThread* message_loop, - bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port, bool offload_enabled) { inc_func_call_count(__func__); - return test::mock::audio_hal_interface_a2dp_encoding::init(message_loop, audio_port); + return test::mock::audio_hal_interface_a2dp_encoding::init(message_loop, audio_port, + offload_enabled); } bool is_hal_enabled() { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h index f56ac74365e..e35853b2b1e 100644 --- a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h +++ b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h @@ -137,14 +137,14 @@ extern struct get_a2dp_configuration get_a2dp_configuration; struct init { static bool return_value; std::function + bluetooth::audio::a2dp::BluetoothAudioPort const*, bool)> body{[](bluetooth::common::MessageLoopThread* /* message_loop */, - bluetooth::audio::a2dp::BluetoothAudioPort const* /* audio_port */) { - return return_value; - }}; + bluetooth::audio::a2dp::BluetoothAudioPort const* /* audio_port */, + bool /* offload_enabled */) { return return_value; }}; bool operator()(bluetooth::common::MessageLoopThread* message_loop, - bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port) { - return body(message_loop, audio_port); + bluetooth::audio::a2dp::BluetoothAudioPort const* audio_port, + bool offload_enabled) { + return body(message_loop, audio_port, offload_enabled); } }; extern struct init init; -- GitLab From 0dafa1102ee5a6a6dc88fbf8e88b06c46162bbda Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 30 Sep 2024 16:41:40 -0700 Subject: [PATCH 103/875] btif: Remove unused methods DeleteActivePeer Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: I902f5457df16650eafb81edeb3dd350a1c17a89d --- system/btif/src/btif_av.cc | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 44d799394bf..277dc493e1c 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -538,18 +538,6 @@ public: return true; } - void DeleteActivePeer(void) { - log::info("active_peer={}", active_peer_); - - std::promise shutdown_complete_promise; - if (!bta_av_co_set_active_source_peer(RawAddress::kEmpty)) { - log::warn("unable to set active peer to empty in BtaAvCo"); - } - btif_a2dp_source_end_session(active_peer_); - btif_a2dp_source_shutdown(std::move(shutdown_complete_promise)); - active_peer_ = RawAddress::kEmpty; - } - /** * Update source codec configuration for a peer. * @@ -722,18 +710,6 @@ public: return true; } - void DeleteActivePeer(void) { - log::info("active_peer={}", active_peer_); - - if (!bta_av_co_set_active_sink_peer(RawAddress::kEmpty)) { - log::warn("unable to set active peer to empty in BtaAvCo"); - } - - btif_a2dp_sink_end_session(active_peer_); - btif_a2dp_sink_shutdown(); - active_peer_ = RawAddress::kEmpty; - } - /** * Get number of saved peers. */ -- GitLab From 24ed4cfdd93724f7294908e74d9ed870537656c0 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Mon, 26 Aug 2024 15:56:15 +0800 Subject: [PATCH 104/875] hh: disconnect if UHID is not ready after 10 seconds It's possible, e.g. due to a bad driver, for us to never receive UHID OPEN event, thus making the device forever stuck in not ready state. While this is not a problem by itself, the flag hid_report_queuing queues any incoming input event during this whole time, so it will waste memory, especially if the device is very actively sending input events. Disconnect the device if UHID is not ready after 10 seconds. Bug: 359134513 Bug: 362665394 Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.close_hid_if_uhid_ready_too_slow Change-Id: I84cdd578cacfa68c21782e5a52b83184b0776fac --- system/bta/include/bta_hh_co.h | 2 +- system/btif/co/bta_hh_co.cc | 53 +++++++++++++++++++++++++++------- system/btif/include/btif_hh.h | 3 +- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/system/bta/include/bta_hh_co.h b/system/bta/include/bta_hh_co.h index b291459f710..fe9e90a542b 100644 --- a/system/bta/include/bta_hh_co.h +++ b/system/bta/include/bta_hh_co.h @@ -41,7 +41,7 @@ typedef struct { typedef enum : uint8_t { BTA_HH_UHID_INBOUND_INPUT_EVT, - BTA_HH_UHID_INBOUND_OPEN_TIMEOUT_EVT, + BTA_HH_UHID_INBOUND_READY_EVT, BTA_HH_UHID_INBOUND_CLOSE_EVT, BTA_HH_UHID_INBOUND_DSCP_EVT, BTA_HH_UHID_INBOUND_GET_REPORT_EVT, diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index dfe83e42a29..9165b9ce7e5 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -58,6 +58,9 @@ static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; #define BTA_HH_UHID_POLL_PERIOD2_MS -1 /* Max number of polling interrupt allowed */ #define BTA_HH_UHID_INTERRUPT_COUNT_MAX 100 +/* Disconnect if UHID isn't ready after this many milliseconds. */ +#define BTA_HH_UHID_READY_DISCONN_TIMEOUT_MS 10000 +#define BTA_HH_UHID_READY_SHORT_DISCONN_TIMEOUT_MS 2000 using namespace bluetooth; @@ -208,21 +211,35 @@ static void uhid_set_ready(btif_hh_uhid_t* p_uhid) { } // This runs on main thread. -static void uhid_open_timeout(void* data) { +static void uhid_delayed_ready_cback(void* data) { int send_fd = PTR_TO_INT(data); tBTA_HH_TO_UHID_EVT ev = {}; // Notify the UHID thread that the timer has expired. - log::verbose("UHID Open timeout evt"); - ev.type = BTA_HH_UHID_INBOUND_OPEN_TIMEOUT_EVT; + log::verbose("UHID delayed ready evt"); + ev.type = BTA_HH_UHID_INBOUND_READY_EVT; to_uhid_thread(send_fd, &ev, 0); } +// This runs on main thread. +static void uhid_ready_disconn_timeout(void* data) { + int dev_handle = PTR_TO_INT(data); + + log::verbose("UHID ready disconn timeout evt"); + BTA_HhClose(dev_handle); +} + static void uhid_on_open(btif_hh_uhid_t* p_uhid) { - if (p_uhid->ready_for_data || alarm_is_scheduled(p_uhid->ready_timer)) { + if (p_uhid->ready_for_data || alarm_is_scheduled(p_uhid->delayed_ready_timer)) { return; } + if (com::android::bluetooth::flags::close_hid_if_uhid_ready_too_slow()) { + if (alarm_is_scheduled(p_uhid->ready_disconn_timer)) { + alarm_cancel(p_uhid->ready_disconn_timer); + } + } + // On some platforms delay is required, because even though UHID has indicated // ready, the input events might still not be processed, and therefore lost. // If it's not required, immediately set UHID as ready. @@ -232,7 +249,7 @@ static void uhid_on_open(btif_hh_uhid_t* p_uhid) { return; } - alarm_set_on_mloop(p_uhid->ready_timer, ready_delay_ms, uhid_open_timeout, + alarm_set_on_mloop(p_uhid->delayed_ready_timer, ready_delay_ms, uhid_delayed_ready_cback, INT_TO_PTR(p_uhid->internal_send_fd)); } @@ -293,8 +310,18 @@ static int uhid_read_outbound_event(btif_hh_uhid_t* p_uhid) { log::verbose("UHID_CLOSE from uhid-dev\n"); p_uhid->ready_for_data = false; if (com::android::bluetooth::flags::hid_report_queuing()) { - if (alarm_is_scheduled(p_uhid->ready_timer)) { - alarm_cancel(p_uhid->ready_timer); + if (alarm_is_scheduled(p_uhid->delayed_ready_timer)) { + alarm_cancel(p_uhid->delayed_ready_timer); + } + if (com::android::bluetooth::flags::close_hid_if_uhid_ready_too_slow()) { + // It's possible to get OPEN->CLOSE->OPEN sequence from UHID. Therefore, instead of + // immediately disconnecting when receiving CLOSE, here we wait a while and will + // disconnect if we don't receive OPEN before it times out. + if (!alarm_is_scheduled(p_uhid->ready_disconn_timer)) { + alarm_set_on_mloop(p_uhid->ready_disconn_timer, + BTA_HH_UHID_READY_SHORT_DISCONN_TIMEOUT_MS, + uhid_ready_disconn_timeout, INT_TO_PTR(p_uhid->dev_handle)); + } } } break; @@ -380,7 +407,7 @@ static int uhid_read_inbound_event(btif_hh_uhid_t* p_uhid) { uhid_queue_input(p_uhid, &ev.uhid, ret - 1); } break; - case BTA_HH_UHID_INBOUND_OPEN_TIMEOUT_EVT: + case BTA_HH_UHID_INBOUND_READY_EVT: uhid_set_ready(p_uhid); break; case BTA_HH_UHID_INBOUND_CLOSE_EVT: @@ -471,7 +498,8 @@ static void uhid_fd_close(btif_hh_uhid_t* p_uhid) { fixed_queue_free(p_uhid->input_queue, nullptr); p_uhid->input_queue = nullptr; - alarm_free(p_uhid->ready_timer); + alarm_free(p_uhid->delayed_ready_timer); + alarm_free(p_uhid->ready_disconn_timer); osi_free(p_uhid); } } @@ -660,7 +688,12 @@ static void* btif_hh_poll_event_thread(void* arg) { return 0; } p_uhid->ready_for_data = false; - p_uhid->ready_timer = alarm_new("uhid_ready_timer"); + p_uhid->delayed_ready_timer = alarm_new("uhid_delayed_ready_timer"); + p_uhid->ready_disconn_timer = alarm_new("uhid_ready_disconn_timer"); + if (com::android::bluetooth::flags::close_hid_if_uhid_ready_too_slow()) { + alarm_set_on_mloop(p_uhid->ready_disconn_timer, BTA_HH_UHID_READY_DISCONN_TIMEOUT_MS, + uhid_ready_disconn_timeout, INT_TO_PTR(p_uhid->dev_handle)); + } p_uhid->get_rpt_id_queue = fixed_queue_new(SIZE_MAX); log::assert_that(p_uhid->get_rpt_id_queue, "assert failed: p_uhid->get_rpt_id_queue"); diff --git a/system/btif/include/btif_hh.h b/system/btif/include/btif_hh.h index 08173bfe8d2..23a7f76bd41 100644 --- a/system/btif/include/btif_hh.h +++ b/system/btif/include/btif_hh.h @@ -94,7 +94,8 @@ typedef struct { fixed_queue_t* set_rpt_id_queue; #endif // ENABLE_UHID_SET_REPORT fixed_queue_t* input_queue; // to store the inputs before uhid is ready. - alarm_t* ready_timer; + alarm_t* delayed_ready_timer; // to delay marking a device as ready, give input chance to listen. + alarm_t* ready_disconn_timer; // to disconnect device if still not ready after some time. } btif_hh_uhid_t; /* Control block to maintain properties of devices */ -- GitLab From 86b8a0d3298ff681d772f009683d9254393d8de7 Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Tue, 1 Oct 2024 10:25:11 +0000 Subject: [PATCH 105/875] flags: leaudio_sort_scans_to_sync_by_fails Sort scan results for source sync by fails counter Bug: 370639684 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: I6bb2f40c9cb5e3ccb5ccb680090c63398b6bdff4 --- flags/leaudio.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 26382229e8d..e21901fee8d 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -379,3 +379,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "leaudio_sort_scans_to_sync_by_fails" + namespace: "bluetooth" + description: "Sort scan results for source sync by fails counter" + bug: "370639684" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 7700e22ee88cb087984a7c53e6847817fcc34a26 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 20 Sep 2024 22:37:13 +0000 Subject: [PATCH 106/875] System property for changing minimum key size Introducing a system property to allow increasing the minimum key size from default of 7 octets. System property: bluetooth.gap.min_key_size Test: mmm pacakges/modules/Bluetooth Flag: EXEMPT guarded by system property Bug: 362624309 Change-Id: Idaa7eb191158d8487437642b2f2f7f5492619a88 --- sysprop/Android.bp | 1 + sysprop/BUILD.gn | 1 + .../exported_include/android_bluetooth_sysprop.h | 1 + sysprop/gap.sysprop | 12 ++++++++++++ system/gd/hci/BUILD.gn | 1 + system/gd/hci/controller.cc | 12 ++++++++++-- system/stack/btm/btm_sec.cc | 16 +++++++++++++--- 7 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 sysprop/gap.sysprop diff --git a/sysprop/Android.bp b/sysprop/Android.bp index c2e71a97c81..1b72eb4cb7a 100644 --- a/sysprop/Android.bp +++ b/sysprop/Android.bp @@ -11,6 +11,7 @@ sysprop_library { "ble.sysprop", "bta.sysprop", "device_id.sysprop", + "gap.sysprop", "hfp.sysprop", ], property_owner: "Platform", diff --git a/sysprop/BUILD.gn b/sysprop/BUILD.gn index 09126c8df00..407b7a88fcc 100644 --- a/sysprop/BUILD.gn +++ b/sysprop/BUILD.gn @@ -7,6 +7,7 @@ sysprop("libcom.android.sysprop.bluetooth") { "ble.sysprop", "bta.sysprop", "device_id.sysprop", + "gap.sysprop", "hfp.sysprop", ] deps = [ "//bt/floss/android-base:android-base" ] diff --git a/sysprop/exported_include/android_bluetooth_sysprop.h b/sysprop/exported_include/android_bluetooth_sysprop.h index 50553ecc5b9..8d5122d8e22 100644 --- a/sysprop/exported_include/android_bluetooth_sysprop.h +++ b/sysprop/exported_include/android_bluetooth_sysprop.h @@ -21,4 +21,5 @@ #include #include #include +#include #include diff --git a/sysprop/gap.sysprop b/sysprop/gap.sysprop new file mode 100644 index 00000000000..e9f7e00a3c0 --- /dev/null +++ b/sysprop/gap.sysprop @@ -0,0 +1,12 @@ +module: "android.sysprop.bluetooth.Gap" +owner: Platform + +prop { + api_name: "min_key_size" + type: Integer + scope: Internal + access: Readonly + prop_name: "bluetooth.gap.min_key_size" +} + + diff --git a/system/gd/hci/BUILD.gn b/system/gd/hci/BUILD.gn index d7366c33b2a..8f65671fd77 100644 --- a/system/gd/hci/BUILD.gn +++ b/system/gd/hci/BUILD.gn @@ -43,6 +43,7 @@ source_set("BluetoothHciSources") { deps = [ "//bt/flags:bluetooth_flags_c_lib", "//bt/system/gd:gd_default_deps", + "//bt/sysprop:libcom.android.sysprop.bluetooth", ] configs += [ diff --git a/system/gd/hci/controller.cc b/system/gd/hci/controller.cc index 3a4ab17dfb6..9a3f7211107 100644 --- a/system/gd/hci/controller.cc +++ b/system/gd/hci/controller.cc @@ -16,6 +16,7 @@ #include "hci/controller.h" +#include #include #include @@ -39,7 +40,9 @@ namespace bluetooth { namespace hci { -constexpr uint8_t kMinEncryptionKeySize = 7; // #define MIN_ENCRYPTION_KEY_SIZE 7 +constexpr int kMinEncryptionKeySize = 7; +constexpr int kMinEncryptionKeySizeDefault = kMinEncryptionKeySize; +constexpr int kMaxEncryptionKeySize = 16; constexpr bool kDefaultVendorCapabilitiesEnabled = true; static const std::string kPropertyVendorCapabilitiesEnabled = @@ -107,8 +110,13 @@ struct Controller::impl { handler->BindOnceOn(this, &Controller::impl::read_buffer_size_complete_handler)); if (is_supported(OpCode::SET_MIN_ENCRYPTION_KEY_SIZE)) { + uint8_t min_key_size = + (uint8_t)std::min(std::max(android::sysprop::bluetooth::Gap::min_key_size().value_or( + kMinEncryptionKeySizeDefault), + kMinEncryptionKeySize), + kMaxEncryptionKeySize); hci_->EnqueueCommand( - SetMinEncryptionKeySizeBuilder::Create(kMinEncryptionKeySize), + SetMinEncryptionKeySizeBuilder::Create(min_key_size), handler->BindOnceOn(this, &Controller::impl::set_min_encryption_key_size_handler)); } diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index d458bf79a86..e647715e40b 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -26,6 +26,7 @@ #include "stack/btm/btm_sec.h" +#include #include #include #include @@ -3365,7 +3366,16 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_en } } -constexpr uint8_t MIN_KEY_SIZE = 7; +constexpr int MIN_KEY_SIZE = 7; +constexpr int MIN_KEY_SIZE_DEFAULT = MIN_KEY_SIZE; +constexpr int MAX_KEY_SIZE = 16; +static uint8_t get_min_enc_key_size() { + static uint8_t min_key_size = (uint8_t)std::min( + std::max(android::sysprop::bluetooth::Gap::min_key_size().value_or(MIN_KEY_SIZE_DEFAULT), + MIN_KEY_SIZE), + MAX_KEY_SIZE); + return min_key_size; +} static void read_encryption_key_size_complete_after_encryption_change(uint8_t status, uint16_t handle, @@ -3386,7 +3396,7 @@ static void read_encryption_key_size_complete_after_encryption_change(uint8_t st return; } - if (key_size < MIN_KEY_SIZE) { + if (key_size < get_min_enc_key_size()) { log::error("encryption key too short, disconnecting. handle:0x{:x},key_size:{}", handle, key_size); @@ -3961,7 +3971,7 @@ static void read_encryption_key_size_complete_after_key_refresh(uint8_t status, return; } - if (key_size < MIN_KEY_SIZE) { + if (key_size < get_min_enc_key_size()) { log::error("encryption key too short, disconnecting. handle: 0x{:x} key_size {}", handle, key_size); -- GitLab From dffb079b535b47da88e28db7c75b351e9bd1574c Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Tue, 1 Oct 2024 17:03:11 +0000 Subject: [PATCH 107/875] Remove sink_audio_policy_handover flag The change is in nextfood and rolled out to public, so remove the flag Bug: 305636605 Bug: 333562819 Change-Id: I27ee4a3eb728671b92b16505e78afe3706fe5a80 Test: atest HeadsetServiceTest Flag: com::android::bluetooth::flags::sink_audio_policy_handover --- .../android/bluetooth/hfp/HeadsetService.java | 23 +++++++++---------- flags/hfp.aconfig | 10 -------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index 9cba675ff6e..15f16e379b1 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -2046,18 +2046,17 @@ public class HeadsetService extends ProfileService { * it to set fallback device be active. */ removeActiveDevice(); - if (Flags.sinkAudioPolicyHandover()) { - BluetoothDevice fallbackDevice = getFallbackDevice(); - if (fallbackDevice != null - && getConnectionState(fallbackDevice) - == BluetoothProfile.STATE_CONNECTED) { - Log.d( - TAG, - "BluetoothSinkAudioPolicy set fallbackDevice=" - + fallbackDevice - + " active"); - setActiveDevice(fallbackDevice); - } + + BluetoothDevice fallbackDevice = getFallbackDevice(); + if (fallbackDevice != null + && getConnectionState(fallbackDevice) + == BluetoothProfile.STATE_CONNECTED) { + Log.d( + TAG, + "BluetoothSinkAudioPolicy set fallbackDevice=" + + fallbackDevice + + " active"); + setActiveDevice(fallbackDevice); } } } diff --git a/flags/hfp.aconfig b/flags/hfp.aconfig index a27c7806800..96985f27508 100644 --- a/flags/hfp.aconfig +++ b/flags/hfp.aconfig @@ -39,16 +39,6 @@ flag { } } -flag { - name: "sink_audio_policy_handover" - namespace: "bluetooth" - description: "If sink audio policy makes device active for call, then resume past active device" - bug: "333562819" - metadata { - purpose: PURPOSE_BUGFIX - } -} - flag { name: "fix_hfp_qual_1_9" namespace: "bluetooth" -- GitLab From 5d45ae436fb0c6d2341257d7a8c472764954302e Mon Sep 17 00:00:00 2001 From: Cheng Li Date: Mon, 30 Sep 2024 18:14:53 +0000 Subject: [PATCH 108/875] Add flag to control snoop logger tracing Change-Id: I9bbaabd9839a06395d956ceadcacf2b0f8573ee7 Test: m Flag: com.android.bluetooth.flags.snoop_logger_tracing Bug: 369428038 Bug: 365778358 Bug: 315241296 --- flags/hal.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/hal.aconfig b/flags/hal.aconfig index 5f0177c56f9..286d1fceb4a 100644 --- a/flags/hal.aconfig +++ b/flags/hal.aconfig @@ -10,3 +10,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "snoop_logger_tracing" + namespace: "bluetooth" + description: "Add snoop logger tracing" + bug: "369428038" + metadata { + purpose: PURPOSE_BUGFIX + } +} \ No newline at end of file -- GitLab From 74d136c5cade7a97f2e54f1fbe0f917703fb5b80 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Tue, 1 Oct 2024 17:44:16 +0000 Subject: [PATCH 109/875] add @Override annotation Flag: EXEMPT, just annotation Bug: 349479600 Test: m -j; Change-Id: I71442afbce5ab511e51e173d92552f39fee79076 --- .../com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java | 1 + .../com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java | 1 + 2 files changed, 2 insertions(+) diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java index b66295d43e2..5565fbd87db 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java @@ -280,6 +280,7 @@ public class BluetoothPbapCallLogComposer implements AutoCloseable { } /** Closes the composer, releasing all of its resources. */ + @Override public void close() { if (mCursor != null) { try { diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java index ac65f6c78e0..8f894848dd9 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java @@ -194,6 +194,7 @@ public class BluetoothPbapSimVcardManager implements AutoCloseable { } /** Closes the manager, releasing all of its resources. */ + @Override public void close() { if (mCursor != null) { try { -- GitLab From f787f083cea0be61788673127a97d0b7deea30ba Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 14 May 2024 15:37:10 +0000 Subject: [PATCH 110/875] Add new APIs of channel sounding 1. DistanceMeasurementResult#getElapsedRealtimeNanos 2. DistanceMeasurementMethod#getMethodId Flag: com.android.bluetooth.flags.channel_sounding_25q2_apis Bug: 367409858 Bug: 340528388 Test: m com.andorid.btservices Change-Id: I1827594fbc3a0e75d271e78a955690cbf827a5ba --- .../app/jni/com_android_bluetooth_gatt.cpp | 13 +++--- .../gatt/DistanceMeasurementManager.java | 2 + .../DistanceMeasurementNativeInterface.java | 2 + .../gatt/DistanceMeasurementManagerTest.java | 3 ++ flags/ranging.aconfig | 10 ++++- framework/api/system-current.txt | 5 ++- .../le/DistanceMeasurementMethod.java | 22 +++++++--- .../le/DistanceMeasurementResult.java | 42 ++++++++++++++++++- system/gd/hci/distance_measurement_manager.cc | 12 +++++- system/gd/hci/distance_measurement_manager.h | 2 +- .../hci/distance_measurement_manager_mock.h | 2 +- .../hardware/distance_measurement_interface.h | 3 +- .../main/shim/distance_measurement_manager.cc | 12 +++--- 13 files changed, 103 insertions(+), 27 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index fe17a63b8be..d3008be475e 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -1231,17 +1231,18 @@ public: void OnDistanceMeasurementResult(RawAddress address, uint32_t centimeter, uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, - int error_altitude_angle, uint8_t method) { + int error_altitude_angle, long elapsedRealtimeNanos, + uint8_t method) { std::shared_lock lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mDistanceMeasurementCallbacksObj) { return; } ScopedLocalRef addr(sCallbackEnv.get(), bdaddr2newjstr(sCallbackEnv.get(), &address)); - sCallbackEnv->CallVoidMethod(mDistanceMeasurementCallbacksObj, - method_onDistanceMeasurementResult, addr.get(), centimeter, - error_centimeter, azimuth_angle, error_azimuth_angle, - altitude_angle, error_altitude_angle, method); + sCallbackEnv->CallVoidMethod( + mDistanceMeasurementCallbacksObj, method_onDistanceMeasurementResult, addr.get(), + centimeter, error_centimeter, azimuth_angle, error_azimuth_angle, altitude_angle, + error_altitude_angle, elapsedRealtimeNanos, method); } }; @@ -2826,7 +2827,7 @@ static int register_com_android_bluetooth_gatt_distance_measurement(JNIEnv* env) &method_onDistanceMeasurementStartFail}, {"onDistanceMeasurementStopped", "(Ljava/lang/String;II)V", &method_onDistanceMeasurementStopped}, - {"onDistanceMeasurementResult", "(Ljava/lang/String;IIIIIII)V", + {"onDistanceMeasurementResult", "(Ljava/lang/String;IIIIIIJI)V", &method_onDistanceMeasurementResult}, }; GET_JAVA_METHODS(env, "com/android/bluetooth/gatt/DistanceMeasurementNativeInterface", diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java index b4070b3bcac..95868961183 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java @@ -468,6 +468,7 @@ public class DistanceMeasurementManager { int errorAzimuthAngle, int altitudeAngle, int errorAltitudeAngle, + long elapsedRealtimeNanos, int method) { logd( "onDistanceMeasurementResult " @@ -476,6 +477,7 @@ public class DistanceMeasurementManager { + centimeter); DistanceMeasurementResult result = new DistanceMeasurementResult.Builder(centimeter / 100.0, errorCentimeter / 100.0) + .setMeasurementTimestampNanos(elapsedRealtimeNanos) .build(); switch (method) { case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java index 4378d9d9db0..223e36556fb 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java @@ -110,6 +110,7 @@ public class DistanceMeasurementNativeInterface { int errorAzimuthAngle, int altitudeAngle, int errorAltitudeAngle, + long elapsedRealtimeNanos, int method) { mDistanceMeasurementManager.onDistanceMeasurementResult( address, @@ -119,6 +120,7 @@ public class DistanceMeasurementNativeInterface { errorAzimuthAngle, altitudeAngle, errorAltitudeAngle, + elapsedRealtimeNanos, method); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java index 829b39e9c7a..ca85b26668f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java @@ -196,6 +196,7 @@ public class DistanceMeasurementManagerTest { -1, -1, -1, + 1000L, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); ArgumentCaptor result = ArgumentCaptor.forClass(DistanceMeasurementResult.class); @@ -206,6 +207,7 @@ public class DistanceMeasurementManagerTest { assertThat(result.getValue().getErrorAzimuthAngle()).isEqualTo(Double.NaN); assertThat(result.getValue().getAltitudeAngle()).isEqualTo(Double.NaN); assertThat(result.getValue().getErrorAltitudeAngle()).isEqualTo(Double.NaN); + assertThat(result.getValue().getMeasurementTimestampNanos()).isEqualTo(1000L); } @Test @@ -232,6 +234,7 @@ public class DistanceMeasurementManagerTest { -1, -1, -1, + 1000L, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); DistanceMeasurementResult result = new DistanceMeasurementResult.Builder(1.00, 1.00).build(); diff --git a/flags/ranging.aconfig b/flags/ranging.aconfig index 49dc920b52c..6b750031639 100644 --- a/flags/ranging.aconfig +++ b/flags/ranging.aconfig @@ -14,4 +14,12 @@ flag { namespace: "bluetooth" description: "Enable Channel Sounding in the Bluetooth stack" bug: "324185011" -} \ No newline at end of file +} + +flag { + name:"channel_sounding_25q2_apis" + namespace: "bluetooth" + is_exported: true + description: "Add new APIs for channel sounding" + bug: "367409858" +} diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 783635e7d45..a95e03cf52e 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -1292,7 +1292,8 @@ package android.bluetooth.le { public final class DistanceMeasurementMethod implements android.os.Parcelable { method public int describeContents(); - method public double getId(); + method @Deprecated @FlaggedApi("com.android.bluetooth.flags.channel_sounding_25q2_apis") public double getId(); + method @FlaggedApi("com.android.bluetooth.flags.channel_sounding_25q2_apis") public int getMethodId(); method public boolean isAltitudeAngleSupported(); method public boolean isAzimuthAngleSupported(); method public void writeToParcel(android.os.Parcel, int); @@ -1344,6 +1345,7 @@ package android.bluetooth.le { method public double getErrorAltitudeAngle(); method public double getErrorAzimuthAngle(); method @FloatRange(from=0.0) public double getErrorMeters(); + method @FlaggedApi("com.android.bluetooth.flags.channel_sounding_25q2_apis") public long getMeasurementTimestampNanos(); method public double getResultMeters(); method @FlaggedApi("com.android.bluetooth.flags.channel_sounding") public double getVelocityMetersPerSecond(); method public void writeToParcel(android.os.Parcel, int); @@ -1368,6 +1370,7 @@ package android.bluetooth.le { method @FlaggedApi("com.android.bluetooth.flags.channel_sounding") @NonNull public android.bluetooth.le.DistanceMeasurementResult.Builder setDetectedAttackLevel(int); method @NonNull public android.bluetooth.le.DistanceMeasurementResult.Builder setErrorAltitudeAngle(@FloatRange(from=0.0, to=180.0) double); method @NonNull public android.bluetooth.le.DistanceMeasurementResult.Builder setErrorAzimuthAngle(@FloatRange(from=0.0, to=360.0) double); + method @FlaggedApi("com.android.bluetooth.flags.channel_sounding_25q2_apis") @NonNull public android.bluetooth.le.DistanceMeasurementResult.Builder setMeasurementTimestampNanos(long); method @FlaggedApi("com.android.bluetooth.flags.channel_sounding") @NonNull public android.bluetooth.le.DistanceMeasurementResult.Builder setVelocityMetersPerSecond(double); } diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java b/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java index a6fcff8c4d3..26cfc191ec2 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java @@ -88,13 +88,28 @@ public final class DistanceMeasurementMethod implements Parcelable { * Id of the method used for {@link DistanceMeasurementParams.Builder#setMethod(int)} * * @return id of the method + * @deprecated use {@link #getMethodId} instead. * @hide */ + @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING_25Q2_APIS) + @Deprecated @SystemApi public @DistanceMeasurementMethodId double getId() { return mId; } + /** + * Id of the method used for {@link DistanceMeasurementParams.Builder#setMethodId(int)} + * + * @return ID of the measurement method + * @hide + */ + @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING_25Q2_APIS) + @SystemApi + public @DistanceMeasurementMethodId int getMethodId() { + return mId; + } + /** * Checks whether the azimuth angle is supported for this method. * @@ -161,12 +176,7 @@ public final class DistanceMeasurementMethod implements Parcelable { if (!(o instanceof DistanceMeasurementMethod)) return false; final DistanceMeasurementMethod u = (DistanceMeasurementMethod) o; - - if (mId != u.getId()) { - return false; - } - - return true; + return mId == u.mId; } @Override diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementResult.java b/framework/java/android/bluetooth/le/DistanceMeasurementResult.java index 7c2815f52ed..9fb3416a85f 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementResult.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementResult.java @@ -16,6 +16,7 @@ package android.bluetooth.le; +import android.annotation.ElapsedRealtimeLong; import android.annotation.FlaggedApi; import android.annotation.FloatRange; import android.annotation.IntDef; @@ -140,6 +141,7 @@ public final class DistanceMeasurementResult implements Parcelable { private final double mConfidenceLevel; private final int mDetectedAttackLevel; private final double mVelocityMetersPerSecond; + private final @ElapsedRealtimeLong long mMeasurementTimestampNanos; private DistanceMeasurementResult( double meters, @@ -151,7 +153,8 @@ public final class DistanceMeasurementResult implements Parcelable { double delaySpreadMeters, double confidenceLevel, @Nadm int detectedAttackLevel, - double velocityMetersPerSecond) { + double velocityMetersPerSecond, + @ElapsedRealtimeLong long measurementTimestampNanos) { mMeters = meters; mErrorMeters = errorMeters; mAzimuthAngle = azimuthAngle; @@ -162,6 +165,7 @@ public final class DistanceMeasurementResult implements Parcelable { mConfidenceLevel = confidenceLevel; mDetectedAttackLevel = detectedAttackLevel; mVelocityMetersPerSecond = velocityMetersPerSecond; + mMeasurementTimestampNanos = measurementTimestampNanos; } /** @@ -312,6 +316,19 @@ public final class DistanceMeasurementResult implements Parcelable { return mVelocityMetersPerSecond; } + /** + * Timestamp of this distance measurement in time since boot nanos in the same namespace as + * {@link SystemClock#elapsedRealtimeNanos()} + * + * @return timestamp of ranging measurement in nanoseconds + * @hide + */ + @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING_25Q2_APIS) + @SystemApi + public @ElapsedRealtimeLong long getMeasurementTimestampNanos() { + return mMeasurementTimestampNanos; + } + /** * {@inheritDoc} * @@ -339,6 +356,7 @@ public final class DistanceMeasurementResult implements Parcelable { out.writeDouble(mConfidenceLevel); out.writeInt(mDetectedAttackLevel); out.writeDouble(mVelocityMetersPerSecond); + out.writeLong(mMeasurementTimestampNanos); } /** @@ -367,6 +385,8 @@ public final class DistanceMeasurementResult implements Parcelable { + mDetectedAttackLevel + ", velocityMetersPerSecond: " + mVelocityMetersPerSecond + + ", elapsedRealtimeNanos" + + mMeasurementTimestampNanos + "]"; } @@ -384,6 +404,7 @@ public final class DistanceMeasurementResult implements Parcelable { .setConfidenceLevel(in.readDouble()) .setDetectedAttackLevel(in.readInt()) .setVelocityMetersPerSecond(in.readDouble()) + .setMeasurementTimestampNanos(in.readLong()) .build(); } @@ -410,6 +431,7 @@ public final class DistanceMeasurementResult implements Parcelable { private double mConfidenceLevel = Double.NaN; private int mDetectedAttackLevel = NADM_UNKNOWN; private double mVelocityMetersPerSecond = Double.NaN; + private @ElapsedRealtimeLong long mMeasurementTimestampNanos = -1L; /** * Constructor of the Builder. @@ -587,6 +609,21 @@ public final class DistanceMeasurementResult implements Parcelable { return this; } + /** + * Set the elapsed realtime in nanoseconds when the distance measurement occurred + * + * @param measurementTimestampNanos time the distance measurement occurred + * @hide + */ + @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING_25Q2_APIS) + @SystemApi + @NonNull + public Builder setMeasurementTimestampNanos( + @ElapsedRealtimeLong long measurementTimestampNanos) { + mMeasurementTimestampNanos = measurementTimestampNanos; + return this; + } + /** * Builds the {@link DistanceMeasurementResult} object. * @@ -606,7 +643,8 @@ public final class DistanceMeasurementResult implements Parcelable { mDelaySpreadMeters, mConfidenceLevel, mDetectedAttackLevel, - mVelocityMetersPerSecond); + mVelocityMetersPerSecond, + mMeasurementTimestampNanos); } } } diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index d7bcbe477d1..6949069a0b1 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -212,9 +213,12 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } log::debug("address {}, resultMeters {}", cs_trackers_[connection_handle].address, ranging_result.result_meters_); + using namespace std::chrono; + long elapsedRealtimeNanos = + duration_cast(steady_clock::now().time_since_epoch()).count(); distance_measurement_callbacks_->OnDistanceMeasurementResult( cs_trackers_[connection_handle].address, ranging_result.result_meters_ * 100, 0.0, -1, - -1, -1, -1, DistanceMeasurementMethod::METHOD_CS); + -1, -1, -1, elapsedRealtimeNanos, DistanceMeasurementMethod::METHOD_CS); } ~impl() {} @@ -1474,8 +1478,12 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { int8_t rssi = complete_view.GetRssi(); double pow_value = (remote_tx_power - rssi - kRSSIDropOffAt1M) / 20.0; double distance = pow(10.0, pow_value); + + using namespace std::chrono; + long elapsedRealtimeNanos = + duration_cast(steady_clock::now().time_since_epoch()).count(); distance_measurement_callbacks_->OnDistanceMeasurementResult( - address, distance * 100, distance * 100, -1, -1, -1, -1, + address, distance * 100, distance * 100, -1, -1, -1, -1, elapsedRealtimeNanos, DistanceMeasurementMethod::METHOD_RSSI); } diff --git a/system/gd/hci/distance_measurement_manager.h b/system/gd/hci/distance_measurement_manager.h index ee7ba9ee0e2..cdf9a780dc4 100644 --- a/system/gd/hci/distance_measurement_manager.h +++ b/system/gd/hci/distance_measurement_manager.h @@ -59,7 +59,7 @@ public: virtual void OnDistanceMeasurementResult(Address address, uint32_t centimeter, uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, - int error_altitude_angle, + int error_altitude_angle, long elapsedRealtimeNanos, DistanceMeasurementMethod method) = 0; virtual void OnRasFragmentReady(Address address, uint16_t procedure_counter, bool is_last, std::vector raw_data) = 0; diff --git a/system/gd/hci/distance_measurement_manager_mock.h b/system/gd/hci/distance_measurement_manager_mock.h index 7813969bff3..6561c18d8cf 100644 --- a/system/gd/hci/distance_measurement_manager_mock.h +++ b/system/gd/hci/distance_measurement_manager_mock.h @@ -37,7 +37,7 @@ class MockDistanceMeasurementCallbacks : public DistanceMeasurementCallbacks { MOCK_METHOD(void, OnDistanceMeasurementStopped, (Address, DistanceMeasurementErrorCode, DistanceMeasurementMethod)); MOCK_METHOD(void, OnDistanceMeasurementResult, - (Address, uint32_t, uint32_t, int, int, int, int, DistanceMeasurementMethod)); + (Address, uint32_t, uint32_t, int, int, int, int, long, DistanceMeasurementMethod)); }; class MockDistanceMeasurementManager : public DistanceMeasurementManager { diff --git a/system/include/hardware/distance_measurement_interface.h b/system/include/hardware/distance_measurement_interface.h index 4472e318d4c..ed382d32e09 100644 --- a/system/include/hardware/distance_measurement_interface.h +++ b/system/include/hardware/distance_measurement_interface.h @@ -33,7 +33,8 @@ public: virtual void OnDistanceMeasurementResult(RawAddress address, uint32_t centimeter, uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, - int error_altitude_angle, uint8_t method) = 0; + int error_altitude_angle, long elapsedRealtimeNanos, + uint8_t method) = 0; }; class DistanceMeasurementInterface { diff --git a/system/main/shim/distance_measurement_manager.cc b/system/main/shim/distance_measurement_manager.cc index 22b540c3c52..b54fc1ce345 100644 --- a/system/main/shim/distance_measurement_manager.cc +++ b/system/main/shim/distance_measurement_manager.cc @@ -118,13 +118,13 @@ public: void OnDistanceMeasurementResult(bluetooth::hci::Address address, uint32_t centimeter, uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, - int error_altitude_angle, + int error_altitude_angle, long elapsedRealtimeNanos, DistanceMeasurementMethod method) override { - do_in_jni_thread(base::BindOnce(&::DistanceMeasurementCallbacks::OnDistanceMeasurementResult, - base::Unretained(distance_measurement_callbacks_), - bluetooth::ToRawAddress(address), centimeter, error_centimeter, - azimuth_angle, error_azimuth_angle, altitude_angle, - error_altitude_angle, static_cast(method))); + do_in_jni_thread(base::BindOnce( + &::DistanceMeasurementCallbacks::OnDistanceMeasurementResult, + base::Unretained(distance_measurement_callbacks_), bluetooth::ToRawAddress(address), + centimeter, error_centimeter, azimuth_angle, error_azimuth_angle, altitude_angle, + error_altitude_angle, elapsedRealtimeNanos, static_cast(method))); } void OnRasFragmentReady(bluetooth::hci::Address address, uint16_t procedure_counter, bool is_last, -- GitLab From 8c49b368bc8b6fd0da02552e6d2503042ce68ce9 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Tue, 1 Oct 2024 20:06:32 +0000 Subject: [PATCH 111/875] Remove leaudio_broadcast_feature_support flag Bug: 316005152 Test: m com.android.btservices Change-Id: I9506690e1a484444a70e4f9ac31cb358e3a6f0e3 --- .../bluetooth/bass_client/BassClientService.java | 4 +--- .../android/bluetooth/le_audio/LeAudioService.java | 4 +--- .../bluetooth/mcp/MediaControlGattService.java | 6 ------ .../bluetooth/le_audio/LeAudioServiceTest.java | 1 - .../bluetooth/mcp/MediaControlGattServiceTest.java | 13 ++++--------- flags/leaudio.aconfig | 7 ------- .../util/src/android/bluetooth/cts/TestUtils.java | 3 --- system/gd/hci/le_periodic_sync_manager.h | 6 ++---- system/gd/hci/le_periodic_sync_manager_test.cc | 4 +--- 9 files changed, 9 insertions(+), 39 deletions(-) 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 05056d68247..76f16edb999 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -26,7 +26,6 @@ import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState; import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment; import static com.android.bluetooth.flags.Flags.leaudioBroadcastAudioHandoverPolicies; import static com.android.bluetooth.flags.Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine; -import static com.android.bluetooth.flags.Flags.leaudioBroadcastFeatureSupport; import static com.android.bluetooth.flags.Flags.leaudioBroadcastMonitorSourceSyncStatus; import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper; @@ -278,8 +277,7 @@ public class BassClientService extends ProfileService { } public static boolean isEnabled() { - return leaudioBroadcastFeatureSupport() - && BluetoothProperties.isProfileBapBroadcastAssistEnabled().orElse(false); + return BluetoothProperties.isProfileBapBroadcastAssistEnabled().orElse(false); } private static class SourceSyncRequest { 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 3dca9d250ad..e03e01a7a72 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -25,7 +25,6 @@ import static com.android.bluetooth.bass_client.BassConstants.INVALID_BROADCAST_ import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask; import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState; import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment; -import static com.android.bluetooth.flags.Flags.leaudioBroadcastFeatureSupport; import static com.android.bluetooth.flags.Flags.leaudioUseAudioModeListener; import static com.android.modules.utils.build.SdkLevel.isAtLeastU; @@ -508,8 +507,7 @@ public class LeAudioService extends ProfileService { } public static boolean isBroadcastEnabled() { - return leaudioBroadcastFeatureSupport() - && BluetoothProperties.isProfileBapBroadcastSourceEnabled().orElse(false); + return BluetoothProperties.isProfileBapBroadcastSourceEnabled().orElse(false); } private boolean registerTmap() { diff --git a/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java b/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java index c229f184ae8..25085f87d22 100644 --- a/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java +++ b/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java @@ -48,7 +48,6 @@ import com.android.bluetooth.BluetoothEventLogger; import com.android.bluetooth.Utils; import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.le_audio.LeAudioService; import com.android.internal.annotations.VisibleForTesting; @@ -2166,11 +2165,6 @@ public class MediaControlGattService implements MediaControlGattServiceInterface * @return {@code true} if is broadcasting audio, {@code false} otherwise */ private boolean isBroadcastActive() { - if (!Flags.leaudioBroadcastFeatureSupport()) { - // disable this if feature flag is false - return false; - } - return mLeAudioService != null && mLeAudioService.isBroadcastActive(); } 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 fb1a2bcac80..ca78b59f0ef 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 @@ -1206,7 +1206,6 @@ public class LeAudioServiceTest { /** Test setting connection policy */ @Test public void testSetConnectionPolicy() { - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_FEATURE_SUPPORT); doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class)); doReturn(true).when(mNativeInterface).disconnectLeAudio(any(BluetoothDevice.class)); doReturn(true) diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java index f024f0c357e..54d8f929d52 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java @@ -34,7 +34,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.flags.Flags; import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; @@ -1037,18 +1036,14 @@ public class MediaControlGattServiceTest { @Test public void testMediaControlPointeRequest_OpcodePlayCallLeAudioServiceSetActiveDevice() { - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_FEATURE_SUPPORT); initAllFeaturesGattService(); prepareConnectedDevice(); mMcpService.updateSupportedOpcodesChar(Request.SupportedOpcodes.PLAY, true); verifyMediaControlPointRequest(Request.Opcodes.PLAY, null, BluetoothGatt.GATT_SUCCESS, 1); - if (!Flags.leaudioBroadcastFeatureSupport()) { - verify(mMockLeAudioService).setActiveDevice(any(BluetoothDevice.class)); - } else { - final List metadataList = mock(List.class); - when(mMockLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); - verify(mMockMcsCallbacks, times(1)).onMediaControlRequest(any(Request.class)); - } + + final List metadataList = mock(List.class); + when(mMockLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); + verify(mMockMcsCallbacks, times(1)).onMediaControlRequest(any(Request.class)); } @Test diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 26382229e8d..669b6325907 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -52,13 +52,6 @@ flag { bug: "312273987" } -flag { - name: "leaudio_broadcast_feature_support" - namespace: "bluetooth" - description: "Le audio broadcast feature roll-out control flag" - bug: "316005152" -} - flag { name: "metadata_api_inactive_audio_device_upon_connection" is_exported: true diff --git a/framework/tests/util/src/android/bluetooth/cts/TestUtils.java b/framework/tests/util/src/android/bluetooth/cts/TestUtils.java index 8f97811a281..4d3a39fe60c 100644 --- a/framework/tests/util/src/android/bluetooth/cts/TestUtils.java +++ b/framework/tests/util/src/android/bluetooth/cts/TestUtils.java @@ -16,7 +16,6 @@ package android.bluetooth.cts; -import static com.android.bluetooth.flags.Flags.leaudioBroadcastFeatureSupport; import static com.android.modules.utils.build.SdkLevel.isAtLeastV; import static com.google.common.truth.Truth.assertThat; @@ -99,12 +98,10 @@ public class TestUtils extends android.bluetooth.test_utils.TestUtils { } case BluetoothProfile.LE_AUDIO_BROADCAST -> { return isAtLeastV() - && leaudioBroadcastFeatureSupport() && BluetoothProperties.isProfileBapBroadcastSourceEnabled().orElse(false); } case BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT -> { return isAtLeastV() - && leaudioBroadcastFeatureSupport() && BluetoothProperties.isProfileBapBroadcastAssistEnabled().orElse(false); } // Hidden profile diff --git a/system/gd/hci/le_periodic_sync_manager.h b/system/gd/hci/le_periodic_sync_manager.h index af6668fba95..97f9769340a 100644 --- a/system/gd/hci/le_periodic_sync_manager.h +++ b/system/gd/hci/le_periodic_sync_manager.h @@ -339,10 +339,8 @@ public: address_with_type, (uint16_t)event_view.GetAdvertiserPhy(), event_view.GetPeriodicAdvertisingInterval()); - if (com::android::bluetooth::flags::leaudio_broadcast_feature_support()) { - if (event_view.GetStatus() != ErrorCode::SUCCESS) { - periodic_syncs_.erase(periodic_sync); - } + if (event_view.GetStatus() != ErrorCode::SUCCESS) { + periodic_syncs_.erase(periodic_sync); } } else { log::debug("[PSync]: Wrong sync state={}", (uint8_t)(periodic_sync->sync_state)); diff --git a/system/gd/hci/le_periodic_sync_manager_test.cc b/system/gd/hci/le_periodic_sync_manager_test.cc index 854e7b393d3..94d7efef10b 100644 --- a/system/gd/hci/le_periodic_sync_manager_test.cc +++ b/system/gd/hci/le_periodic_sync_manager_test.cc @@ -529,9 +529,7 @@ TEST_F(PeriodicSyncManagerTest, handle_sync_lost_test) { sync_handler(); } -TEST_F_WITH_FLAGS(PeriodicSyncManagerTest, handle_advertising_sync_established_after_error_test, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, - leaudio_broadcast_feature_support))) { +TEST_F(PeriodicSyncManagerTest, handle_advertising_sync_established_after_error_test) { uint16_t sync_handle = 0x12; uint8_t advertiser_sid = 0x02; // start scan -- GitLab From b81adc256c06dde5f885d175fdf45ad43c9b03d3 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Tue, 1 Oct 2024 20:17:59 +0000 Subject: [PATCH 112/875] Remove leaudio_broadcast_audio_handover_policies flag Bug: 308171251 Test: m com.android.btservices Change-Id: If13bd4b31c9d7c28fbf672f88982fd66a7f99384 --- .../bass_client/BassClientService.java | 28 +++++-------- .../btservice/ActiveDeviceManager.java | 5 --- .../bluetooth/le_audio/LeAudioService.java | 40 +++++-------------- .../bass_client/BassClientServiceTest.java | 8 ++-- .../btservice/ActiveDeviceManagerTest.java | 4 -- .../le_audio/LeAudioBroadcastServiceTest.java | 1 - .../le_audio/LeAudioServiceTest.java | 1 - flags/leaudio.aconfig | 7 ---- system/bta/le_audio/client.cc | 8 +--- system/bta/le_audio/le_audio_client_test.cc | 13 ------ 10 files changed, 26 insertions(+), 89 deletions(-) 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 76f16edb999..0f2a1daac77 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -24,7 +24,6 @@ import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask; import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState; import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment; -import static com.android.bluetooth.flags.Flags.leaudioBroadcastAudioHandoverPolicies; import static com.android.bluetooth.flags.Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine; import static com.android.bluetooth.flags.Flags.leaudioBroadcastMonitorSourceSyncStatus; import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper; @@ -3245,27 +3244,22 @@ public class BassClientService extends ProfileService { } private boolean isAllowedToAddSource() { - if (leaudioBroadcastAudioHandoverPolicies()) { - /* Check if should wait for status update */ - if (mUnicastSourceStreamStatus.isEmpty()) { - /* Assistant was not active, inform about activation */ - if (!mIsAssistantActive) { - mIsAssistantActive = true; - - LeAudioService leAudioService = mServiceFactory.getLeAudioService(); - if (leAudioService != null) { - leAudioService.activeBroadcastAssistantNotification(true); - } - } + /* Check if should wait for status update */ + if (mUnicastSourceStreamStatus.isEmpty()) { + /* Assistant was not active, inform about activation */ + if (!mIsAssistantActive) { + mIsAssistantActive = true; - return false; + LeAudioService leAudioService = mServiceFactory.getLeAudioService(); + if (leAudioService != null) { + leAudioService.activeBroadcastAssistantNotification(true); + } } - return mUnicastSourceStreamStatus.get() == STATUS_LOCAL_STREAM_SUSPENDED; + return false; } - /* Don't block if this is not a handover case */ - return true; + return mUnicastSourceStreamStatus.get() == STATUS_LOCAL_STREAM_SUSPENDED; } /** Return true if there is any non primary device receiving broadcast */ diff --git a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java index 232e664778e..9286194a540 100644 --- a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +++ b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java @@ -1263,11 +1263,6 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac * @return {@code true} if is broadcasting audio, {@code false} otherwise */ private boolean isBroadcastingAudio() { - if (!Flags.leaudioBroadcastAudioHandoverPolicies()) { - // disable this if feature flag is false - return false; - } - final LeAudioService leAudioService = mFactory.getLeAudioService(); return leAudioService != null && !leAudioService.getAllBroadcastMetadata().isEmpty(); } 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 e03e01a7a72..1f7e07e3173 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -1175,9 +1175,7 @@ public class LeAudioService extends ProfileService { "Unicast group is active, queueing Broadcast creation, while the Unicast" + " group is deactivated."); mCreateBroadcastQueue.add(broadcastSettings); - if (Flags.leaudioBroadcastAudioHandoverPolicies()) { - mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, true); - } + mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, true); removeActiveDevice(true); return; @@ -1422,10 +1420,8 @@ public class LeAudioService extends ProfileService { } Log.d(TAG, "destroyBroadcast"); - if (Flags.leaudioBroadcastAudioHandoverPolicies()) { - mIsSinkStreamMonitorModeEnabled = false; - mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, false); - } + mIsSinkStreamMonitorModeEnabled = false; + mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, false); mLeAudioBroadcasterNativeInterface.destroyBroadcast(broadcastId); } @@ -2235,8 +2231,7 @@ public class LeAudioService extends ProfileService { if (notifyAndUpdateInactiveOutDeviceOnly && ((newSupportedAudioDirections & AUDIO_DIRECTION_INPUT_BIT) != 0)) { newInDevice = getLeadDeviceForTheGroup(groupId); - } else if (Flags.leaudioBroadcastAudioHandoverPolicies() - && mIsSinkStreamMonitorModeEnabled) { + } else if (mIsSinkStreamMonitorModeEnabled) { mIsSinkStreamMonitorModeEnabled = false; mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, false); } @@ -2790,8 +2785,7 @@ public class LeAudioService extends ProfileService { */ boolean leaveConnectedInputDevice = false; Integer newDirections = AUDIO_DIRECTION_NONE; - if (Flags.leaudioBroadcastAudioHandoverPolicies() - && isBroadcastReadyToBeReActivated()) { + if (isBroadcastReadyToBeReActivated()) { leaveConnectedInputDevice = true; newDirections |= AUDIO_DIRECTION_INPUT_BIT; @@ -2879,10 +2873,6 @@ public class LeAudioService extends ProfileService { } private boolean isGroupReceivingBroadcast(int groupId) { - if (!Flags.leaudioBroadcastAudioHandoverPolicies()) { - return false; - } - BassClientService bassClientService = getBassClientService(); if (bassClientService == null) { return false; @@ -3895,10 +3885,8 @@ public class LeAudioService extends ProfileService { } // Notify broadcast assistant - if (Flags.leaudioBroadcastAudioHandoverPolicies()) { - if (bassClientService != null) { - bassClientService.notifyBroadcastStateChanged(descriptor.mState, broadcastId); - } + if (bassClientService != null) { + bassClientService.notifyBroadcastStateChanged(descriptor.mState, broadcastId); } } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_METADATA_CHANGED) { int broadcastId = stackEvent.valueInt1; @@ -3941,10 +3929,8 @@ public class LeAudioService extends ProfileService { if (mAwaitingBroadcastCreateResponse && !areAllGroupsInNotActiveState()) { /* Broadcast would be created once unicast group became inactive */ Log.i(TAG, "Unicast group is active, deactivate due to pending broadcast"); - if (Flags.leaudioBroadcastAudioHandoverPolicies()) { - mIsSinkStreamMonitorModeEnabled = true; - mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, true); - } + mIsSinkStreamMonitorModeEnabled = true; + mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, true); removeActiveDevice(true); } } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_NATIVE_INITIALIZED) { @@ -4287,9 +4273,7 @@ public class LeAudioService extends ProfileService { if (!leaudioUseAudioModeListener()) { /* For setting inCall mode */ - if (Flags.leaudioBroadcastAudioHandoverPolicies() - && inCall - && !areBroadcastsAllStopped()) { + if (inCall && !areBroadcastsAllStopped()) { mQueuedInCallValue = Optional.of(true); /* Request activation of unicast group */ @@ -4304,9 +4288,7 @@ public class LeAudioService extends ProfileService { if (!leaudioUseAudioModeListener()) { /* For clearing inCall mode */ - if (Flags.leaudioBroadcastAudioHandoverPolicies() - && !inCall - && mBroadcastIdDeactivatedForUnicastTransition.isPresent()) { + if (!inCall && mBroadcastIdDeactivatedForUnicastTransition.isPresent()) { handleUnicastStreamStatusChange( LeAudioStackEvent.DIRECTION_SINK, LeAudioStackEvent.STATUS_LOCAL_STREAM_SUSPENDED); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index bb75ed78cd9..295b41f9343 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -1394,11 +1394,9 @@ public class BassClientServiceTest { } private void handleHandoverSupport() { - if (Flags.leaudioBroadcastAudioHandoverPolicies()) { - /* Unicast finished streaming */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); - } + /* Unicast finished streaming */ + mBassClientService.handleUnicastSourceStreamStatusChange( + 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); } private void verifyAddSourceForGroup(BluetoothLeBroadcastMetadata meta) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index b6db6fc1f9a..3a508fdce8b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -1353,7 +1353,6 @@ public class ActiveDeviceManagerTest { */ @Test public void a2dpConnectedWhenBroadcasting_notSetA2dpActive() { - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); final List metadataList = mock(List.class); when(mLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); a2dpConnected(mA2dpDevice, false); @@ -1370,7 +1369,6 @@ public class ActiveDeviceManagerTest { */ @Test public void headsetConnectedWhenBroadcasting_notSetHeadsetActive() { - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); final List metadataList = mock(List.class); when(mLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); headsetConnected(mHeadsetDevice, false); @@ -1387,7 +1385,6 @@ public class ActiveDeviceManagerTest { */ @Test public void hearingAidConnectedWhenBroadcasting_notSetHearingAidActive() { - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); final List metadataList = mock(List.class); when(mLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); hearingAidConnected(mHearingAidDevice); @@ -1401,7 +1398,6 @@ public class ActiveDeviceManagerTest { */ @Test public void leHearingAidConnectedWhenBroadcasting_notSetLeHearingAidActive() { - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); final List metadataList = mock(List.class); when(mLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); leHearingAidConnected(mLeHearingAidDevice); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 864b635f905..10909db22d9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -952,7 +952,6 @@ public class LeAudioBroadcastServiceTest { private void prepareHandoverStreamingBroadcast(int groupId, int broadcastId, byte[] code) { mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION); - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE); synchronized (mService.mBroadcastCallbacks) { 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 ca78b59f0ef..6e694c5c824 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 @@ -2117,7 +2117,6 @@ public class LeAudioServiceTest { @Test public void testMediaContextUnavailableWhileReceivingBroadcast() { mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION); - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class)); connectTestDevice(mSingleDevice, testGroupId); diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 669b6325907..031e5b02946 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -17,13 +17,6 @@ flag { bug: "307408418" } -flag { - name: "leaudio_broadcast_audio_handover_policies" - namespace: "bluetooth" - description: "Support le audio broadcast audio routing policies" - bug: "308171251" -} - flag { name: "leaudio_multicodec_aidl_support" namespace: "bluetooth" diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index b44b24e98a8..a0568998e2e 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -895,8 +895,7 @@ public: /* If assistant have some connected delegators that needs to be informed * when there would be request to stream unicast. */ - if (com::android::bluetooth::flags::leaudio_broadcast_audio_handover_policies() && - !sink_monitor_mode_ && source_monitor_mode_ && !group_is_streaming) { + if (!sink_monitor_mode_ && source_monitor_mode_ && !group_is_streaming) { callbacks_->OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource, UnicastMonitorModeStatus::STREAMING_REQUESTED); } @@ -1113,11 +1112,6 @@ public: } void SetUnicastMonitorMode(uint8_t direction, bool enable) override { - if (!com::android::bluetooth::flags::leaudio_broadcast_audio_handover_policies()) { - log::warn("Monitor mode is disabled, Set Unicast Monitor mode is ignored"); - return; - } - if (direction == bluetooth::le_audio::types::kLeAudioDirectionSink) { /* Cleanup Sink HAL client interface if listening mode is toggled off * before group activation (active group context would take care of diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 0d10c9c832e..9b9498aa0f0 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -11667,8 +11667,6 @@ TEST_F(UnicastTest, GroupStreamStatusResendAfterRemove) { } TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsActive) { - com::android::bluetooth::flags::provider_->leaudio_broadcast_audio_handover_policies(true); - uint8_t group_size = 2; int group_id = 2; @@ -11810,7 +11808,6 @@ TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsActive) { } TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsInactive) { - com::android::bluetooth::flags::provider_->leaudio_broadcast_audio_handover_policies(true); uint8_t group_size = 2; int group_id = 2; @@ -11905,8 +11902,6 @@ TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsInactive) { } TEST_F(UnicastTestHandoverMode, ClearSinkMonitorModeWhileUnicastIsActive) { - com::android::bluetooth::flags::provider_->leaudio_broadcast_audio_handover_policies(true); - uint8_t group_size = 2; int group_id = 2; @@ -12000,8 +11995,6 @@ TEST_F(UnicastTestHandoverMode, ClearSinkMonitorModeWhileUnicastIsActive) { } TEST_F(UnicastTestHandoverMode, SetAndClearSinkMonitorModeWhileUnicastIsInactive) { - com::android::bluetooth::flags::provider_->leaudio_broadcast_audio_handover_policies(true); - EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(0); EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(0); EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0); @@ -12024,8 +12017,6 @@ TEST_F(UnicastTestHandoverMode, SetAndClearSinkMonitorModeWhileUnicastIsInactive } TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsInactive) { - com::android::bluetooth::flags::provider_->leaudio_broadcast_audio_handover_policies(true); - /* Enabling monitor mode for source while group is not active should result in * sending STREAMING_SUSPENDED notification. */ @@ -12043,8 +12034,6 @@ TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsInactive) { } TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsNotStreaming) { - com::android::bluetooth::flags::provider_->leaudio_broadcast_audio_handover_policies(true); - int group_id = 2; LeAudioClient::Get()->GroupSetActive(group_id); @@ -12066,8 +12055,6 @@ TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsNotStreaming) } TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsActive) { - com::android::bluetooth::flags::provider_->leaudio_broadcast_audio_handover_policies(true); - uint8_t group_size = 2; int group_id = 2; -- GitLab From c0d3a9510dd007150606b37b6ea79dcef9569f5d Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 30 Sep 2024 19:31:57 -0700 Subject: [PATCH 113/875] Pbap: Stop depending on static AdapterService Bug: 367395001 Test: atest BluetoothInstrumentationTests:BluetoothPbapServiceTest Flag: Exempt no-op refactor in code and then TEST_ONLY Change-Id: I349dd736e72faef25a25e4b524f2c3544b4933fe --- .../bluetooth/pbap/BluetoothPbapService.java | 167 +++++++----------- .../pbap/BluetoothPbapServiceTest.java | 52 +++--- 2 files changed, 92 insertions(+), 127 deletions(-) diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java index 0292c6f6849..cd8ae677fb2 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java @@ -21,6 +21,8 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.bluetooth.BluetoothDevice.ACCESS_ALLOWED; import static android.bluetooth.BluetoothDevice.ACCESS_REJECTED; +import static java.util.Objects.requireNonNull; + import android.annotation.RequiresPermission; import android.app.Activity; import android.app.Notification; @@ -39,7 +41,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; -import android.database.sqlite.SQLiteException; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -71,17 +72,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; -import java.util.Objects; // Next tag value for ContentProfileErrorReportUtils.report(): 12 public class BluetoothPbapService extends ProfileService implements IObexConnectionHandler { - private static final String TAG = "BluetoothPbapService"; - - /** - * To enable PBAP DEBUG/VERBOSE logging - run below cmd in adb shell, and restart - * com.android.bluetooth process. only enable DEBUG log: "setprop log.tag.BluetoothPbapService - * DEBUG"; enable both VERBOSE and DEBUG log: "setprop log.tag.BluetoothPbapService VERBOSE" - */ + private static final String TAG = BluetoothPbapService.class.getSimpleName(); /** The component name of the owned BluetoothPbapActivity */ private static final String PBAP_ACTIVITY = BluetoothPbapActivity.class.getCanonicalName(); @@ -132,8 +126,12 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect private static String sLocalPhoneNum; private static String sLocalPhoneName; + private final AdapterService mAdapterService; + private final Context mContext; + private final DatabaseManager mDatabaseManager; + private final NotificationManager mNotificationManager; + private ObexServerSockets mServerSockets = null; - private DatabaseManager mDatabaseManager; private static final int SDP_PBAP_SERVER_VERSION_1_2 = 0x0102; // PBAP v1.2.3, Sec. 7.1.2: local phonebook and favorites @@ -172,12 +170,22 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect private static final String PBAP_NOTIFICATION_ID = "pbap_notification"; private static final String PBAP_NOTIFICATION_NAME = "BT_PBAP_ADVANCE_SUPPORT"; private static final int PBAP_ADV_VERSION = 0x0102; - private static NotificationManager sNotificationManager; private static boolean sIsPseDynamicVersionUpgradeEnabled; - public BluetoothPbapService(Context ctx) { - super(ctx); + public BluetoothPbapService(AdapterService adapterService) { + this( + requireNonNull(adapterService), + adapterService.getSystemService(NotificationManager.class)); + } + + @VisibleForTesting + BluetoothPbapService(AdapterService adapterService, NotificationManager notificationManager) { + super(requireNonNull(adapterService)); + mContext = adapterService; + mAdapterService = adapterService; + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); + mNotificationManager = requireNonNull(notificationManager); } public static boolean isEnabled() { @@ -244,16 +252,15 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect boolean savePreference = intent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false); - AdapterService adapterService = AdapterService.getAdapterService(); if (access == BluetoothDevice.CONNECTION_ACCESS_YES) { if (savePreference) { - adapterService.setPhonebookAccessPermission(device, ACCESS_ALLOWED); + mAdapterService.setPhonebookAccessPermission(device, ACCESS_ALLOWED); Log.v(TAG, "setPhonebookAccessPermission(ACCESS_ALLOWED)"); } sm.sendMessage(PbapStateMachine.AUTHORIZED); } else { if (savePreference) { - adapterService.setPhonebookAccessPermission(device, ACCESS_REJECTED); + mAdapterService.setPhonebookAccessPermission(device, ACCESS_REJECTED); Log.v(TAG, "setPhonebookAccessPermission(ACCESS_REJECTED)"); } sm.sendMessage(PbapStateMachine.REJECTED); @@ -425,49 +432,33 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect } /*Creates Notification for PBAP version upgrade */ - protected static void createNotification(BluetoothPbapService context) { + protected void createNotification() { Log.v(TAG, "Create PBAP Notification for Upgrade"); // create Notification channel. - sNotificationManager = context.getSystemService(NotificationManager.class); - if (sNotificationManager != null) { - NotificationChannel mChannel = - new NotificationChannel( - PBAP_NOTIFICATION_ID, - PBAP_NOTIFICATION_NAME, - NotificationManager.IMPORTANCE_DEFAULT); - sNotificationManager.createNotificationChannel(mChannel); - // create notification - String title = context.getString(R.string.phonebook_advance_feature_support); - String contentText = context.getString(R.string.repair_for_adv_phonebook_feature); - int notificationId = android.R.drawable.stat_sys_data_bluetooth; - Notification notification = - new Notification.Builder(context, PBAP_NOTIFICATION_ID) - .setContentTitle(title) - .setContentText(contentText) - .setSmallIcon(notificationId) - .setAutoCancel(true) - .build(); - sNotificationManager.notify(notificationId, notification); - } else { - Log.e(TAG, "sNotificationManager is null"); - ContentProfileErrorReportUtils.report( - BluetoothProfile.PBAP, - BluetoothProtoEnums.BLUETOOTH_PBAP_SERVICE, - BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__LOG_ERROR, - 6); - } + NotificationChannel mChannel = + new NotificationChannel( + PBAP_NOTIFICATION_ID, + PBAP_NOTIFICATION_NAME, + NotificationManager.IMPORTANCE_DEFAULT); + mNotificationManager.createNotificationChannel(mChannel); + // create notification + String title = getString(R.string.phonebook_advance_feature_support); + String contentText = getString(R.string.repair_for_adv_phonebook_feature); + int notificationId = android.R.drawable.stat_sys_data_bluetooth; + Notification notification = + new Notification.Builder(this, PBAP_NOTIFICATION_ID) + .setContentTitle(title) + .setContentText(contentText) + .setSmallIcon(notificationId) + .setAutoCancel(true) + .build(); + mNotificationManager.notify(notificationId, notification); } /* Checks if notification for Version Upgrade is required */ - protected static void handleNotificationTask( - BluetoothPbapService service, BluetoothDevice remoteDevice) { - int pce_version = 0; - - AdapterService adapterService = AdapterService.getAdapterService(); - if (adapterService != null) { - pce_version = adapterService.getRemotePbapPceVersion(remoteDevice.getAddress()); - Log.d(TAG, "pce_version: " + pce_version); - } + protected void handleNotificationTask(BluetoothDevice remoteDevice) { + int pce_version = mAdapterService.getRemotePbapPceVersion(remoteDevice.getAddress()); + Log.d(TAG, "pce_version: " + pce_version); boolean matched = InteropUtil.interopMatchAddrOrName( @@ -477,12 +468,10 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect if (pce_version == PBAP_ADV_VERSION && !matched) { Log.d(TAG, "Remote Supports PBAP 1.2. Notify user"); - createNotification(service); + createNotification(); } else { Log.d(TAG, "Notification Not Required."); - if (sNotificationManager != null) { - sNotificationManager.cancel(android.R.drawable.stat_sys_data_bluetooth); - } + mNotificationManager.cancel(android.R.drawable.stat_sys_data_bluetooth); } } @@ -584,7 +573,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect case HANDLE_VERSION_UPDATE_NOTIFICATION: BluetoothDevice remoteDev = (BluetoothDevice) msg.obj; - handleNotificationTask(sBluetoothPbapService, remoteDev); + handleNotificationTask(remoteDev); break; default: break; @@ -711,17 +700,13 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect @Override public void start() { Log.v(TAG, "start()"); - mDatabaseManager = - Objects.requireNonNull( - AdapterService.getAdapterService().getDatabase(), - "DatabaseManager cannot be null when PbapService starts"); IntentFilter userFilter = new IntentFilter(); userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); userFilter.addAction(Intent.ACTION_USER_SWITCHED); userFilter.addAction(Intent.ACTION_USER_UNLOCKED); - getApplicationContext().registerReceiver(mUserChangeReceiver, userFilter); + registerReceiver(mUserChangeReceiver, userFilter); // Enable owned Activity component setComponentAvailable(PBAP_ACTIVITY, true); @@ -738,42 +723,22 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect filter.addAction(AUTH_CANCELLED_ACTION); BluetoothPbapConfig.init(this); registerReceiver(mPbapReceiver, filter); - try { - mContactChangeObserver = new BluetoothPbapContentObserver(); - getContentResolver() - .registerContentObserver( - DevicePolicyUtils.getEnterprisePhoneUri(this), - false, - mContactChangeObserver); - } catch (SQLiteException e) { - ContentProfileErrorReportUtils.report( - BluetoothProfile.PBAP, - BluetoothProtoEnums.BLUETOOTH_PBAP_SERVICE, - BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION, - 9); - Log.e(TAG, "SQLite exception: " + e); - } catch (IllegalStateException e) { - ContentProfileErrorReportUtils.report( - BluetoothProfile.PBAP, - BluetoothProtoEnums.BLUETOOTH_PBAP_SERVICE, - BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION, - 10); - Log.e(TAG, "Illegal state exception, content observer is already registered"); - } + mContactChangeObserver = new BluetoothPbapContentObserver(); + mContext.getContentResolver() + .registerContentObserver( + DevicePolicyUtils.getEnterprisePhoneUri(this), + false, + mContactChangeObserver); setBluetoothPbapService(this); - mSessionStatusHandler.sendMessage( - mSessionStatusHandler.obtainMessage(GET_LOCAL_TELEPHONY_DETAILS)); - mSessionStatusHandler.sendMessage(mSessionStatusHandler.obtainMessage(LOAD_CONTACTS)); - mSessionStatusHandler.sendMessage(mSessionStatusHandler.obtainMessage(START_LISTENER)); + mSessionStatusHandler.sendEmptyMessage(GET_LOCAL_TELEPHONY_DETAILS); + mSessionStatusHandler.sendEmptyMessage(LOAD_CONTACTS); + mSessionStatusHandler.sendEmptyMessage(START_LISTENER); - AdapterService adapterService = AdapterService.getAdapterService(); - if (adapterService != null) { - sIsPseDynamicVersionUpgradeEnabled = - adapterService.pbapPseDynamicVersionUpgradeIsEnabled(); - Log.d(TAG, "sIsPseDynamicVersionUpgradeEnabled: " + sIsPseDynamicVersionUpgradeEnabled); - } + sIsPseDynamicVersionUpgradeEnabled = + mAdapterService.pbapPseDynamicVersionUpgradeIsEnabled(); + Log.d(TAG, "sIsPseDynamicVersionUpgradeEnabled: " + sIsPseDynamicVersionUpgradeEnabled); } @Override @@ -781,7 +746,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect Log.v(TAG, "stop()"); setBluetoothPbapService(null); if (mSessionStatusHandler != null) { - mSessionStatusHandler.obtainMessage(SHUTDOWN).sendToTarget(); + mSessionStatusHandler.sendEmptyMessage(SHUTDOWN); } if (mHandlerThread != null) { mHandlerThread.quitSafely(); @@ -792,13 +757,13 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect return; } unregisterReceiver(mPbapReceiver); - getContentResolver().unregisterContentObserver(mContactChangeObserver); + mContext.getContentResolver().unregisterContentObserver(mContactChangeObserver); mContactChangeObserver = null; setComponentAvailable(PBAP_ACTIVITY, false); synchronized (mPbapStateMachineMap) { mPbapStateMachineMap.clear(); } - getApplicationContext().unregisterReceiver(mUserChangeReceiver); + unregisterReceiver(mUserChangeReceiver); } /** @@ -955,7 +920,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void checkOrGetPhonebookPermission(PbapStateMachine stateMachine) { BluetoothDevice device = stateMachine.getRemoteDevice(); - int permission = AdapterService.getAdapterService().getPhonebookAccessPermission(device); + int permission = mAdapterService.getPhonebookAccessPermission(device); Log.d(TAG, "getPhonebookAccessPermission() = " + permission); if (permission == ACCESS_ALLOWED) { @@ -1022,7 +987,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect mPbapStateMachineMap.clear(); } - mSessionStatusHandler.sendMessage(mSessionStatusHandler.obtainMessage(START_LISTENER)); + mSessionStatusHandler.sendEmptyMessage(START_LISTENER); } private void loadAllContacts() { diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java index 013d5dc9200..dbbb53e9d88 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java @@ -25,13 +25,16 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.NotificationManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.os.Message; +import android.os.UserManager; import android.os.test.TestLooper; +import android.test.mock.MockContentResolver; import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; @@ -53,58 +56,55 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.List; + @MediumTest @RunWith(AndroidJUnit4.class) public class BluetoothPbapServiceTest { - private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; - - private BluetoothPbapService mService; - private BluetoothAdapter mAdapter = null; - private BluetoothDevice mRemoteDevice; - private boolean mIsAdapterServiceSet; - private boolean mIsBluetoothPabpServiceStarted; - private TestLooper mTestLooper; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; + @Mock private NotificationManager mNotificationManager; @Spy private BluetoothMethodProxy mMethodProxy = BluetoothMethodProxy.getInstance(); + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mRemoteDevice = TestUtils.getTestDevice(mAdapter, 42); + private final Context mTargetContext = InstrumentationRegistry.getTargetContext(); + private final MockContentResolver mMockContentResolver = + new MockContentResolver(mTargetContext); + + private BluetoothPbapService mService; + private TestLooper mTestLooper; + @Before public void setUp() throws Exception { - Context targetContext = InstrumentationRegistry.getTargetContext(); + doReturn(mTargetContext.getPackageName()).when(mAdapterService).getPackageName(); + doReturn(mTargetContext.getPackageManager()).when(mAdapterService).getPackageManager(); + doReturn(mMockContentResolver).when(mAdapterService).getContentResolver(); + UserManager manager = + TestUtils.mockGetSystemService( + mAdapterService, Context.USER_SERVICE, UserManager.class); + doReturn(List.of()).when(manager).getAllProfiles(); + mTestLooper = new TestLooper(); BluetoothMethodProxy.setInstanceForTesting(mMethodProxy); doReturn(mTestLooper.getLooper()).when(mMethodProxy).handlerThreadGetLooper(any()); doNothing().when(mMethodProxy).threadStart(any()); mTestLooper.startAutoDispatch(); - TestUtils.setAdapterService(mAdapterService); - mIsAdapterServiceSet = true; doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); - mService = new BluetoothPbapService(targetContext); + mService = new BluetoothPbapService(mAdapterService, mNotificationManager); mService.start(); mService.setAvailable(true); - mIsBluetoothPabpServiceStarted = true; - // Try getting the Bluetooth adapter - mAdapter = BluetoothAdapter.getDefaultAdapter(); - assertThat(mAdapter).isNotNull(); - mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); } @After public void tearDown() throws Exception { mTestLooper.stopAutoDispatchAndIgnoreExceptions(); BluetoothMethodProxy.setInstanceForTesting(null); - if (!mIsAdapterServiceSet) { - return; - } - if (mIsBluetoothPabpServiceStarted) { - mService.stop(); - mService = BluetoothPbapService.getBluetoothPbapService(); - assertThat(mService).isNull(); - } - TestUtils.clearAdapterService(mAdapterService); + mService.stop(); + assertThat(BluetoothPbapService.getBluetoothPbapService()).isNull(); } @Test -- GitLab From e0d8076730b4dee087220e043908f51798c51802 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 1 Oct 2024 14:29:26 -0700 Subject: [PATCH 114/875] Add flag get_profile_use_lock Bug: 370815283 Bug: 315241296 Test: m . Flag: com.android.bluetooth.flags.get_profile_use_lock Change-Id: I5406a8e1a39d79bff4724a9112444833d7fe6cf3 --- flags/framework.aconfig | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/flags/framework.aconfig b/flags/framework.aconfig index c3b4e418d3a..c2f1f51e817 100644 --- a/flags/framework.aconfig +++ b/flags/framework.aconfig @@ -60,4 +60,14 @@ flag { namespace: "bluetooth" description: "Enhanced Bluetooth Framework Support for Accessing Bluetooth Quality Report v6 Information" bug: "364517559" -} \ No newline at end of file +} + +flag { + name: "get_profile_use_lock" + namespace: "bluetooth" + description: "Instead of bloating the main thread, use the binder thread with a synchronization lock" + bug: "370815283" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 0d0173695d5463c2beae208ad4c86c9289d709e4 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 1 Oct 2024 22:37:55 +0000 Subject: [PATCH 115/875] system/btif: Fix -Wmissing-prototypes errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor fixes Change-Id: I187dfb0298ddd5b153f2e900ec2bbdc43d3ceb74 --- system/btif/co/bta_av_co.cc | 5 ++--- system/btif/co/bta_hh_co.cc | 21 ++++++++------------- system/btif/include/btif_dm.h | 2 ++ system/btif/include/btif_hh.h | 6 ++++++ system/btif/src/btif_hh.cc | 16 +++++++--------- system/test/mock/mock_btif_co_bta_hh_co.cc | 1 - 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index 1364631d26b..7805782e048 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -37,9 +37,11 @@ #include "audio_hal_interface/a2dp_encoding.h" #include "bta/include/bta_av_api.h" #include "bta/include/bta_av_ci.h" +#include "bta/include/bta_av_co.h" #include "btif/include/bta_av_co_peer.h" #include "btif/include/btif_a2dp_source.h" #include "btif/include/btif_av.h" +#include "btif/include/btif_av_co.h" #include "device/include/device_iot_config.h" #include "include/hardware/bt_av.h" #include "internal_include/bt_trace.h" @@ -53,9 +55,6 @@ #include "stack/include/bt_uuid16.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; // SCMS-T protect info diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index 9165b9ce7e5..5b2bffb4e7b 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -31,6 +31,7 @@ #include #include "bta_hh_api.h" +#include "btif_config.h" #include "btif_hh.h" #include "hci/controller_interface.h" #include "main/shim/entry.h" @@ -40,13 +41,6 @@ #include "osi/include/properties.h" #include "storage/config_keys.h" #include "types/raw_address.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -const char* dev_path = "/dev/uhid"; - -#include "btif_config.h" #define BTA_HH_NV_LOAD_MAX 16 static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; #define BTA_HH_CACHE_REPORT_VERSION 1 @@ -64,15 +58,16 @@ static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; using namespace bluetooth; -static const char kPropertyWaitMsAfterUhidOpen[] = "bluetooth.hid.wait_ms_after_uhid_open"; +static constexpr char kDevPath[] = "/dev/uhid"; +static constexpr char kPropertyWaitMsAfterUhidOpen[] = "bluetooth.hid.wait_ms_after_uhid_open"; -static const bthh_report_type_t map_rtype_uhid_hh[] = {BTHH_FEATURE_REPORT, BTHH_OUTPUT_REPORT, - BTHH_INPUT_REPORT}; +static constexpr bthh_report_type_t map_rtype_uhid_hh[] = {BTHH_FEATURE_REPORT, BTHH_OUTPUT_REPORT, + BTHH_INPUT_REPORT}; static void* btif_hh_poll_event_thread(void* arg); static bool to_uhid_thread(int fd, const tBTA_HH_TO_UHID_EVT* ev, size_t data_len); -void uhid_set_non_blocking(int fd) { +static void uhid_set_non_blocking(int fd) { int opts = fcntl(fd, F_GETFL); if (opts < 0) { log::error("Getting flags failed ({})", strerror(errno)); @@ -508,7 +503,7 @@ static void uhid_fd_close(btif_hh_uhid_t* p_uhid) { static bool uhid_fd_open(btif_hh_device_t* p_dev) { if (!com::android::bluetooth::flags::hid_report_queuing()) { if (p_dev->uhid.fd < 0) { - p_dev->uhid.fd = open(dev_path, O_RDWR | O_CLOEXEC); + p_dev->uhid.fd = open(kDevPath, O_RDWR | O_CLOEXEC); if (p_dev->uhid.fd < 0) { log::error("Failed to open uhid, err:{}", strerror(errno)); return false; @@ -680,7 +675,7 @@ static void* btif_hh_poll_event_thread(void* arg) { btif_hh_uhid_t* p_uhid = (btif_hh_uhid_t*)arg; if (com::android::bluetooth::flags::hid_report_queuing()) { - p_uhid->fd = open(dev_path, O_RDWR | O_CLOEXEC); + p_uhid->fd = open(kDevPath, O_RDWR | O_CLOEXEC); if (p_uhid->fd < 0) { log::error("Failed to open uhid, err:{}", strerror(errno)); close(p_uhid->internal_recv_fd); diff --git a/system/btif/include/btif_dm.h b/system/btif/include/btif_dm.h index d9f444cbce5..5db8b50d47e 100644 --- a/system/btif/include/btif_dm.h +++ b/system/btif/include/btif_dm.h @@ -116,6 +116,8 @@ void btif_dm_set_event_filter_inquiry_result_all_devices(); void btif_dm_metadata_changed(const RawAddress& remote_bd_addr, int key, std::vector value); +void btif_dm_hh_open_failed(RawAddress* bdaddr); + /*callout for reading SMP properties from Text file*/ bool btif_dm_get_smp_config(tBTE_APPL_CFG* p_cfg); diff --git a/system/btif/include/btif_hh.h b/system/btif/include/btif_hh.h index 23a7f76bd41..2ff60d74da9 100644 --- a/system/btif/include/btif_hh.h +++ b/system/btif/include/btif_hh.h @@ -158,6 +158,12 @@ void btif_hh_load_bonded_dev(const tAclLinkSpec& link_spec, tBTA_HH_ATTR_MASK at uint8_t sub_class, uint8_t app_id, tBTA_HH_DEV_DSCP_INFO dscp_info, bool reconnect_allowed); +int bta_hh_co_write(int fd, uint8_t* rpt, uint16_t len); +void bta_hh_co_close(btif_hh_device_t* p_dev); +void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name, uint16_t vendor_id, + uint16_t product_id, uint16_t version, uint8_t ctry_code, + uint16_t dscp_len, uint8_t* p_dscp); + void DumpsysHid(int fd); namespace fmt { diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index 90e55f074e9..93720f51823 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -37,6 +37,8 @@ #include "bta_hh_co.h" #include "bta_sec_api.h" #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" @@ -141,21 +143,17 @@ static tHID_KB_LIST hid_kb_numlock_on_list[] = { ******************************************************************************/ static void btif_hh_transport_select(tAclLinkSpec& link_spec); + /******************************************************************************* * Externs ******************************************************************************/ + bool check_cod(const RawAddress* remote_bdaddr, uint32_t cod); bool check_cod_hid(const RawAddress* remote_bdaddr); bool check_cod_hid_major(const RawAddress& bd_addr, uint32_t cod); -void bta_hh_co_close(btif_hh_device_t* p_dev); -void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name, uint16_t vendor_id, - uint16_t product_id, uint16_t version, uint8_t ctry_code, - uint16_t dscp_len, uint8_t* p_dscp); -void bta_hh_co_write(int fd, uint8_t* rpt, uint16_t len); + static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data); -void btif_dm_hh_open_failed(RawAddress* bdaddr); -void btif_hd_service_registration(); -void btif_hh_timer_timeout(void* data); +static void btif_hh_timer_timeout(void* data); /******************************************************************************* * Functions @@ -1434,7 +1432,7 @@ static void btif_hh_handle_evt(uint16_t event, char* p_param) { * * Returns void ******************************************************************************/ -void btif_hh_timer_timeout(void* data) { +static void btif_hh_timer_timeout(void* data) { btif_hh_device_t* p_dev = (btif_hh_device_t*)data; tBTA_HH_EVT event = BTA_HH_VC_UNPLUG_EVT; tBTA_HH p_data; diff --git a/system/test/mock/mock_btif_co_bta_hh_co.cc b/system/test/mock/mock_btif_co_bta_hh_co.cc index 788317f56ca..8f9a4ea7396 100644 --- a/system/test/mock/mock_btif_co_bta_hh_co.cc +++ b/system/test/mock/mock_btif_co_bta_hh_co.cc @@ -69,4 +69,3 @@ void bta_hh_le_co_rpt_info(const tAclLinkSpec& /* link_spec */, tBTA_HH_RPT_CACHE_ENTRY* /* p_entry */, uint8_t /* app_id */) { inc_func_call_count(__func__); } -void uhid_set_non_blocking(int /* fd */) { inc_func_call_count(__func__); } -- GitLab From 07a3c0b2db9c301e6bcf2d15770bd6fb18b1cce7 Mon Sep 17 00:00:00 2001 From: Pomai Ahlo Date: Tue, 1 Oct 2024 10:25:33 -0700 Subject: [PATCH 116/875] RfcommTest: Document test steps Bug: 331415222 Test: atest RfcommTest Flag: DOCS_ONLY Change-Id: I655c37258209f339060935e54ec323ea746e81d4 --- .../src/android/bluetooth/RfcommTest.kt | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/framework/tests/bumble/src/android/bluetooth/RfcommTest.kt b/framework/tests/bumble/src/android/bluetooth/RfcommTest.kt index 40dec912f7f..404847df682 100644 --- a/framework/tests/bumble/src/android/bluetooth/RfcommTest.kt +++ b/framework/tests/bumble/src/android/bluetooth/RfcommTest.kt @@ -73,6 +73,13 @@ class RfcommTest { private var mConnectionCounter = 1 private var mProfileServiceListener = mock() + /* + Setup: + 1. Initialize host and mRemoteDevice + 2. Disable A2DP, HFP, and HID profiles + 3. Bond devices + 4. Disconnect devices + */ @Before fun setUp() { mRemoteDevice = mBumble.remoteDevice @@ -99,6 +106,11 @@ class RfcommTest { } } + /* + TearDown: + 1. unbond + 2. shutdown host + */ @After fun tearDown() { if (mAdapter.bondedDevices.contains(mRemoteDevice)) { @@ -107,16 +119,36 @@ class RfcommTest { host.close() } + /* + Test Steps: + 1. Create an insecure socket + 2. Connect to the socket + 3. Verify that devices are connected. + */ @Test fun clientConnectToOpenServerSocketBondedInsecure() { startServer { serverId -> createConnectAcceptSocket(isSecure = false, serverId) } } + /* + Test Steps: + 1. Create an secure socket + 2. Connect to the socket + 3. Verify that devices are connected. + */ @Test fun clientConnectToOpenServerSocketBondedSecure() { startServer { serverId -> createConnectAcceptSocket(isSecure = true, serverId) } } + /* + Test Steps: + 1. Create an insecure socket + 2. Connect to the socket + 3. Verify that devices are connected + 4. Write data to socket output stream + 5. Verify bumble received that data + */ @Test fun clientSendDataOverInsecureSocket() { startServer { serverId -> @@ -134,6 +166,14 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create a secure socket + 2. Connect to the socket + 3. Verify that devices are connected + 4. Write data to socket output stream + 5. Verify remote device received that data + */ @Test fun clientSendDataOverSecureSocket() { startServer { serverId -> @@ -151,6 +191,14 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create an insecure socket + 2. Connect to the socket + 3. Verify that devices are connected + 4. Send data from remote device + 5. Read and verify data from socket input stream + */ @Test fun clientReceiveDataOverInsecureSocket() { startServer { serverId -> @@ -169,6 +217,14 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create a secure socket + 2. Connect to the socket + 3. Verify that devices are connected + 4. Send data from remote device + 5. Read and verify data from socket input stream + */ @Test fun clientReceiveDataOverSecureSocket() { startServer { serverId -> @@ -187,6 +243,15 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create insecure socket 1 + 2. Create insecure socket 2 + 3. Remote device initiates connection to socket 1 + 4. Remote device initiates connection to socket 2 + 5. Accept socket 1 and verify connection + 6. Accept socket 2 and verify connection + */ @Test fun connectTwoInsecureClientsSimultaneously() { startServer("ServerPort1", TEST_UUID) { serverId1 -> @@ -203,6 +268,13 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create insecure socket 1 + 2. Remote device initiates connection to socket 1 + 3. Accept socket 1 and verify connection + 4. Repeat for socket 2 + */ @Test fun connectTwoInsecureClientsSequentially() { startServer("ServerPort1", TEST_UUID) { serverId1 -> @@ -218,6 +290,15 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create secure socket 1 + 2. Create secure socket 2 + 3. Remote device initiates connection to socket 1 + 4. Remote device initiates connection to socket 2 + 5. Accept socket 1 and verify connection + 6. Accept socket 2 and verify connection + */ @Test fun connectTwoSecureClientsSimultaneously() { startServer("ServerPort1", TEST_UUID) { serverId1 -> @@ -234,6 +315,13 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create insecure socket 1 + 2. Remote device initiates connection to socket 1 + 3. Accept socket 1 and verify connection + 4. Repeat for socket 2 + */ @Test fun connectTwoSecureClientsSequentially() { startServer("ServerPort1", TEST_UUID) { serverId1 -> @@ -249,6 +337,13 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create insecure socket 1 + 2. Remote device initiates connection to socket 1 + 3. Accept socket 1 and verify connection + 4. Repeat for secure socket 2 + */ @Test fun connectTwoMixedClientsInsecureThenSecure() { startServer("ServerPort1", TEST_UUID) { serverId1 -> @@ -264,6 +359,13 @@ class RfcommTest { } } + /* + Test Steps: + 1. Create secure socket 2 + 2. Remote device initiates connection to socket 2 + 3. Accept socket 2 and verify connection + 4. Repeat for insecure socket 1 + */ @Test fun connectTwoMixedClientsSecureThenInsecure() { startServer("ServerPort1", TEST_UUID) { serverId1 -> -- GitLab From eebd8b2df7e9a82e361540baaf126514114e4498 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 1 Oct 2024 15:47:03 -0700 Subject: [PATCH 117/875] Mark packages/modules/Bluetooth apps in updatable apexes with updatable: true Set updatable: true for apps that are embedded in updatable apexes. This replaces the top down propagation that was automatically setting the flag in order to unblock support for incremental Soong analysis. Bug: 367784740 Test: builds Flag: EXEMPT refactor Change-Id: I16f35ea96361f5e4572dec149ceef2a0fd7bdab2 --- android/app/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/android/app/Android.bp b/android/app/Android.bp index efc06848653..a692042ec0f 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -385,6 +385,7 @@ android_app { }, min_sdk_version: "Tiramisu", sdk_version: "module_current", + updatable: true, } java_library { -- GitLab From 6e0be93a4d9772f96c84b7f72c2095435729ab2e Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 19 Sep 2024 21:32:17 +0000 Subject: [PATCH 118/875] audio_hal_interface: Split off A2DP AIDL bindings Move everything A2DP specific to system/audio_hal_interface/aidl/a2dp Common definitions for the client interface and transport are duplicated under the namespace bluetooth::audio::aidl::a2dp. The common definitions will be tailored down to A2DP's usecase in a follow up change. Bug: 365022887 Test: m com.android.btservices Test: Manual streaming test Flag: EXEMPT, mechanical refactor Change-Id: I32e5b447487fdde25845a62349db843262fa54d4 --- system/audio_hal_interface/Android.bp | 12 +- system/audio_hal_interface/a2dp_encoding.cc | 2 +- .../aidl/{ => a2dp}/a2dp_encoding_aidl.cc | 24 +- .../aidl/{ => a2dp}/a2dp_encoding_aidl.h | 0 .../aidl/{ => a2dp}/a2dp_provider_info.cc | 0 .../aidl/{ => a2dp}/a2dp_provider_info.h | 0 .../{ => a2dp}/a2dp_provider_info_unittest.cc | 6 +- .../aidl/{ => a2dp}/a2dp_transport.h | 4 +- .../aidl/a2dp/audio_aidl_interfaces.h | 78 ++ .../aidl/a2dp/audio_ctrl_ack.h | 69 ++ .../aidl/a2dp/bluetooth_audio_port_impl.cc | 231 ++++++ .../aidl/a2dp/bluetooth_audio_port_impl.h | 70 ++ .../aidl/a2dp/client_interface_aidl.cc | 735 ++++++++++++++++++ .../aidl/a2dp/client_interface_aidl.h | 228 ++++++ .../aidl/{ => a2dp}/codec_status_aidl.cc | 2 + .../aidl/{ => a2dp}/codec_status_aidl.h | 2 + .../aidl/a2dp/transport_instance.h | 132 ++++ .../aidl/le_audio_software_aidl.cc | 1 - 18 files changed, 1572 insertions(+), 24 deletions(-) rename system/audio_hal_interface/aidl/{ => a2dp}/a2dp_encoding_aidl.cc (97%) rename system/audio_hal_interface/aidl/{ => a2dp}/a2dp_encoding_aidl.h (100%) rename system/audio_hal_interface/aidl/{ => a2dp}/a2dp_provider_info.cc (100%) rename system/audio_hal_interface/aidl/{ => a2dp}/a2dp_provider_info.h (100%) rename system/audio_hal_interface/aidl/{ => a2dp}/a2dp_provider_info_unittest.cc (99%) rename system/audio_hal_interface/aidl/{ => a2dp}/a2dp_transport.h (93%) create mode 100644 system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h create mode 100644 system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h create mode 100644 system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc create mode 100644 system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h create mode 100644 system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc create mode 100644 system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h rename system/audio_hal_interface/aidl/{ => a2dp}/codec_status_aidl.cc (99%) rename system/audio_hal_interface/aidl/{ => a2dp}/codec_status_aidl.h (98%) create mode 100644 system/audio_hal_interface/aidl/a2dp/transport_instance.h diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index 9704c1589bd..9ccd5c4cbe7 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -42,11 +42,13 @@ cc_library_static { ], srcs: [ "a2dp_encoding.cc", - "aidl/a2dp_encoding_aidl.cc", - "aidl/a2dp_provider_info.cc", + "aidl/a2dp/a2dp_encoding_aidl.cc", + "aidl/a2dp/a2dp_provider_info.cc", + "aidl/a2dp/bluetooth_audio_port_impl.cc", + "aidl/a2dp/client_interface_aidl.cc", + "aidl/a2dp/codec_status_aidl.cc", "aidl/bluetooth_audio_port_impl.cc", "aidl/client_interface_aidl.cc", - "aidl/codec_status_aidl.cc", "aidl/hearing_aid_software_encoding_aidl.cc", "aidl/hfp_client_interface_aidl.cc", "aidl/le_audio_software_aidl.cc", @@ -164,8 +166,8 @@ cc_test { srcs: [ ":TestCommonMockFunctions", ":TestMockAudioHalInterface", - "aidl/a2dp_provider_info.cc", - "aidl/a2dp_provider_info_unittest.cc", + "aidl/a2dp/a2dp_provider_info.cc", + "aidl/a2dp/a2dp_provider_info_unittest.cc", ], shared_libs: [ "libaconfig_storage_read_api_cc", diff --git a/system/audio_hal_interface/a2dp_encoding.cc b/system/audio_hal_interface/a2dp_encoding.cc index d98b99fbcfa..1bebeac1ed0 100644 --- a/system/audio_hal_interface/a2dp_encoding.cc +++ b/system/audio_hal_interface/a2dp_encoding.cc @@ -18,7 +18,7 @@ #include -#include "aidl/a2dp_encoding_aidl.h" +#include "aidl/a2dp/a2dp_encoding_aidl.h" #include "hal_version_manager.h" #include "hidl/a2dp_encoding_hidl.h" diff --git a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc similarity index 97% rename from system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc rename to system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc index 38b7edc5883..a3e0ec2a1c1 100644 --- a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc @@ -57,16 +57,16 @@ using ::aidl::android::hardware::bluetooth::audio::CodecConfiguration; using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration; using ::aidl::android::hardware::bluetooth::audio::SessionType; -using ::bluetooth::audio::aidl::BluetoothAudioCtrlAck; -using ::bluetooth::audio::aidl::BluetoothAudioSinkClientInterface; -using ::bluetooth::audio::aidl::codec::A2dpAacToHalConfig; -using ::bluetooth::audio::aidl::codec::A2dpAptxToHalConfig; -using ::bluetooth::audio::aidl::codec::A2dpCodecToHalBitsPerSample; -using ::bluetooth::audio::aidl::codec::A2dpCodecToHalChannelMode; -using ::bluetooth::audio::aidl::codec::A2dpCodecToHalSampleRate; -using ::bluetooth::audio::aidl::codec::A2dpLdacToHalConfig; -using ::bluetooth::audio::aidl::codec::A2dpOpusToHalConfig; -using ::bluetooth::audio::aidl::codec::A2dpSbcToHalConfig; +using ::bluetooth::audio::aidl::a2dp::BluetoothAudioCtrlAck; +using ::bluetooth::audio::aidl::a2dp::BluetoothAudioSinkClientInterface; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpAacToHalConfig; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpAptxToHalConfig; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpCodecToHalBitsPerSample; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpCodecToHalChannelMode; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpCodecToHalSampleRate; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpLdacToHalConfig; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpOpusToHalConfig; +using ::bluetooth::audio::aidl::a2dp::codec::A2dpSbcToHalConfig; static BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(BluetoothAudioStatus ack) { switch (ack) { @@ -303,7 +303,7 @@ bool update_codec_offloading_capabilities( /* Load the provider information if supported by the HAL. */ provider_info = ::bluetooth::audio::aidl::a2dp::ProviderInfo::GetProviderInfo( supports_a2dp_hw_offload_v2); - return ::bluetooth::audio::aidl::codec::UpdateOffloadingCapabilities(framework_preference); + return ::bluetooth::audio::aidl::a2dp::codec::UpdateOffloadingCapabilities(framework_preference); } // Checking if new bluetooth_audio is enabled @@ -473,7 +473,7 @@ bool setup_codec(A2dpCodecConfig* a2dp_config, uint16_t peer_mtu, } bool should_codec_offloading = - bluetooth::audio::aidl::codec::IsCodecOffloadingEnabled(codec_config); + bluetooth::audio::aidl::a2dp::codec::IsCodecOffloadingEnabled(codec_config); if (should_codec_offloading && !is_hal_offloading()) { log::warn("Switching BluetoothAudio HAL to Hardware"); end_session(); diff --git a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.h b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h similarity index 100% rename from system/audio_hal_interface/aidl/a2dp_encoding_aidl.h rename to system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h diff --git a/system/audio_hal_interface/aidl/a2dp_provider_info.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc similarity index 100% rename from system/audio_hal_interface/aidl/a2dp_provider_info.cc rename to system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc diff --git a/system/audio_hal_interface/aidl/a2dp_provider_info.h b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.h similarity index 100% rename from system/audio_hal_interface/aidl/a2dp_provider_info.h rename to system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.h diff --git a/system/audio_hal_interface/aidl/a2dp_provider_info_unittest.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info_unittest.cc similarity index 99% rename from system/audio_hal_interface/aidl/a2dp_provider_info_unittest.cc rename to system/audio_hal_interface/aidl/a2dp/a2dp_provider_info_unittest.cc index 8b1e04b2357..f1c4b0cbd1b 100644 --- a/system/audio_hal_interface/aidl/a2dp_provider_info_unittest.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info_unittest.cc @@ -35,10 +35,10 @@ using aidl::android::hardware::bluetooth::audio::ChannelMode; using aidl::android::hardware::bluetooth::audio::CodecId; using aidl::android::hardware::bluetooth::audio::CodecInfo; -using bluetooth::audio::aidl::BluetoothAudioClientInterface; -using bluetooth::audio::aidl::IBluetoothAudioProviderFactory; -using bluetooth::audio::aidl::SessionType; +using bluetooth::audio::aidl::a2dp::BluetoothAudioClientInterface; +using bluetooth::audio::aidl::a2dp::IBluetoothAudioProviderFactory; using bluetooth::audio::aidl::a2dp::ProviderInfo; +using bluetooth::audio::aidl::a2dp::SessionType; using ::testing::_; using ::testing::Return; using ::testing::Test; diff --git a/system/audio_hal_interface/aidl/a2dp_transport.h b/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h similarity index 93% rename from system/audio_hal_interface/aidl/a2dp_transport.h rename to system/audio_hal_interface/aidl/a2dp/a2dp_transport.h index 08f906dcfee..ae244ccbc33 100644 --- a/system/audio_hal_interface/aidl/a2dp_transport.h +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h @@ -37,10 +37,10 @@ namespace a2dp { namespace { -using ::bluetooth::audio::aidl::LatencyMode; +using ::bluetooth::audio::aidl::a2dp::LatencyMode; // Provide call-in APIs for the Bluetooth Audio HAL -class A2dpTransport : public ::bluetooth::audio::aidl::IBluetoothSinkTransportInstance { +class A2dpTransport : public ::bluetooth::audio::aidl::a2dp::IBluetoothSinkTransportInstance { public: A2dpTransport(SessionType sessionType); diff --git a/system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h b/system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h new file mode 100644 index 00000000000..e8fb9ba5e8b --- /dev/null +++ b/system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h @@ -0,0 +1,78 @@ +/* + * Copyright 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. + */ + +#pragma once + +/*** + * Because some dependencies of AIDL libraries use syslog LOG macros, we must + * include them in the following order to use in libbluetooth. + ***/ + +// clang-format off + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef LOG_INFO +#undef LOG_INFO +#endif +#ifdef LOG_WARNING +#undef LOG_WARNING +#endif +#ifdef LOG_DEBUG +#undef LOG_DEBUG +#endif + +// clang-format on \ No newline at end of file diff --git a/system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h b/system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h new file mode 100644 index 00000000000..0bb70c13353 --- /dev/null +++ b/system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h @@ -0,0 +1,69 @@ +/* + * Copyright 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. + */ + +#pragma once + +#include + +#include "audio_aidl_interfaces.h" + +namespace bluetooth { +namespace audio { +namespace aidl { +namespace a2dp { + +enum class BluetoothAudioCtrlAck : uint8_t { + SUCCESS_FINISHED = 0, + SUCCESS_RECONFIGURATION, + PENDING, + FAILURE_UNSUPPORTED, + FAILURE_BUSY, + FAILURE_DISCONNECTING, + FAILURE +}; + +std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack); + +inline ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus +BluetoothAudioCtrlAckToHalStatus(const BluetoothAudioCtrlAck& ack) { + using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus; + switch (ack) { + case BluetoothAudioCtrlAck::SUCCESS_FINISHED: + return BluetoothAudioStatus::SUCCESS; + case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED: + return BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION; + case BluetoothAudioCtrlAck::PENDING: + return BluetoothAudioStatus::FAILURE; + case BluetoothAudioCtrlAck::FAILURE_BUSY: + return BluetoothAudioStatus::FAILURE; + case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING: + return BluetoothAudioStatus::FAILURE; + case BluetoothAudioCtrlAck::SUCCESS_RECONFIGURATION: + return BluetoothAudioStatus::RECONFIGURATION; + default: + return BluetoothAudioStatus::FAILURE; + } +} + +} // namespace a2dp +} // namespace aidl +} // namespace audio +} // namespace bluetooth + +namespace fmt { +template <> +struct formatter : ostream_formatter {}; +} // namespace fmt diff --git a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc new file mode 100644 index 00000000000..30d83a2937c --- /dev/null +++ b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc @@ -0,0 +1,231 @@ +/* + * Copyright 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. + */ + +#include "bluetooth_audio_port_impl.h" + +#include +#include + +#include + +#include "android/binder_ibinder_platform.h" +#include "btif/include/btif_common.h" +#include "common/stop_watch_legacy.h" + +namespace bluetooth { +namespace audio { +namespace aidl { +namespace a2dp { + +using ::bluetooth::common::StopWatchLegacy; + +BluetoothAudioPortImpl::BluetoothAudioPortImpl( + IBluetoothTransportInstance* transport_instance, + const std::shared_ptr& provider) + : transport_instance_(transport_instance), provider_(provider) {} + +BluetoothAudioPortImpl::~BluetoothAudioPortImpl() {} + +ndk::ScopedAStatus BluetoothAudioPortImpl::startStream(bool is_low_latency) { + StopWatchLegacy stop_watch(__func__); + BluetoothAudioCtrlAck ack = transport_instance_->StartRequest(is_low_latency); + if (ack != BluetoothAudioCtrlAck::PENDING) { + auto aidl_retval = provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack)); + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); + } + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioPortImpl::suspendStream() { + StopWatchLegacy stop_watch(__func__); + BluetoothAudioCtrlAck ack = transport_instance_->SuspendRequest(); + if (ack != BluetoothAudioCtrlAck::PENDING) { + auto aidl_retval = provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack)); + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); + } + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioPortImpl::stopStream() { + StopWatchLegacy stop_watch(__func__); + transport_instance_->StopRequest(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioPortImpl::getPresentationPosition( + PresentationPosition* _aidl_return) { + StopWatchLegacy stop_watch(__func__); + uint64_t remote_delay_report_ns; + uint64_t total_bytes_read; + timespec data_position; + bool retval = transport_instance_->GetPresentationPosition(&remote_delay_report_ns, + &total_bytes_read, &data_position); + + PresentationPosition::TimeSpec transmittedOctetsTimeStamp; + if (retval) { + transmittedOctetsTimeStamp = timespec_convert_to_hal(data_position); + } else { + remote_delay_report_ns = 0; + total_bytes_read = 0; + transmittedOctetsTimeStamp = {}; + } + log::verbose("result={}, delay={}, data={} byte(s), timestamp={}", retval, remote_delay_report_ns, + total_bytes_read, transmittedOctetsTimeStamp.toString()); + _aidl_return->remoteDeviceAudioDelayNanos = static_cast(remote_delay_report_ns); + _aidl_return->transmittedOctets = static_cast(total_bytes_read); + _aidl_return->transmittedOctetsTimestamp = transmittedOctetsTimeStamp; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioPortImpl::updateSourceMetadata( + const SourceMetadata& source_metadata) { + StopWatchLegacy stop_watch(__func__); + log::info("{} track(s)", source_metadata.tracks.size()); + + std::vector tracks_vec; + tracks_vec.reserve(source_metadata.tracks.size()); + for (const auto& track : source_metadata.tracks) { + auto num_of_tags = track.tags.size(); + log::info("metadata tags size: {}", num_of_tags); + + playback_track_metadata_v7 desc_track = { + .base = {.usage = static_cast(track.usage), + .content_type = static_cast(track.contentType), + .gain = track.gain}, + }; + + if (num_of_tags != 0) { + int copied_size = 0; + int max_tags_size = sizeof(desc_track.tags); + std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); + for (size_t i = 0; i < num_of_tags - 1; i++) { + int string_len = track.tags[i].length(); + + if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { + log::error("Too many tags, copied size: {}", copied_size); + break; + } + + track.tags[i].copy(desc_track.tags + copied_size, string_len, 0); + copied_size += string_len; + separator.copy(desc_track.tags + copied_size, 1, 0); + copied_size += 1; + } + + int string_len = track.tags[num_of_tags - 1].length(); + if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { + log::error("Too many tags, copied size: {}", copied_size); + } else { + track.tags[num_of_tags - 1].copy(desc_track.tags + copied_size, string_len, 0); + } + } else { + memset(desc_track.tags, 0, sizeof(desc_track.tags)); + } + + tracks_vec.push_back(desc_track); + } + + const source_metadata_v7_t legacy_source_metadata = {.track_count = tracks_vec.size(), + .tracks = tracks_vec.data()}; + transport_instance_->SourceMetadataChanged(legacy_source_metadata); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioPortImpl::updateSinkMetadata(const SinkMetadata& sink_metadata) { + StopWatchLegacy stop_watch(__func__); + log::info("{} track(s)", sink_metadata.tracks.size()); + + std::vector tracks_vec; + tracks_vec.reserve(sink_metadata.tracks.size()); + for (const auto& track : sink_metadata.tracks) { + auto num_of_tags = track.tags.size(); + log::info("metadata tags size: {}", num_of_tags); + + record_track_metadata_v7 desc_track = { + .base = + { + .source = static_cast(track.source), + .gain = track.gain, + }, + }; + + if (num_of_tags != 0) { + int copied_size = 0; + int max_tags_size = sizeof(desc_track.tags); + std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); + for (size_t i = 0; i < num_of_tags - 1; i++) { + int string_len = track.tags[i].length(); + + if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { + log::error("Too many tags, copied size: {}", copied_size); + break; + } + + track.tags[i].copy(desc_track.tags + copied_size, string_len, 0); + copied_size += string_len; + separator.copy(desc_track.tags + copied_size, 1, 0); + copied_size += 1; + } + + int string_len = track.tags[num_of_tags - 1].length(); + if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { + log::error("Too many tags, copied size: {}", copied_size); + } else { + track.tags[num_of_tags - 1].copy(desc_track.tags + copied_size, string_len, 0); + } + } else { + memset(desc_track.tags, 0, sizeof(desc_track.tags)); + } + + tracks_vec.push_back(desc_track); + } + + const sink_metadata_v7_t legacy_sink_metadata = {.track_count = tracks_vec.size(), + .tracks = tracks_vec.data()}; + transport_instance_->SinkMetadataChanged(legacy_sink_metadata); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioPortImpl::setLatencyMode(LatencyMode latency_mode) { + bool is_low_latency = latency_mode == LatencyMode::LOW_LATENCY ? true : false; + invoke_switch_buffer_size_cb(is_low_latency); + transport_instance_->SetLatencyMode(latency_mode); + return ndk::ScopedAStatus::ok(); +} + +PresentationPosition::TimeSpec BluetoothAudioPortImpl::timespec_convert_to_hal(const timespec& ts) { + return {.tvSec = static_cast(ts.tv_sec), .tvNSec = static_cast(ts.tv_nsec)}; +} + +// Overriding create binder and inherit RT from caller. +// In our case, the caller is the AIDL session control, so we match the priority +// of the AIDL session / AudioFlinger writer thread. +ndk::SpAIBinder BluetoothAudioPortImpl::createBinder() { + auto binder = BnBluetoothAudioPort::createBinder(); + if (com::android::bluetooth::flags::audio_port_binder_inherit_rt()) { + AIBinder_setInheritRt(binder.get(), true); + } + return binder; +} + +} // namespace a2dp +} // namespace aidl +} // namespace audio +} // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h new file mode 100644 index 00000000000..de4432b4eec --- /dev/null +++ b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h @@ -0,0 +1,70 @@ +/* + * Copyright 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. + */ + +#pragma once + +#include "audio_aidl_interfaces.h" +#include "transport_instance.h" + +namespace bluetooth { +namespace audio { +namespace aidl { +namespace a2dp { + +using ::aidl::android::hardware::audio::common::SinkMetadata; +using ::aidl::android::hardware::audio::common::SourceMetadata; +using ::aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort; +using ::aidl::android::hardware::bluetooth::audio::CodecType; +using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider; +using ::aidl::android::hardware::bluetooth::audio::LatencyMode; +using ::aidl::android::hardware::bluetooth::audio::PresentationPosition; + +class BluetoothAudioPortImpl : public BnBluetoothAudioPort { +public: + BluetoothAudioPortImpl(IBluetoothTransportInstance* transport_instance, + const std::shared_ptr& provider); + + ndk::ScopedAStatus startStream(bool is_low_latency) override; + + ndk::ScopedAStatus suspendStream() override; + + ndk::ScopedAStatus stopStream() override; + + ndk::ScopedAStatus getPresentationPosition(PresentationPosition* _aidl_return) override; + + ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata& source_metadata) override; + + ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata& sink_metadata) override; + + ndk::ScopedAStatus setLatencyMode(LatencyMode latency_mode) override; + +protected: + virtual ~BluetoothAudioPortImpl(); + + IBluetoothTransportInstance* transport_instance_; + const std::shared_ptr provider_; + PresentationPosition::TimeSpec timespec_convert_to_hal(const timespec& ts); + +private: + ndk::ScopedAStatus switchCodec(bool isLowLatency); + + ndk::SpAIBinder createBinder() override; +}; + +} // namespace a2dp +} // namespace aidl +} // namespace audio +} // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc new file mode 100644 index 00000000000..59d7f677610 --- /dev/null +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc @@ -0,0 +1,735 @@ +/* + * Copyright 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. + */ + +#define LOG_TAG "BTAudioClientAIDL" + +#include "aidl/a2dp/client_interface_aidl.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "bta/ag/bta_ag_int.h" + +const uint8_t kFetchAudioProviderRetryNumber = 3; + +namespace bluetooth { +namespace audio { +namespace aidl { +namespace a2dp { + +std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) { + switch (ack) { + case BluetoothAudioCtrlAck::SUCCESS_FINISHED: + return os << "SUCCESS_FINISHED"; + case BluetoothAudioCtrlAck::PENDING: + return os << "PENDING"; + case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED: + return os << "FAILURE_UNSUPPORTED"; + case BluetoothAudioCtrlAck::FAILURE_BUSY: + return os << "FAILURE_BUSY"; + case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING: + return os << "FAILURE_DISCONNECTING"; + case BluetoothAudioCtrlAck::FAILURE: + return os << "FAILURE"; + default: + return os << "UNDEFINED " << static_cast(ack); + } +} + +BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* instance) + : provider_(nullptr), + provider_factory_(nullptr), + session_started_(false), + data_mq_(nullptr), + transport_(instance), + latency_modes_({LatencyMode::FREE}) { + death_recipient_ = + ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(binderDiedCallbackAidl)); +} + +bool BluetoothAudioClientInterface::IsValid() const { return provider_ != nullptr; } + +bool BluetoothAudioClientInterface::is_aidl_available() { + return AServiceManager_isDeclared(kDefaultAudioProviderFactoryInterface.c_str()); +} + +std::vector BluetoothAudioClientInterface::GetAudioCapabilities() const { + return capabilities_; +} + +std::vector BluetoothAudioClientInterface::GetAudioCapabilities( + SessionType session_type) { + std::vector capabilities(0); + if (!is_aidl_available()) { + return capabilities; + } + auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder( + AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str()))); + + if (provider_factory == nullptr) { + log::error("can't get capability from unknown factory"); + return capabilities; + } + + auto aidl_retval = provider_factory->getProviderCapabilities(session_type, &capabilities); + if (!aidl_retval.isOk()) { + log::fatal("BluetoothAudioHal::getProviderCapabilities failure: {}", + aidl_retval.getDescription()); + } + return capabilities; +} + +std::optional +BluetoothAudioClientInterface::GetProviderInfo( + SessionType session_type, + std::shared_ptr provider_factory) { + if (!is_aidl_available()) { + return std::nullopt; + } + + if (provider_factory == nullptr) { + provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder( + AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str()))); + } + + if (provider_factory == nullptr) { + log::error("can't get provider info from unknown factory"); + return std::nullopt; + } + + std::optional provider_info = {}; + auto aidl_retval = provider_factory->getProviderInfo(session_type, &provider_info); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::getProviderInfo failure: {}", aidl_retval.getDescription()); + return std::nullopt; + } + + return provider_info; +} + +std::optional BluetoothAudioClientInterface::GetA2dpConfiguration( + std::vector const& remote_capabilities, + A2dpConfigurationHint const& hint) const { + if (!is_aidl_available()) { + return std::nullopt; + } + + if (provider_ == nullptr) { + log::error("can't get a2dp configuration from unknown provider"); + return std::nullopt; + } + + std::optional configuration = std::nullopt; + auto aidl_retval = provider_->getA2dpConfiguration(remote_capabilities, hint, &configuration); + + if (!aidl_retval.isOk()) { + log::error("getA2dpConfiguration failure: {}", aidl_retval.getDescription()); + return std::nullopt; + } + + return configuration; +} + +std::optional BluetoothAudioClientInterface::ParseA2dpConfiguration( + const CodecId& codec_id, const std::vector& configuration, + CodecParameters* codec_parameters) const { + A2dpStatus a2dp_status; + + if (provider_ == nullptr) { + log::error("can not parse A2DP configuration because of unknown provider"); + return std::nullopt; + } + + auto aidl_retval = provider_->parseA2dpConfiguration(codec_id, configuration, codec_parameters, + &a2dp_status); + + if (!aidl_retval.isOk()) { + log::error("parseA2dpConfiguration failure: {}", aidl_retval.getDescription()); + return std::nullopt; + } + + return std::make_optional(a2dp_status); +} + +void BluetoothAudioClientInterface::FetchAudioProvider() { + if (!is_aidl_available()) { + log::error("aidl is not supported on this platform."); + return; + } + if (provider_ != nullptr) { + log::warn("refetch"); + } + // Retry if audioserver restarts in the middle of fetching. + // When audioserver restarts, IBluetoothAudioProviderFactory service is also + // re-registered, so we need to re-fetch the service. + for (int retry_no = 0; retry_no < kFetchAudioProviderRetryNumber; ++retry_no) { + auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder( + AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str()))); + + if (provider_factory == nullptr) { + log::error("can't get capability from unknown factory"); + return; + } + + capabilities_.clear(); + auto aidl_retval = + provider_factory->getProviderCapabilities(transport_->GetSessionType(), &capabilities_); + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::getProviderCapabilities failure: {}, retry number {}", + aidl_retval.getDescription(), retry_no + 1); + continue; + } + if (capabilities_.empty()) { + log::warn("SessionType={} Not supported by BluetoothAudioHal", + toString(transport_->GetSessionType())); + return; + } + log::info("BluetoothAudioHal SessionType={} has {} AudioCapabilities", + toString(transport_->GetSessionType()), capabilities_.size()); + + aidl_retval = provider_factory->openProvider(transport_->GetSessionType(), &provider_); + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::openProvider failure: {}, retry number {}", + aidl_retval.getDescription(), retry_no + 1); + } else { + provider_factory_ = std::move(provider_factory); + break; + } + } + log::assert_that(provider_factory_ != nullptr, "assert failed: provider_factory_ != nullptr"); + log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); + + binder_status_t binder_status = + AIBinder_linkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), this); + if (binder_status != STATUS_OK) { + log::error("Failed to linkToDeath {}", static_cast(binder_status)); + } + + log::info("IBluetoothAudioProvidersFactory::openProvider() returned {}{}", + fmt::ptr(provider_.get()), (provider_->isRemote() ? " (remote)" : " (local)")); +} + +BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface( + IBluetoothSinkTransportInstance* sink) + : BluetoothAudioClientInterface{sink}, sink_(sink) { + FetchAudioProvider(); +} + +BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() { + if (provider_factory_ != nullptr) { + AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); + } +} + +BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface( + IBluetoothSourceTransportInstance* source) + : BluetoothAudioClientInterface{source}, source_(source) { + FetchAudioProvider(); +} + +BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() { + if (provider_factory_ != nullptr) { + AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); + } +} + +void BluetoothAudioClientInterface::binderDiedCallbackAidl(void* ptr) { + log::warn("restarting connection with new Audio Hal"); + auto client = static_cast(ptr); + if (client == nullptr) { + log::error("null audio HAL died!"); + return; + } + client->RenewAudioProviderAndSession(); +} + +bool BluetoothAudioClientInterface::UpdateAudioConfig(const AudioConfiguration& audio_config) { + bool is_software_session = + (transport_->GetSessionType() == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || + transport_->GetSessionType() == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH || + transport_->GetSessionType() == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH || + transport_->GetSessionType() == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH || + transport_->GetSessionType() == + SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH || + (bta_ag_is_sco_managed_by_audio() && + (transport_->GetSessionType() == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH || + transport_->GetSessionType() == SessionType::HFP_SOFTWARE_DECODING_DATAPATH))); + bool is_a2dp_offload_session = + (transport_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); + bool is_leaudio_unicast_offload_session = + (transport_->GetSessionType() == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + transport_->GetSessionType() == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH); + bool is_leaudio_broadcast_offload_session = + (transport_->GetSessionType() == + SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH); + auto audio_config_tag = audio_config.getTag(); + bool is_software_audio_config = + (is_software_session && audio_config_tag == AudioConfiguration::pcmConfig); + bool is_a2dp_offload_audio_config = + (is_a2dp_offload_session && (audio_config_tag == AudioConfiguration::a2dpConfig || + audio_config_tag == AudioConfiguration::a2dp)); + bool is_leaudio_unicast_offload_audio_config = + (is_leaudio_unicast_offload_session && + audio_config_tag == AudioConfiguration::leAudioConfig); + bool is_leaudio_broadcast_offload_audio_config = + (is_leaudio_broadcast_offload_session && + audio_config_tag == AudioConfiguration::leAudioBroadcastConfig); + bool is_hfp_offload_audio_config = + (bta_ag_is_sco_managed_by_audio() && + transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH && + audio_config_tag == AudioConfiguration::hfpConfig); + if (!is_software_audio_config && !is_a2dp_offload_audio_config && + !is_leaudio_unicast_offload_audio_config && !is_leaudio_broadcast_offload_audio_config && + !is_hfp_offload_audio_config) { + return false; + } + transport_->UpdateAudioConfiguration(audio_config); + + if (provider_ == nullptr) { + log::info("BluetoothAudioHal nullptr, update it as session started"); + return true; + } + + if (!session_started_) { + log::info("BluetoothAudioHal session has not started"); + return true; + } + + auto aidl_retval = provider_->updateAudioConfiguration(audio_config); + if (!aidl_retval.isOk()) { + if (audio_config.getTag() != transport_->GetAudioConfiguration().getTag()) { + log::warn( + "BluetoothAudioHal audio config type: {} doesn't " + "match provider's audio config type: {}", + ::aidl::android::hardware::bluetooth::audio::toString(audio_config.getTag()), + ::aidl::android::hardware::bluetooth::audio::toString( + transport_->GetAudioConfiguration().getTag())); + } else { + log::warn("BluetoothAudioHal is not ready: {} ", aidl_retval.getDescription()); + } + } + return true; +} + +bool BluetoothAudioClientInterface::SetAllowedLatencyModes(std::vector latency_modes) { + if (provider_ == nullptr) { + log::info("BluetoothAudioHal nullptr"); + return false; + } + + if (latency_modes.empty()) { + latency_modes_.clear(); + latency_modes_.push_back(LatencyMode::FREE); + } else { + /* Ensure that FREE is always included and remove duplicates if any */ + std::set temp_set(latency_modes.begin(), latency_modes.end()); + temp_set.insert(LatencyMode::FREE); + latency_modes_.clear(); + latency_modes_.assign(temp_set.begin(), temp_set.end()); + } + + for (auto latency_mode : latency_modes) { + log::info("Latency mode allowed: {}", + ::aidl::android::hardware::bluetooth::audio::toString(latency_mode)); + } + + /* Low latency mode is used if modes other than FREE are present */ + bool allowed = (latency_modes_.size() > 1); + log::info("Latency mode allowed: {}", allowed); + auto aidl_retval = provider_->setLowLatencyModeAllowed(allowed); + if (!aidl_retval.isOk()) { + log::warn( + "BluetoothAudioHal is not ready: {}. latency_modes_ is saved and it " + "will be sent to BluetoothAudioHal at StartSession.", + aidl_retval.getDescription()); + } + return true; +} + +int BluetoothAudioClientInterface::StartSession() { + std::lock_guard guard(internal_mutex_); + if (provider_ == nullptr) { + log::error("BluetoothAudioHal nullptr"); + session_started_ = false; + return -EINVAL; + } + if (session_started_) { + log::error("session started already"); + return -EBUSY; + } + + std::shared_ptr stack_if = + ndk::SharedRefBase::make(transport_, provider_); + + std::unique_ptr data_mq; + DataMQDesc mq_desc; + + auto aidl_retval = provider_->startSession(stack_if, transport_->GetAudioConfiguration(), + latency_modes_, &mq_desc); + if (!aidl_retval.isOk()) { + if (aidl_retval.getExceptionCode() == EX_ILLEGAL_ARGUMENT) { + log::error("BluetoothAudioHal Error: {}, audioConfig={}", aidl_retval.getDescription(), + transport_->GetAudioConfiguration().toString()); + } else { + log::fatal("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); + } + return -EPROTO; + } + data_mq.reset(new DataMQ(mq_desc)); + + if (data_mq && data_mq->isValid()) { + data_mq_ = std::move(data_mq); + } else if (transport_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + transport_->GetSessionType() == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || + transport_->GetSessionType() == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + transport_->GetSessionType() == + SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + (bta_ag_is_sco_managed_by_audio() && + transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) { + transport_->ResetPresentationPosition(); + session_started_ = true; + return 0; + } + if (data_mq_ && data_mq_->isValid()) { + transport_->ResetPresentationPosition(); + session_started_ = true; + return 0; + } else { + if (!data_mq_) { + log::error("Failed to obtain audio data path"); + } + if (data_mq_ && !data_mq_->isValid()) { + log::error("Audio data path is invalid"); + } + session_started_ = false; + return -EIO; + } +} + +void BluetoothAudioClientInterface::StreamStarted(const BluetoothAudioCtrlAck& ack) { + if (provider_ == nullptr) { + log::error("BluetoothAudioHal nullptr"); + return; + } + if (ack == BluetoothAudioCtrlAck::PENDING) { + log::info("{} ignored", ack); + return; + } + + auto status = BluetoothAudioCtrlAckToHalStatus(ack); + auto aidl_retval = provider_->streamStarted(status); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); + } +} + +void BluetoothAudioClientInterface::StreamSuspended(const BluetoothAudioCtrlAck& ack) { + if (provider_ == nullptr) { + log::error("BluetoothAudioHal nullptr"); + return; + } + if (ack == BluetoothAudioCtrlAck::PENDING) { + log::info("{} ignored", ack); + return; + } + + auto status = BluetoothAudioCtrlAckToHalStatus(ack); + auto aidl_retval = provider_->streamSuspended(status); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); + } +} + +int BluetoothAudioClientInterface::EndSession() { + std::lock_guard guard(internal_mutex_); + if (!session_started_) { + log::info("session ended already"); + return 0; + } + + session_started_ = false; + if (provider_ == nullptr) { + log::error("BluetoothAudioHal nullptr"); + return -EINVAL; + } + data_mq_ = nullptr; + + auto aidl_retval = provider_->endSession(); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); + return -EPROTO; + } + return 0; +} + +void BluetoothAudioClientInterface::FlushAudioData() { + if (transport_->GetSessionType() == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + transport_->GetSessionType() == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || + transport_->GetSessionType() == + SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + (bta_ag_is_sco_managed_by_audio() && + transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) { + return; + } + + if (data_mq_ == nullptr || !data_mq_->isValid()) { + log::warn("data_mq_ invalid"); + return; + } + size_t size = data_mq_->availableToRead(); + if (size == 0) { + return; + } + + std::vector buffer(size); + + if (data_mq_->read(buffer.data(), size) != size) { + log::warn("failed to flush data queue!"); + } +} + +size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, uint32_t len) { + if (!IsValid()) { + log::error("BluetoothAudioHal is not valid"); + return 0; + } + if (p_buf == nullptr || len == 0) { + return 0; + } + + std::lock_guard guard(internal_mutex_); + + size_t total_read = 0; + int timeout_ms = kDefaultDataReadTimeoutMs; + do { + if (data_mq_ == nullptr || !data_mq_->isValid()) { + break; + } + + size_t avail_to_read = data_mq_->availableToRead(); + if (avail_to_read) { + if (avail_to_read > len - total_read) { + avail_to_read = len - total_read; + } + if (data_mq_->read(reinterpret_cast(p_buf) + total_read, avail_to_read) == 0) { + log::warn("len={} total_read={} failed", len, total_read); + break; + } + total_read += avail_to_read; + } else if (timeout_ms >= kDefaultDataReadPollIntervalMs) { + std::this_thread::sleep_for(std::chrono::milliseconds(kDefaultDataReadPollIntervalMs)); + timeout_ms -= kDefaultDataReadPollIntervalMs; + continue; + } else { + log::warn("{}/{} no data {} ms", len - total_read, len, + kDefaultDataReadTimeoutMs - timeout_ms); + break; + } + } while (total_read < len); + + if (timeout_ms < (kDefaultDataReadTimeoutMs - kDefaultDataReadPollIntervalMs) && + timeout_ms >= kDefaultDataReadPollIntervalMs) { + log::verbose("underflow {} -> {} read {} ms", len, total_read, + kDefaultDataReadTimeoutMs - timeout_ms); + } else { + log::verbose("{} -> {} read", len, total_read); + } + + sink_->LogBytesRead(total_read); + return total_read; +} + +void BluetoothAudioClientInterface::RenewAudioProviderAndSession() { + // NOTE: must be invoked on the same thread where this + // BluetoothAudioClientInterface is running + FetchAudioProvider(); + + if (session_started_) { + log::info("Restart the session while audio HAL recovering"); + session_started_ = false; + + StartSession(); + } +} + +size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, uint32_t len) { + if (!IsValid()) { + log::error("BluetoothAudioHal is not valid"); + return 0; + } + if (p_buf == nullptr || len == 0) { + return 0; + } + + std::lock_guard guard(internal_mutex_); + + size_t total_written = 0; + int timeout_ms = kDefaultDataWriteTimeoutMs; + do { + if (data_mq_ == nullptr || !data_mq_->isValid()) { + break; + } + + size_t avail_to_write = data_mq_->availableToWrite(); + if (avail_to_write) { + if (avail_to_write > len - total_written) { + avail_to_write = len - total_written; + } + if (data_mq_->write((const MqDataType*)p_buf + total_written, avail_to_write) == 0) { + log::warn("len={} total_written={} failed", len, total_written); + break; + } + total_written += avail_to_write; + } else if (timeout_ms >= kDefaultDataWritePollIntervalMs) { + std::this_thread::sleep_for(std::chrono::milliseconds(kDefaultDataWritePollIntervalMs)); + timeout_ms -= kDefaultDataWritePollIntervalMs; + continue; + } else { + log::warn("{}/{} no data {} ms", len - total_written, len, + kDefaultDataWriteTimeoutMs - timeout_ms); + break; + } + } while (total_written < len); + + if (timeout_ms < (kDefaultDataWriteTimeoutMs - kDefaultDataWritePollIntervalMs) && + timeout_ms >= kDefaultDataWritePollIntervalMs) { + log::verbose("underflow {} -> {} read {} ms", len, total_written, + kDefaultDataWriteTimeoutMs - timeout_ms); + } else { + log::verbose("{} -> {} written", len, total_written); + } + + source_->LogBytesWritten(total_written); + return total_written; +} + +void BluetoothAudioClientInterface::SetCodecPriority(CodecId codec_id, int32_t priority) { + log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); + auto aidl_retval = provider_->setCodecPriority(codec_id, priority); + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::setCodecPriority failure: {}", aidl_retval.getDescription()); + } +} + +std::vector +BluetoothAudioClientInterface::GetLeAudioAseConfiguration( + std::optional< + std::vector>>& + remoteSinkAudioCapabilities, + std::optional< + std::vector>>& + remoteSourceAudioCapabilities, + std::vector& requirements) { + log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); + + std::vector configurations; + auto aidl_retval = provider_->getLeAudioAseConfiguration(remoteSinkAudioCapabilities, + remoteSourceAudioCapabilities, + requirements, &configurations); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::getLeAudioAseConfiguration failure: {}", + aidl_retval.getDescription()); + } else { + log::info( + "BluetoothAudioHal::getLeAudioAseConfiguration returned {} " + "configurations.", + configurations.size()); + } + + return configurations; +} + +IBluetoothAudioProvider::LeAudioAseQosConfigurationPair +BluetoothAudioClientInterface::getLeAudioAseQosConfiguration( + IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement& qosRequirement) { + log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); + + IBluetoothAudioProvider::LeAudioAseQosConfigurationPair qos_configuration; + auto aidl_retval = provider_->getLeAudioAseQosConfiguration(qosRequirement, &qos_configuration); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::getLeAudioAseQosConfiguration failure: {}", + aidl_retval.getDescription()); + } + return qos_configuration; +} + +void BluetoothAudioClientInterface::onSinkAseMetadataChanged( + IBluetoothAudioProvider::AseState state, int32_t cigId, int32_t cisId, + std::optional>>& metadata) { + log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); + + auto aidl_retval = provider_->onSinkAseMetadataChanged(state, cigId, cisId, metadata); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::onSinkAseMetadataChanged failure: {}", + aidl_retval.getDescription()); + } +} + +void BluetoothAudioClientInterface::onSourceAseMetadataChanged( + IBluetoothAudioProvider::AseState state, int32_t cigId, int32_t cisId, + std::optional>>& metadata) { + log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); + + auto aidl_retval = provider_->onSourceAseMetadataChanged(state, cigId, cisId, metadata); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::onSourceAseMetadataChanged failure: {}", + aidl_retval.getDescription()); + } +} + +IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting +BluetoothAudioClientInterface::getLeAudioBroadcastConfiguration( + const std::optional< + std::vector>>& + remoteSinkAudioCapabilities, + const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& requirement) { + log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); + + IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting setting; + auto aidl_retval = provider_->getLeAudioBroadcastConfiguration(remoteSinkAudioCapabilities, + requirement, &setting); + + if (!aidl_retval.isOk()) { + log::error("BluetoothAudioHal::getLeAudioBroadcastConfiguration failure: {}", + aidl_retval.getDescription()); + } + + return setting; +} + +} // namespace a2dp +} // namespace aidl +} // namespace audio +} // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h new file mode 100644 index 00000000000..89aa10f75a7 --- /dev/null +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h @@ -0,0 +1,228 @@ +/* + * Copyright 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. + */ + +#pragma once + +#include +#include + +#include +#include +#include + +#include "audio_aidl_interfaces.h" +#include "audio_ctrl_ack.h" +#include "bluetooth_audio_port_impl.h" +#include "bta/le_audio/broadcaster/broadcaster_types.h" +#include "bta/le_audio/le_audio_types.h" +#include "transport_instance.h" + +namespace bluetooth { +namespace audio { +namespace aidl { +namespace a2dp { + +using ::aidl::android::hardware::bluetooth::audio::A2dpConfiguration; +using ::aidl::android::hardware::bluetooth::audio::A2dpConfigurationHint; +using ::aidl::android::hardware::bluetooth::audio::A2dpRemoteCapabilities; +using ::aidl::android::hardware::bluetooth::audio::A2dpStatus; +using ::aidl::android::hardware::bluetooth::audio::AudioCapabilities; +using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; +using ::aidl::android::hardware::bluetooth::audio::CodecId; +using ::aidl::android::hardware::bluetooth::audio::CodecInfo; +using ::aidl::android::hardware::bluetooth::audio::CodecParameters; +using ::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv; +using ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv; +using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort; +using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider; +using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory; +using ::aidl::android::hardware::bluetooth::audio::LatencyMode; +using ::aidl::android::hardware::bluetooth::audio::MetadataLtv; +using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration; + +using ::aidl::android::hardware::common::fmq::MQDescriptor; +using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; +using ::android::AidlMessageQueue; + +using MqDataType = int8_t; +using MqDataMode = SynchronizedReadWrite; +using DataMQ = AidlMessageQueue; +using DataMQDesc = MQDescriptor; + +/*** + * The client interface connects an IBluetoothTransportInstance to + * IBluetoothAudioProvider and helps to route callbacks to + * IBluetoothTransportInstance + ***/ +class BluetoothAudioClientInterface { +public: + BluetoothAudioClientInterface(IBluetoothTransportInstance* instance); + virtual ~BluetoothAudioClientInterface() = default; + + bool IsValid() const; + + std::vector GetAudioCapabilities() const; + + static std::vector GetAudioCapabilities(SessionType session_type); + static std::optional GetProviderInfo( + SessionType session_type, + std::shared_ptr provider_factory = nullptr); + + std::optional ParseA2dpConfiguration(const CodecId& codec_id, + const std::vector& configuration, + CodecParameters* codec_parameters) const; + + std::optional GetA2dpConfiguration( + std::vector const& remote_capabilities, + A2dpConfigurationHint const& hint) const; + + void StreamStarted(const BluetoothAudioCtrlAck& ack); + + void StreamSuspended(const BluetoothAudioCtrlAck& ack); + + int StartSession(); + + /*** + * Renew the connection and usually is used when aidl restarted + ***/ + void RenewAudioProviderAndSession(); + + int EndSession(); + + bool UpdateAudioConfig(const AudioConfiguration& audioConfig); + + bool SetAllowedLatencyModes(std::vector latency_modes); + + void FlushAudioData(); + + void SetCodecPriority(CodecId codec_id, int32_t priority); + + std::vector GetLeAudioAseConfiguration( + std::optional< + std::vector>>& + remoteSinkAudioCapabilities, + std::optional< + std::vector>>& + remoteSourceAudioCapabilities, + std::vector& requirements); + + IBluetoothAudioProvider::LeAudioAseQosConfigurationPair getLeAudioAseQosConfiguration( + IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement& qosRequirement); + + void onSinkAseMetadataChanged(IBluetoothAudioProvider::AseState state, int32_t cigId, + int32_t cisId, + std::optional>>& metadata); + + void onSourceAseMetadataChanged(IBluetoothAudioProvider::AseState state, int32_t cigId, + int32_t cisId, + std::optional>>& metadata); + + IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting getLeAudioBroadcastConfiguration( + const std::optional< + std::vector>>& + remoteSinkAudioCapabilities, + const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& requirement); + + static constexpr PcmConfiguration kInvalidPcmConfiguration = {}; + + static bool is_aidl_available(); + +protected: + mutable std::mutex internal_mutex_; + /*** + * Helper function to connect to an IBluetoothAudioProvider + ***/ + void FetchAudioProvider(); + + /*** + * Invoked when binder died + ***/ + static void binderDiedCallbackAidl(void* cookie_ptr); + + std::shared_ptr provider_; + + std::shared_ptr provider_factory_; + + bool session_started_; + std::unique_ptr data_mq_; + + ::ndk::ScopedAIBinder_DeathRecipient death_recipient_; + // static constexpr const char* kDefaultAudioProviderFactoryInterface = + // "android.hardware.bluetooth.audio.IBluetoothAudioProviderFactory/default"; + static inline const std::string kDefaultAudioProviderFactoryInterface = + std::string() + IBluetoothAudioProviderFactory::descriptor + "/default"; + +private: + IBluetoothTransportInstance* transport_; + std::vector capabilities_; + std::vector latency_modes_; +}; + +/*** + * The client interface connects an IBluetoothTransportInstance to + * IBluetoothAudioProvider and helps to route callbacks to + * IBluetoothTransportInstance + ***/ +class BluetoothAudioSinkClientInterface : public BluetoothAudioClientInterface { +public: + /*** + * Constructs an BluetoothAudioSinkClientInterface to communicate to + * BluetoothAudio HAL. |sink| is the implementation for the transport. + ***/ + BluetoothAudioSinkClientInterface(IBluetoothSinkTransportInstance* sink); + virtual ~BluetoothAudioSinkClientInterface(); + + IBluetoothSinkTransportInstance* GetTransportInstance() const { return sink_; } + + /*** + * Read data from audio HAL through fmq + ***/ + size_t ReadAudioData(uint8_t* p_buf, uint32_t len); + +private: + IBluetoothSinkTransportInstance* sink_; + + static constexpr int kDefaultDataReadTimeoutMs = 10; + static constexpr int kDefaultDataReadPollIntervalMs = 1; +}; + +class BluetoothAudioSourceClientInterface : public BluetoothAudioClientInterface { +public: + /*** + * Constructs an BluetoothAudioSourceClientInterface to communicate to + * BluetoothAudio HAL. |source| is the implementation for the transport. + ***/ + BluetoothAudioSourceClientInterface(IBluetoothSourceTransportInstance* source); + virtual ~BluetoothAudioSourceClientInterface(); + + IBluetoothSourceTransportInstance* GetTransportInstance() const { return source_; } + + /*** + * Write data to audio HAL through fmq + ***/ + size_t WriteAudioData(const uint8_t* p_buf, uint32_t len); + +private: + IBluetoothSourceTransportInstance* source_; + + static constexpr int kDefaultDataWriteTimeoutMs = 10; + static constexpr int kDefaultDataWritePollIntervalMs = 1; +}; + +} // namespace a2dp +} // namespace aidl +} // namespace audio +} // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/codec_status_aidl.cc b/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.cc similarity index 99% rename from system/audio_hal_interface/aidl/codec_status_aidl.cc rename to system/audio_hal_interface/aidl/a2dp/codec_status_aidl.cc index 9f5fc95dab4..d9c85c5a577 100644 --- a/system/audio_hal_interface/aidl/codec_status_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.cc @@ -34,6 +34,7 @@ namespace bluetooth { namespace audio { namespace aidl { +namespace a2dp { namespace codec { using ::aidl::android::hardware::bluetooth::audio::AacCapabilities; @@ -588,6 +589,7 @@ bool IsCodecOffloadingEnabled(const CodecConfiguration& codec_config) { } } // namespace codec +} // namespace a2dp } // namespace aidl } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/codec_status_aidl.h b/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.h similarity index 98% rename from system/audio_hal_interface/aidl/codec_status_aidl.h rename to system/audio_hal_interface/aidl/a2dp/codec_status_aidl.h index b6eb8fb04f3..6ca6604c216 100644 --- a/system/audio_hal_interface/aidl/codec_status_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.h @@ -24,6 +24,7 @@ namespace bluetooth { namespace audio { namespace aidl { +namespace a2dp { namespace codec { using ::aidl::android::hardware::bluetooth::audio::ChannelMode; @@ -51,6 +52,7 @@ bool UpdateOffloadingCapabilities( bool IsCodecOffloadingEnabled(const CodecConfiguration& codec_config); } // namespace codec +} // namespace a2dp } // namespace aidl } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/a2dp/transport_instance.h b/system/audio_hal_interface/aidl/a2dp/transport_instance.h new file mode 100644 index 00000000000..3d458969ecb --- /dev/null +++ b/system/audio_hal_interface/aidl/a2dp/transport_instance.h @@ -0,0 +1,132 @@ +/* + * Copyright 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. + */ + +#pragma once + +#include + +#include "audio_aidl_interfaces.h" +#include "audio_ctrl_ack.h" + +namespace bluetooth { +namespace audio { +namespace aidl { +namespace a2dp { + +using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; +using ::aidl::android::hardware::bluetooth::audio::LatencyMode; +using ::aidl::android::hardware::bluetooth::audio::SessionType; + +/*** + * An IBluetoothTransportInstance needs to be implemented by a Bluetooth + * audio transport, such as A2DP or Hearing Aid, to handle callbacks from Audio + * HAL. + ***/ +class IBluetoothTransportInstance { +public: + IBluetoothTransportInstance(SessionType sessionType, AudioConfiguration audioConfig) + : session_type_(sessionType), audio_config_(std::move(audioConfig)) {} + virtual ~IBluetoothTransportInstance() = default; + + SessionType GetSessionType() const { return session_type_; } + + AudioConfiguration GetAudioConfiguration() const { return audio_config_; } + + void UpdateAudioConfiguration(const AudioConfiguration& audio_config) { + switch (audio_config.getTag()) { + case AudioConfiguration::pcmConfig: + audio_config_.set( + audio_config.get()); + break; + case AudioConfiguration::a2dpConfig: + audio_config_.set( + audio_config.get()); + break; + case AudioConfiguration::hfpConfig: + audio_config_.set( + audio_config.get()); + break; + case AudioConfiguration::leAudioConfig: + audio_config_.set( + audio_config.get()); + break; + case AudioConfiguration::leAudioBroadcastConfig: + audio_config_.set( + audio_config.get()); + break; + case AudioConfiguration::a2dp: + audio_config_.set(audio_config.get()); + break; + } + } + + virtual BluetoothAudioCtrlAck StartRequest(bool is_low_latency) = 0; + + virtual BluetoothAudioCtrlAck SuspendRequest() = 0; + + virtual void StopRequest() = 0; + + virtual void SetLatencyMode(LatencyMode latency_mode) = 0; + + virtual bool GetPresentationPosition(uint64_t* remote_delay_report_ns, + uint64_t* total_bytes_readed, timespec* data_position) = 0; + + virtual void SourceMetadataChanged(const source_metadata_v7_t& source_metadata) = 0; + virtual void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) = 0; + + /*** + * Invoked when the transport is requested to reset presentation position + ***/ + virtual void ResetPresentationPosition() = 0; + +private: + const SessionType session_type_; + AudioConfiguration audio_config_; +}; + +/*** + * An IBluetoothSinkTransportInstance needs to be implemented by a Bluetooth + * audio transport, such as A2DP, Hearing Aid or LeAudio, to handle callbacks + * from Audio HAL. + ***/ +class IBluetoothSinkTransportInstance : public IBluetoothTransportInstance { +public: + IBluetoothSinkTransportInstance(SessionType sessionType, AudioConfiguration audioConfig) + : IBluetoothTransportInstance{sessionType, audioConfig} {} + virtual ~IBluetoothSinkTransportInstance() = default; + + /*** + * Invoked when the transport is requested to log bytes read + ***/ + virtual void LogBytesRead(size_t bytes_readed) = 0; +}; + +class IBluetoothSourceTransportInstance : public IBluetoothTransportInstance { +public: + IBluetoothSourceTransportInstance(SessionType sessionType, AudioConfiguration audioConfig) + : IBluetoothTransportInstance{sessionType, audioConfig} {} + virtual ~IBluetoothSourceTransportInstance() = default; + + /*** + * Invoked when the transport is requested to log bytes written + ***/ + virtual void LogBytesWritten(size_t bytes_written) = 0; +}; + +} // namespace a2dp +} // namespace aidl +} // namespace audio +} // namespace bluetooth 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 72ebc9ecb36..8e3d8bfa03d 100644 --- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc +++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc @@ -27,7 +27,6 @@ #include #include -#include "codec_status_aidl.h" #include "hal_version_manager.h" #include "os/log.h" -- GitLab From f1fbeb1f1a6d32a8fb61bd663eeb918339cee57e Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 1 Oct 2024 14:03:11 -0700 Subject: [PATCH 119/875] SystemServer: prevent state change after crash Bug: 369633468 Fix: 369633468 Flag: Exempt null check Test: m ServiceBluetoothTests Change-Id: I83442a318889023d4882133666c99c93b1bac625 --- .../bluetooth/BluetoothManagerService.java | 28 ++++++---- .../BluetoothManagerServiceTest.java | 53 ++++++++++++++++--- 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index d7d7997e9d9..6dd7ebc449b 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -23,6 +23,7 @@ import static android.bluetooth.BluetoothAdapter.STATE_OFF; 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 android.bluetooth.BluetoothAdapter.nameForState; import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE; import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST; import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH; @@ -216,6 +217,11 @@ class BluetoothManagerService { new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) { + Log.d( + TAG, + "IBluetoothCallback.onBluetoothStateChange:" + + (" prevState=" + nameForState(prevState)) + + (" newState=" + nameForState(newState))); mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState) .sendToTarget(); } @@ -226,6 +232,7 @@ class BluetoothManagerService { if (name.isEmpty()) { throw new IllegalArgumentException("Invalid Empty name"); } + Log.d(TAG, "IBluetoothCallback.onAdapterNameChange: " + name); mHandler.post(() -> storeName(name)); } @@ -235,6 +242,7 @@ class BluetoothManagerService { if (!BluetoothAdapter.checkBluetoothAddress(address)) { throw new IllegalArgumentException("Invalid address"); } + Log.d(TAG, "IBluetoothCallback.onAdapterAddressChange: " + logAddress(address)); mHandler.post(() -> storeAddress(address)); } }; @@ -353,7 +361,7 @@ class BluetoothManagerService { Log.d( TAG, ("delayModeChangedIfNeeded(" + modechanged + "):") - + (" state=" + BluetoothAdapter.nameForState(state)) + + (" state=" + nameForState(state)) + (" Airplane.isOnOverrode=" + AirplaneModeListener.isOnOverrode()) + (" Airplane.isOn=" + AirplaneModeListener.isOn()) + (" isSatelliteModeOn()=" + isSatelliteModeOn()) @@ -458,7 +466,7 @@ class BluetoothManagerService { Log.d( TAG, ("handleAirplaneModeChanged(" + isAirplaneModeOn + "):") - + (" currentState=" + BluetoothAdapter.nameForState(currentState))); + + (" currentState=" + nameForState(currentState))); if (isAirplaneModeOn) { forceToOffFromModeChange(currentState, ENABLE_DISABLE_REASON_AIRPLANE_MODE); @@ -1596,8 +1604,12 @@ class BluetoothManagerService { Log.d( TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE:" - + (" prevState=" + BluetoothAdapter.nameForState(prevState)) - + (" newState=" + BluetoothAdapter.nameForState(newState))); + + (" prevState=" + nameForState(prevState)) + + (" newState=" + nameForState(newState))); + if (mAdapter == null) { + Log.e(TAG, "State change received after bluetooth has crashed"); + break; + } bluetoothStateChangeHandler(prevState, newState); // handle error state transition case from TURNING_ON to OFF // unbind and rebind bluetooth service and enable bluetooth @@ -1955,8 +1967,8 @@ class BluetoothManagerService { TAG, "broadcastIntentStateChange:" + (" action=" + action.substring(action.lastIndexOf('.') + 1)) - + (" prevState=" + BluetoothAdapter.nameForState(prevState)) - + (" newState=" + BluetoothAdapter.nameForState(newState))); + + (" prevState=" + nameForState(prevState)) + + (" newState=" + nameForState(newState))); // Send broadcast message to everyone else Intent intent = new Intent(action); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); @@ -2304,9 +2316,7 @@ class BluetoothManagerService { final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd)); proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled()); proto.write(BluetoothManagerServiceDumpProto.STATE, mState.get()); - proto.write( - BluetoothManagerServiceDumpProto.STATE_NAME, - BluetoothAdapter.nameForState(mState.get())); + proto.write(BluetoothManagerServiceDumpProto.STATE_NAME, nameForState(mState.get())); proto.write(BluetoothManagerServiceDumpProto.ADDRESS, logAddress(mAddress)); proto.write(BluetoothManagerServiceDumpProto.NAME, mName); if (mEnable) { diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java index 6e9222a7449..49dfc45b46a 100644 --- a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java +++ b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java @@ -22,9 +22,11 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON; import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON; 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; import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_DISABLE; import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_ENABLE; +import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_RESTART_BLUETOOTH_SERVICE; import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_TIMEOUT_BIND; import static com.google.common.truth.Truth.assertThat; @@ -173,6 +175,7 @@ public class BluetoothManagerServiceTest { any(ServiceConnection.class), anyInt(), any(UserHandle.class)); + doNothing().when(mContext).unbindService(any()); BluetoothServerProxy.setInstanceForTesting(mBluetoothServerProxy); @@ -244,7 +247,6 @@ public class BluetoothManagerServiceTest { any(ServiceConnection.class), anyInt(), any(UserHandle.class)); - doNothing().when(mContext).unbindService(any()); mManagerService.enableBle("enable_bindFailure_removesTimeout", mBinder); syncHandler(MESSAGE_ENABLE); verify(mContext).unbindService(any()); @@ -269,18 +271,22 @@ public class BluetoothManagerServiceTest { // * if user ask to enable again, it will start a second bind but the first still run } - private void acceptBluetoothBinding(IBinder binder, String name, int n) { - ComponentName compName = new ComponentName("", "com.android.bluetooth." + name); + private BluetoothManagerService.BluetoothServiceConnection acceptBluetoothBinding() { + ComponentName compName = + new ComponentName("", "com.android.bluetooth.btservice.AdapterService"); ArgumentCaptor captor = ArgumentCaptor.forClass(BluetoothManagerService.BluetoothServiceConnection.class); - verify(mContext, times(n)) + verify(mContext) .bindServiceAsUser( any(Intent.class), captor.capture(), anyInt(), any(UserHandle.class)); - assertThat(captor.getAllValues().size()).isEqualTo(n); + assertThat(captor.getAllValues().size()).isEqualTo(1); - captor.getAllValues().get(n - 1).onServiceConnected(compName, binder); + BluetoothManagerService.BluetoothServiceConnection serviceConnection = + captor.getAllValues().get(0); + serviceConnection.onServiceConnected(compName, mBinder); syncHandler(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); + return serviceConnection; } private static IBluetoothCallback captureBluetoothCallback(AdapterBinder adapterBinder) @@ -294,7 +300,7 @@ public class BluetoothManagerServiceTest { IBluetoothCallback transition_offToBleOn() throws Exception { // Binding of IBluetooth - acceptBluetoothBinding(mBinder, "btservice.AdapterService", 1); + acceptBluetoothBinding(); // TODO(b/280518177): This callback is too early, bt is not ON nor BLE_ON verify(mManagerCallback).onBluetoothServiceUp(any()); @@ -361,4 +367,37 @@ public class BluetoothManagerServiceTest { assertThat(mManagerService.getState()).isEqualTo(STATE_ON); } + + @Test + public void crash_whileTransitionState_canRecover() throws Exception { + mManagerService.enableBle("crash_whileTransitionState_canRecover", mBinder); + syncHandler(MESSAGE_ENABLE); + + BluetoothManagerService.BluetoothServiceConnection serviceConnection = + acceptBluetoothBinding(); + + IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder); + 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); + + serviceConnection.onServiceDisconnected( + new ComponentName("", "com.android.bluetooth.btservice.AdapterService")); + syncHandler(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); + assertThat(mManagerService.getState()).isEqualTo(STATE_OFF); + + // Send a late bluetoothStateChange (since it can happen concurrently) + btCallback.onBluetoothStateChange(STATE_BLE_TURNING_ON, STATE_BLE_ON); + syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE); + + // Bluetooth is still OFF and doesn't crash + assertThat(mManagerService.getState()).isEqualTo(STATE_OFF); + + mLooper.moveTimeForward(120_000); + Message msg = mLooper.nextMessage(); + assertThat(msg).isNotNull(); + assertThat(msg.what).isEqualTo(MESSAGE_RESTART_BLUETOOTH_SERVICE); + // Discard the msg without executing it + } } -- GitLab From 34e8ce242fbee2b526735179bab6c2a6631c6d48 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 1 Oct 2024 17:14:33 -0700 Subject: [PATCH 120/875] SystemServer: Remove un-necessary synchronize All this code is running on a unique handler. The synchronize keyword is coming from legacy and doesn't make sense anymore Bug: 288450479 Test: m Bluetooth Flag: Exempt trivial removal Change-Id: Ib32abd5bba95e2670804e8dcfcf8555d21907407 --- .../bluetooth/BluetoothManagerService.java | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index d7d7997e9d9..749d9d17f3e 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -983,9 +983,7 @@ class BluetoothManagerService { Log.i(TAG, "enableBle: Bluetooth is already in state" + mState); return true; } - synchronized (mReceiver) { - sendEnableMsg(false, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName, true); - } + sendEnableMsg(false, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName, true); return true; } @@ -1110,11 +1108,9 @@ class BluetoothManagerService { return false; } - synchronized (mReceiver) { - mQuietEnableExternal = true; - mEnableExternal = true; - sendEnableMsg(true, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); - } + mQuietEnableExternal = true; + mEnableExternal = true; + sendEnableMsg(true, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); return true; } @@ -1136,13 +1132,11 @@ class BluetoothManagerService { return false; } - synchronized (mReceiver) { - mQuietEnableExternal = false; - mEnableExternal = true; - AirplaneModeListener.notifyUserToggledBluetooth( - mContentResolver, mCurrentUserContext, true); - sendEnableMsg(false, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); - } + mQuietEnableExternal = false; + mEnableExternal = true; + AirplaneModeListener.notifyUserToggledBluetooth( + mContentResolver, mCurrentUserContext, true); + sendEnableMsg(false, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); return true; } @@ -1159,16 +1153,14 @@ class BluetoothManagerService { + (" isBinding=" + isBinding()) + (" mState=" + mState)); - synchronized (mReceiver) { - AirplaneModeListener.notifyUserToggledBluetooth( - mContentResolver, mCurrentUserContext, false); + AirplaneModeListener.notifyUserToggledBluetooth( + mContentResolver, mCurrentUserContext, false); - if (persist) { - setBluetoothPersistedState(BLUETOOTH_OFF); - } - mEnableExternal = false; - sendDisableMsg(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + if (persist) { + setBluetoothPersistedState(BLUETOOTH_OFF); } + mEnableExternal = false; + sendDisableMsg(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); return true; } -- GitLab From 011a4671e0b3e2e661351f1d88c0882532ed3319 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 20 Sep 2024 00:43:18 +0000 Subject: [PATCH 121/875] audio_hal_interface/aidl/a2dp: Remove BluetoothAudioCtrlAck This enum was added to shim the type from the aidl interface; the type BluetoothAudioStatus from bluetooth::audio::a2dp now can be used directly. Test: m com.android.btservices Flag: EXEMPT, no logical change Bug: 365022887 Change-Id: I9070390383c7a2aaa4755e57b3745c2f1296442e --- .../aidl/a2dp/a2dp_encoding_aidl.cc | 36 +++------- .../aidl/a2dp/a2dp_transport.h | 6 +- .../aidl/a2dp/audio_ctrl_ack.h | 69 ------------------- .../aidl/a2dp/bluetooth_audio_port_impl.cc | 13 ++-- .../aidl/a2dp/client_interface_aidl.cc | 31 ++------- .../aidl/a2dp/client_interface_aidl.h | 23 ++++++- .../aidl/a2dp/transport_instance.h | 7 +- 7 files changed, 51 insertions(+), 134 deletions(-) delete mode 100644 system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc index a3e0ec2a1c1..99f957d29dc 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc @@ -57,7 +57,6 @@ using ::aidl::android::hardware::bluetooth::audio::CodecConfiguration; using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration; using ::aidl::android::hardware::bluetooth::audio::SessionType; -using ::bluetooth::audio::aidl::a2dp::BluetoothAudioCtrlAck; using ::bluetooth::audio::aidl::a2dp::BluetoothAudioSinkClientInterface; using ::bluetooth::audio::aidl::a2dp::codec::A2dpAacToHalConfig; using ::bluetooth::audio::aidl::a2dp::codec::A2dpAptxToHalConfig; @@ -68,21 +67,6 @@ using ::bluetooth::audio::aidl::a2dp::codec::A2dpLdacToHalConfig; using ::bluetooth::audio::aidl::a2dp::codec::A2dpOpusToHalConfig; using ::bluetooth::audio::aidl::a2dp::codec::A2dpSbcToHalConfig; -static BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(BluetoothAudioStatus ack) { - switch (ack) { - case BluetoothAudioStatus::SUCCESS: - return BluetoothAudioCtrlAck::SUCCESS_FINISHED; - case BluetoothAudioStatus::PENDING: - return BluetoothAudioCtrlAck::PENDING; - case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: - return BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED; - case BluetoothAudioStatus::UNKNOWN: - case BluetoothAudioStatus::FAILURE: - default: - return BluetoothAudioCtrlAck::FAILURE; - } -} - /*** * * A2dpTransport functions and variables @@ -101,17 +85,17 @@ A2dpTransport::A2dpTransport(SessionType sessionType) remote_delay_report_ = 0; } -BluetoothAudioCtrlAck A2dpTransport::StartRequest(bool is_low_latency) { +BluetoothAudioStatus A2dpTransport::StartRequest(bool is_low_latency) { // Check if a previous Start request is ongoing. if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_START) { log::warn("unable to start stream: already pending"); - return BluetoothAudioCtrlAck::PENDING; + return BluetoothAudioStatus::PENDING; } // Check if a different request is ongoing. if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { log::warn("unable to start stream: busy with pending command {}", a2dp_pending_cmd_); - return BluetoothAudioCtrlAck::FAILURE; + return BluetoothAudioStatus::FAILURE; } log::info(""); @@ -120,20 +104,20 @@ BluetoothAudioCtrlAck A2dpTransport::StartRequest(bool is_low_latency) { a2dp_pending_cmd_ = status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_START : A2DP_CTRL_CMD_NONE; - return a2dp_ack_to_bt_audio_ctrl_ack(status); + return status; } -BluetoothAudioCtrlAck A2dpTransport::SuspendRequest() { +BluetoothAudioStatus A2dpTransport::SuspendRequest() { // Check if a previous Suspend request is ongoing. if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_SUSPEND) { log::warn("unable to suspend stream: already pending"); - return BluetoothAudioCtrlAck::PENDING; + return BluetoothAudioStatus::PENDING; } // Check if a different request is ongoing. if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) { log::warn("unable to suspend stream: busy with pending command {}", a2dp_pending_cmd_); - return BluetoothAudioCtrlAck::FAILURE; + return BluetoothAudioStatus::FAILURE; } log::info(""); @@ -142,7 +126,7 @@ BluetoothAudioCtrlAck A2dpTransport::SuspendRequest() { a2dp_pending_cmd_ = status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_SUSPEND : A2DP_CTRL_CMD_NONE; - return a2dp_ack_to_bt_audio_ctrl_ack(status); + return status; } void A2dpTransport::StopRequest() { @@ -534,7 +518,7 @@ void ack_stream_started(BluetoothAudioStatus ack) { auto a2dp_sink = static_cast(active_hal_interface->GetTransportInstance()); auto pending_cmd = a2dp_sink->GetPendingCmd(); if (pending_cmd == A2DP_CTRL_CMD_START) { - active_hal_interface->StreamStarted(a2dp_ack_to_bt_audio_ctrl_ack(ack)); + active_hal_interface->StreamStarted(ack); } else { log::warn("pending={} ignore result={}", pending_cmd, ack); return; @@ -553,7 +537,7 @@ void ack_stream_suspended(BluetoothAudioStatus ack) { auto a2dp_sink = static_cast(active_hal_interface->GetTransportInstance()); auto pending_cmd = a2dp_sink->GetPendingCmd(); if (pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - active_hal_interface->StreamSuspended(a2dp_ack_to_bt_audio_ctrl_ack(ack)); + active_hal_interface->StreamSuspended(ack); } else if (pending_cmd == A2DP_CTRL_CMD_STOP) { log::info("A2DP_CTRL_CMD_STOP result={}", ack); } else { diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h b/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h index ae244ccbc33..7dec755aacb 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h @@ -16,6 +16,7 @@ #pragma once +#include "a2dp_encoding.h" #include "client_interface_aidl.h" typedef enum { @@ -37,6 +38,7 @@ namespace a2dp { namespace { +using ::bluetooth::audio::a2dp::BluetoothAudioStatus; using ::bluetooth::audio::aidl::a2dp::LatencyMode; // Provide call-in APIs for the Bluetooth Audio HAL @@ -44,9 +46,9 @@ class A2dpTransport : public ::bluetooth::audio::aidl::a2dp::IBluetoothSinkTrans public: A2dpTransport(SessionType sessionType); - BluetoothAudioCtrlAck StartRequest(bool is_low_latency) override; + BluetoothAudioStatus StartRequest(bool is_low_latency) override; - BluetoothAudioCtrlAck SuspendRequest() override; + BluetoothAudioStatus SuspendRequest() override; void StopRequest() override; diff --git a/system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h b/system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h deleted file mode 100644 index 0bb70c13353..00000000000 --- a/system/audio_hal_interface/aidl/a2dp/audio_ctrl_ack.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 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. - */ - -#pragma once - -#include - -#include "audio_aidl_interfaces.h" - -namespace bluetooth { -namespace audio { -namespace aidl { -namespace a2dp { - -enum class BluetoothAudioCtrlAck : uint8_t { - SUCCESS_FINISHED = 0, - SUCCESS_RECONFIGURATION, - PENDING, - FAILURE_UNSUPPORTED, - FAILURE_BUSY, - FAILURE_DISCONNECTING, - FAILURE -}; - -std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack); - -inline ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus -BluetoothAudioCtrlAckToHalStatus(const BluetoothAudioCtrlAck& ack) { - using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus; - switch (ack) { - case BluetoothAudioCtrlAck::SUCCESS_FINISHED: - return BluetoothAudioStatus::SUCCESS; - case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED: - return BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION; - case BluetoothAudioCtrlAck::PENDING: - return BluetoothAudioStatus::FAILURE; - case BluetoothAudioCtrlAck::FAILURE_BUSY: - return BluetoothAudioStatus::FAILURE; - case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING: - return BluetoothAudioStatus::FAILURE; - case BluetoothAudioCtrlAck::SUCCESS_RECONFIGURATION: - return BluetoothAudioStatus::RECONFIGURATION; - default: - return BluetoothAudioStatus::FAILURE; - } -} - -} // namespace a2dp -} // namespace aidl -} // namespace audio -} // namespace bluetooth - -namespace fmt { -template <> -struct formatter : ostream_formatter {}; -} // namespace fmt diff --git a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc index 30d83a2937c..7a715c91f22 100644 --- a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc +++ b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc @@ -21,6 +21,7 @@ #include +#include "client_interface_aidl.h" #include "android/binder_ibinder_platform.h" #include "btif/include/btif_common.h" #include "common/stop_watch_legacy.h" @@ -41,9 +42,9 @@ BluetoothAudioPortImpl::~BluetoothAudioPortImpl() {} ndk::ScopedAStatus BluetoothAudioPortImpl::startStream(bool is_low_latency) { StopWatchLegacy stop_watch(__func__); - BluetoothAudioCtrlAck ack = transport_instance_->StartRequest(is_low_latency); - if (ack != BluetoothAudioCtrlAck::PENDING) { - auto aidl_retval = provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack)); + BluetoothAudioStatus ack = transport_instance_->StartRequest(is_low_latency); + if (ack != BluetoothAudioStatus::PENDING) { + auto aidl_retval = provider_->streamStarted(BluetoothAudioStatusToHalStatus(ack)); if (!aidl_retval.isOk()) { log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); } @@ -53,9 +54,9 @@ ndk::ScopedAStatus BluetoothAudioPortImpl::startStream(bool is_low_latency) { ndk::ScopedAStatus BluetoothAudioPortImpl::suspendStream() { StopWatchLegacy stop_watch(__func__); - BluetoothAudioCtrlAck ack = transport_instance_->SuspendRequest(); - if (ack != BluetoothAudioCtrlAck::PENDING) { - auto aidl_retval = provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack)); + BluetoothAudioStatus ack = transport_instance_->SuspendRequest(); + if (ack != BluetoothAudioStatus::PENDING) { + auto aidl_retval = provider_->streamSuspended(BluetoothAudioStatusToHalStatus(ack)); if (!aidl_retval.isOk()) { log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); } diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc index 59d7f677610..786db3fbc20 100644 --- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc @@ -37,25 +37,6 @@ namespace audio { namespace aidl { namespace a2dp { -std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) { - switch (ack) { - case BluetoothAudioCtrlAck::SUCCESS_FINISHED: - return os << "SUCCESS_FINISHED"; - case BluetoothAudioCtrlAck::PENDING: - return os << "PENDING"; - case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED: - return os << "FAILURE_UNSUPPORTED"; - case BluetoothAudioCtrlAck::FAILURE_BUSY: - return os << "FAILURE_BUSY"; - case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING: - return os << "FAILURE_DISCONNECTING"; - case BluetoothAudioCtrlAck::FAILURE: - return os << "FAILURE"; - default: - return os << "UNDEFINED " << static_cast(ack); - } -} - BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* instance) : provider_(nullptr), provider_factory_(nullptr), @@ -431,17 +412,17 @@ int BluetoothAudioClientInterface::StartSession() { } } -void BluetoothAudioClientInterface::StreamStarted(const BluetoothAudioCtrlAck& ack) { +void BluetoothAudioClientInterface::StreamStarted(const BluetoothAudioStatus& ack) { if (provider_ == nullptr) { log::error("BluetoothAudioHal nullptr"); return; } - if (ack == BluetoothAudioCtrlAck::PENDING) { + if (ack == BluetoothAudioStatus::PENDING) { log::info("{} ignored", ack); return; } - auto status = BluetoothAudioCtrlAckToHalStatus(ack); + auto status = BluetoothAudioStatusToHalStatus(ack); auto aidl_retval = provider_->streamStarted(status); if (!aidl_retval.isOk()) { @@ -449,17 +430,17 @@ void BluetoothAudioClientInterface::StreamStarted(const BluetoothAudioCtrlAck& a } } -void BluetoothAudioClientInterface::StreamSuspended(const BluetoothAudioCtrlAck& ack) { +void BluetoothAudioClientInterface::StreamSuspended(const BluetoothAudioStatus& ack) { if (provider_ == nullptr) { log::error("BluetoothAudioHal nullptr"); return; } - if (ack == BluetoothAudioCtrlAck::PENDING) { + if (ack == BluetoothAudioStatus::PENDING) { log::info("{} ignored", ack); return; } - auto status = BluetoothAudioCtrlAckToHalStatus(ack); + auto status = BluetoothAudioStatusToHalStatus(ack); auto aidl_retval = provider_->streamSuspended(status); if (!aidl_retval.isOk()) { diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h index 89aa10f75a7..818037a7014 100644 --- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h @@ -24,12 +24,15 @@ #include #include "audio_aidl_interfaces.h" -#include "audio_ctrl_ack.h" #include "bluetooth_audio_port_impl.h" #include "bta/le_audio/broadcaster/broadcaster_types.h" #include "bta/le_audio/le_audio_types.h" #include "transport_instance.h" +// Keep after audio_aidl_interfaces.h because of +// conflicting definitions. +#include "a2dp_encoding.h" + namespace bluetooth { namespace audio { namespace aidl { @@ -62,6 +65,20 @@ using MqDataMode = SynchronizedReadWrite; using DataMQ = AidlMessageQueue; using DataMQDesc = MQDescriptor; +inline ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus +BluetoothAudioStatusToHalStatus(BluetoothAudioStatus ack) { + switch (ack) { + case BluetoothAudioStatus::SUCCESS: + return ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus::SUCCESS; + case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: + return ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION; + case BluetoothAudioStatus::PENDING: + case BluetoothAudioStatus::FAILURE: + default: + return ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus::FAILURE; + } +} + /*** * The client interface connects an IBluetoothTransportInstance to * IBluetoothAudioProvider and helps to route callbacks to @@ -89,9 +106,9 @@ public: std::vector const& remote_capabilities, A2dpConfigurationHint const& hint) const; - void StreamStarted(const BluetoothAudioCtrlAck& ack); + void StreamStarted(const BluetoothAudioStatus& ack); - void StreamSuspended(const BluetoothAudioCtrlAck& ack); + void StreamSuspended(const BluetoothAudioStatus& ack); int StartSession(); diff --git a/system/audio_hal_interface/aidl/a2dp/transport_instance.h b/system/audio_hal_interface/aidl/a2dp/transport_instance.h index 3d458969ecb..2bf574e8a13 100644 --- a/system/audio_hal_interface/aidl/a2dp/transport_instance.h +++ b/system/audio_hal_interface/aidl/a2dp/transport_instance.h @@ -18,8 +18,8 @@ #include +#include "a2dp_encoding.h" #include "audio_aidl_interfaces.h" -#include "audio_ctrl_ack.h" namespace bluetooth { namespace audio { @@ -29,6 +29,7 @@ namespace a2dp { using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; using ::aidl::android::hardware::bluetooth::audio::LatencyMode; using ::aidl::android::hardware::bluetooth::audio::SessionType; +using ::bluetooth::audio::a2dp::BluetoothAudioStatus; /*** * An IBluetoothTransportInstance needs to be implemented by a Bluetooth @@ -73,9 +74,9 @@ public: } } - virtual BluetoothAudioCtrlAck StartRequest(bool is_low_latency) = 0; + virtual BluetoothAudioStatus StartRequest(bool is_low_latency) = 0; - virtual BluetoothAudioCtrlAck SuspendRequest() = 0; + virtual BluetoothAudioStatus SuspendRequest() = 0; virtual void StopRequest() = 0; -- GitLab From 9018f822f7cb9d299ae29d91903a76430b74ce94 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 20 Sep 2024 22:20:27 +0000 Subject: [PATCH 122/875] audio_hal_interface: Remove unused definitions in duplicate client interfaces Test: m com.android.btservices Flag: EXEMPT, no logical change Bug: 365022887 Change-Id: I534177bccea0f4ca25c425e11efa8842fa1d3471 --- .../aidl/a2dp/a2dp_encoding_aidl.cc | 85 +++++-- .../aidl/a2dp/a2dp_transport.h | 86 ------- .../aidl/a2dp/audio_aidl_interfaces.h | 8 +- .../aidl/a2dp/bluetooth_audio_port_impl.cc | 107 +-------- .../aidl/a2dp/bluetooth_audio_port_impl.h | 7 - .../aidl/a2dp/client_interface_aidl.cc | 210 +----------------- .../aidl/a2dp/client_interface_aidl.h | 88 +------- .../aidl/a2dp/codec_status_aidl.cc | 4 +- .../aidl/a2dp/transport_instance.h | 52 +---- .../aidl/audio_aidl_interfaces.h | 15 +- .../aidl/client_interface_aidl.cc | 44 ---- .../aidl/client_interface_aidl.h | 13 -- 12 files changed, 94 insertions(+), 625 deletions(-) delete mode 100644 system/audio_hal_interface/aidl/a2dp/a2dp_transport.h diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc index 99f957d29dc..e71171113a7 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc @@ -23,11 +23,23 @@ #include #include "a2dp_provider_info.h" -#include "a2dp_transport.h" #include "audio_aidl_interfaces.h" +#include "client_interface_aidl.h" #include "codec_status_aidl.h" #include "transport_instance.h" +typedef enum { + A2DP_CTRL_CMD_NONE, + A2DP_CTRL_CMD_CHECK_READY, + A2DP_CTRL_CMD_START, + A2DP_CTRL_CMD_STOP, + A2DP_CTRL_CMD_SUSPEND, + A2DP_CTRL_GET_INPUT_AUDIO_CONFIG, + A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG, + A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG, + A2DP_CTRL_GET_PRESENTATION_POSITION, +} tA2DP_CTRL_CMD; + namespace fmt { template <> struct formatter : enum_formatter {}; @@ -42,6 +54,47 @@ namespace audio { namespace aidl { namespace a2dp { +namespace { + +using ::bluetooth::audio::a2dp::BluetoothAudioStatus; +using ::bluetooth::audio::aidl::a2dp::LatencyMode; + +// Provide call-in APIs for the Bluetooth Audio HAL +class A2dpTransport : public ::bluetooth::audio::aidl::a2dp::IBluetoothTransportInstance { +public: + A2dpTransport(SessionType sessionType); + + BluetoothAudioStatus StartRequest(bool is_low_latency) override; + + BluetoothAudioStatus SuspendRequest() override; + + void StopRequest() override; + + void SetLatencyMode(LatencyMode latency_mode) override; + + bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, + timespec* data_position) override; + + tA2DP_CTRL_CMD GetPendingCmd() const; + + void ResetPendingCmd(); + + void ResetPresentationPosition(); + + void LogBytesRead(size_t bytes_read) override; + + // delay reports from AVDTP is based on 1/10 ms (100us) + void SetRemoteDelay(uint16_t delay_report); + +private: + static tA2DP_CTRL_CMD a2dp_pending_cmd_; + static uint16_t remote_delay_report_; + uint64_t total_bytes_read_; + timespec data_position_; +}; + +} // namespace + using ::bluetooth::audio::a2dp::BluetoothAudioPort; using ::bluetooth::audio::a2dp::BluetoothAudioStatus; @@ -57,7 +110,7 @@ using ::aidl::android::hardware::bluetooth::audio::CodecConfiguration; using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration; using ::aidl::android::hardware::bluetooth::audio::SessionType; -using ::bluetooth::audio::aidl::a2dp::BluetoothAudioSinkClientInterface; +using ::bluetooth::audio::aidl::a2dp::BluetoothAudioClientInterface; using ::bluetooth::audio::aidl::a2dp::codec::A2dpAacToHalConfig; using ::bluetooth::audio::aidl::a2dp::codec::A2dpAptxToHalConfig; using ::bluetooth::audio::aidl::a2dp::codec::A2dpCodecToHalBitsPerSample; @@ -78,7 +131,7 @@ tA2DP_CTRL_CMD A2dpTransport::a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; uint16_t A2dpTransport::remote_delay_report_ = 0; A2dpTransport::A2dpTransport(SessionType sessionType) - : IBluetoothSinkTransportInstance(sessionType, (AudioConfiguration){}), + : IBluetoothTransportInstance(sessionType, (AudioConfiguration){}), total_bytes_read_(0), data_position_({}) { a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; @@ -151,20 +204,6 @@ bool A2dpTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns, return true; } -void A2dpTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) { - auto track_count = source_metadata.track_count; - auto tracks = source_metadata.tracks; - log::verbose("{} track(s) received", track_count); - while (track_count) { - log::verbose("usage={}, content_type={}, gain={}", tracks->base.usage, - tracks->base.content_type, tracks->base.gain); - --track_count; - ++tracks; - } -} - -void A2dpTransport::SinkMetadataChanged(const sink_metadata_v7_t&) {} - tA2DP_CTRL_CMD A2dpTransport::GetPendingCmd() const { return a2dp_pending_cmd_; } void A2dpTransport::ResetPendingCmd() { a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; } @@ -192,9 +231,9 @@ void A2dpTransport::LogBytesRead(size_t bytes_read) { void A2dpTransport::SetRemoteDelay(uint16_t delay_report) { remote_delay_report_ = delay_report; } // Common interface to call-out into Bluetooth Audio HAL -BluetoothAudioSinkClientInterface* software_hal_interface = nullptr; -BluetoothAudioSinkClientInterface* offloading_hal_interface = nullptr; -BluetoothAudioSinkClientInterface* active_hal_interface = nullptr; +BluetoothAudioClientInterface* software_hal_interface = nullptr; +BluetoothAudioClientInterface* offloading_hal_interface = nullptr; +BluetoothAudioClientInterface* active_hal_interface = nullptr; // ProviderInfo for A2DP hardware offload encoding and decoding data paths, // if supported by the HAL and enabled. nullptr if not supported @@ -305,9 +344,9 @@ bool is_hal_offloading() { // Opens the HAL client interface of the specified session type and check // that is is valid. Returns nullptr if the client interface did not open // properly. -static BluetoothAudioSinkClientInterface* new_hal_interface(SessionType session_type) { +static BluetoothAudioClientInterface* new_hal_interface(SessionType session_type) { auto a2dp_transport = new A2dpTransport(session_type); - auto hal_interface = new BluetoothAudioSinkClientInterface(a2dp_transport); + auto hal_interface = new BluetoothAudioClientInterface(a2dp_transport); if (hal_interface->IsValid()) { return hal_interface; } else { @@ -319,7 +358,7 @@ static BluetoothAudioSinkClientInterface* new_hal_interface(SessionType session_ } /// Delete the selected HAL client interface. -static void delete_hal_interface(BluetoothAudioSinkClientInterface* hal_interface) { +static void delete_hal_interface(BluetoothAudioClientInterface* hal_interface) { if (hal_interface == nullptr) { return; } diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h b/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h deleted file mode 100644 index 7dec755aacb..00000000000 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_transport.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 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. - */ - -#pragma once - -#include "a2dp_encoding.h" -#include "client_interface_aidl.h" - -typedef enum { - A2DP_CTRL_CMD_NONE, - A2DP_CTRL_CMD_CHECK_READY, - A2DP_CTRL_CMD_START, - A2DP_CTRL_CMD_STOP, - A2DP_CTRL_CMD_SUSPEND, - A2DP_CTRL_GET_INPUT_AUDIO_CONFIG, - A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG, - A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG, - A2DP_CTRL_GET_PRESENTATION_POSITION, -} tA2DP_CTRL_CMD; - -namespace bluetooth { -namespace audio { -namespace aidl { -namespace a2dp { - -namespace { - -using ::bluetooth::audio::a2dp::BluetoothAudioStatus; -using ::bluetooth::audio::aidl::a2dp::LatencyMode; - -// Provide call-in APIs for the Bluetooth Audio HAL -class A2dpTransport : public ::bluetooth::audio::aidl::a2dp::IBluetoothSinkTransportInstance { -public: - A2dpTransport(SessionType sessionType); - - BluetoothAudioStatus StartRequest(bool is_low_latency) override; - - BluetoothAudioStatus SuspendRequest() override; - - void StopRequest() override; - - void SetLatencyMode(LatencyMode latency_mode) override; - - bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, - timespec* data_position) override; - - void SourceMetadataChanged(const source_metadata_v7_t& source_metadata); - - void SinkMetadataChanged(const sink_metadata_v7_t&) override; - - tA2DP_CTRL_CMD GetPendingCmd() const; - - void ResetPendingCmd(); - - void ResetPresentationPosition(); - - void LogBytesRead(size_t bytes_read) override; - - // delay reports from AVDTP is based on 1/10 ms (100us) - void SetRemoteDelay(uint16_t delay_report); - -private: - static tA2DP_CTRL_CMD a2dp_pending_cmd_; - static uint16_t remote_delay_report_; - uint64_t total_bytes_read_; - timespec data_position_; -}; -} // namespace - -} // namespace a2dp -} // namespace aidl -} // namespace audio -} // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h b/system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h index e8fb9ba5e8b..af0daa12ac8 100644 --- a/system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h +++ b/system/audio_hal_interface/aidl/a2dp/audio_aidl_interfaces.h @@ -45,16 +45,10 @@ #include #include #include -#include -#include #include #include #include #include -#include -#include -#include -#include #include #include #include @@ -75,4 +69,4 @@ #undef LOG_DEBUG #endif -// clang-format on \ No newline at end of file +// clang-format on diff --git a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc index 7a715c91f22..6172b33a708 100644 --- a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc +++ b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.cc @@ -21,9 +21,9 @@ #include -#include "client_interface_aidl.h" #include "android/binder_ibinder_platform.h" #include "btif/include/btif_common.h" +#include "client_interface_aidl.h" #include "common/stop_watch_legacy.h" namespace bluetooth { @@ -96,111 +96,12 @@ ndk::ScopedAStatus BluetoothAudioPortImpl::getPresentationPosition( } ndk::ScopedAStatus BluetoothAudioPortImpl::updateSourceMetadata( - const SourceMetadata& source_metadata) { - StopWatchLegacy stop_watch(__func__); - log::info("{} track(s)", source_metadata.tracks.size()); - - std::vector tracks_vec; - tracks_vec.reserve(source_metadata.tracks.size()); - for (const auto& track : source_metadata.tracks) { - auto num_of_tags = track.tags.size(); - log::info("metadata tags size: {}", num_of_tags); - - playback_track_metadata_v7 desc_track = { - .base = {.usage = static_cast(track.usage), - .content_type = static_cast(track.contentType), - .gain = track.gain}, - }; - - if (num_of_tags != 0) { - int copied_size = 0; - int max_tags_size = sizeof(desc_track.tags); - std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); - for (size_t i = 0; i < num_of_tags - 1; i++) { - int string_len = track.tags[i].length(); - - if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { - log::error("Too many tags, copied size: {}", copied_size); - break; - } - - track.tags[i].copy(desc_track.tags + copied_size, string_len, 0); - copied_size += string_len; - separator.copy(desc_track.tags + copied_size, 1, 0); - copied_size += 1; - } - - int string_len = track.tags[num_of_tags - 1].length(); - if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { - log::error("Too many tags, copied size: {}", copied_size); - } else { - track.tags[num_of_tags - 1].copy(desc_track.tags + copied_size, string_len, 0); - } - } else { - memset(desc_track.tags, 0, sizeof(desc_track.tags)); - } - - tracks_vec.push_back(desc_track); - } - - const source_metadata_v7_t legacy_source_metadata = {.track_count = tracks_vec.size(), - .tracks = tracks_vec.data()}; - transport_instance_->SourceMetadataChanged(legacy_source_metadata); + const SourceMetadata& /*source_metadata*/) { return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus BluetoothAudioPortImpl::updateSinkMetadata(const SinkMetadata& sink_metadata) { - StopWatchLegacy stop_watch(__func__); - log::info("{} track(s)", sink_metadata.tracks.size()); - - std::vector tracks_vec; - tracks_vec.reserve(sink_metadata.tracks.size()); - for (const auto& track : sink_metadata.tracks) { - auto num_of_tags = track.tags.size(); - log::info("metadata tags size: {}", num_of_tags); - - record_track_metadata_v7 desc_track = { - .base = - { - .source = static_cast(track.source), - .gain = track.gain, - }, - }; - - if (num_of_tags != 0) { - int copied_size = 0; - int max_tags_size = sizeof(desc_track.tags); - std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); - for (size_t i = 0; i < num_of_tags - 1; i++) { - int string_len = track.tags[i].length(); - - if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { - log::error("Too many tags, copied size: {}", copied_size); - break; - } - - track.tags[i].copy(desc_track.tags + copied_size, string_len, 0); - copied_size += string_len; - separator.copy(desc_track.tags + copied_size, 1, 0); - copied_size += 1; - } - - int string_len = track.tags[num_of_tags - 1].length(); - if ((copied_size >= max_tags_size) || (copied_size + string_len >= max_tags_size)) { - log::error("Too many tags, copied size: {}", copied_size); - } else { - track.tags[num_of_tags - 1].copy(desc_track.tags + copied_size, string_len, 0); - } - } else { - memset(desc_track.tags, 0, sizeof(desc_track.tags)); - } - - tracks_vec.push_back(desc_track); - } - - const sink_metadata_v7_t legacy_sink_metadata = {.track_count = tracks_vec.size(), - .tracks = tracks_vec.data()}; - transport_instance_->SinkMetadataChanged(legacy_sink_metadata); +ndk::ScopedAStatus BluetoothAudioPortImpl::updateSinkMetadata( + const SinkMetadata& /*sink_metadata*/) { return ndk::ScopedAStatus::ok(); } diff --git a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h index de4432b4eec..154702b6ec0 100644 --- a/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h +++ b/system/audio_hal_interface/aidl/a2dp/bluetooth_audio_port_impl.h @@ -38,17 +38,11 @@ public: const std::shared_ptr& provider); ndk::ScopedAStatus startStream(bool is_low_latency) override; - ndk::ScopedAStatus suspendStream() override; - ndk::ScopedAStatus stopStream() override; - ndk::ScopedAStatus getPresentationPosition(PresentationPosition* _aidl_return) override; - ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata& source_metadata) override; - ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata& sink_metadata) override; - ndk::ScopedAStatus setLatencyMode(LatencyMode latency_mode) override; protected: @@ -60,7 +54,6 @@ protected: private: ndk::ScopedAStatus switchCodec(bool isLowLatency); - ndk::SpAIBinder createBinder() override; }; diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc index 786db3fbc20..fdfdceccc19 100644 --- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc @@ -46,6 +46,13 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransport latency_modes_({LatencyMode::FREE}) { death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(binderDiedCallbackAidl)); + FetchAudioProvider(); +} + +BluetoothAudioClientInterface::~BluetoothAudioClientInterface() { + if (provider_factory_ != nullptr) { + AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); + } } bool BluetoothAudioClientInterface::IsValid() const { return provider_ != nullptr; } @@ -211,30 +218,6 @@ void BluetoothAudioClientInterface::FetchAudioProvider() { fmt::ptr(provider_.get()), (provider_->isRemote() ? " (remote)" : " (local)")); } -BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface( - IBluetoothSinkTransportInstance* sink) - : BluetoothAudioClientInterface{sink}, sink_(sink) { - FetchAudioProvider(); -} - -BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() { - if (provider_factory_ != nullptr) { - AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); - } -} - -BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface( - IBluetoothSourceTransportInstance* source) - : BluetoothAudioClientInterface{source}, source_(source) { - FetchAudioProvider(); -} - -BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() { - if (provider_factory_ != nullptr) { - AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); - } -} - void BluetoothAudioClientInterface::binderDiedCallbackAidl(void* ptr) { log::warn("restarting connection with new Audio Hal"); auto client = static_cast(ptr); @@ -471,33 +454,7 @@ int BluetoothAudioClientInterface::EndSession() { return 0; } -void BluetoothAudioClientInterface::FlushAudioData() { - if (transport_->GetSessionType() == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || - transport_->GetSessionType() == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || - transport_->GetSessionType() == - SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || - (bta_ag_is_sco_managed_by_audio() && - transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) { - return; - } - - if (data_mq_ == nullptr || !data_mq_->isValid()) { - log::warn("data_mq_ invalid"); - return; - } - size_t size = data_mq_->availableToRead(); - if (size == 0) { - return; - } - - std::vector buffer(size); - - if (data_mq_->read(buffer.data(), size) != size) { - log::warn("failed to flush data queue!"); - } -} - -size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, uint32_t len) { +size_t BluetoothAudioClientInterface::ReadAudioData(uint8_t* p_buf, uint32_t len) { if (!IsValid()) { log::error("BluetoothAudioHal is not valid"); return 0; @@ -544,7 +501,7 @@ size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, uint32_t log::verbose("{} -> {} read", len, total_read); } - sink_->LogBytesRead(total_read); + transport_->LogBytesRead(total_read); return total_read; } @@ -561,155 +518,6 @@ void BluetoothAudioClientInterface::RenewAudioProviderAndSession() { } } -size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, uint32_t len) { - if (!IsValid()) { - log::error("BluetoothAudioHal is not valid"); - return 0; - } - if (p_buf == nullptr || len == 0) { - return 0; - } - - std::lock_guard guard(internal_mutex_); - - size_t total_written = 0; - int timeout_ms = kDefaultDataWriteTimeoutMs; - do { - if (data_mq_ == nullptr || !data_mq_->isValid()) { - break; - } - - size_t avail_to_write = data_mq_->availableToWrite(); - if (avail_to_write) { - if (avail_to_write > len - total_written) { - avail_to_write = len - total_written; - } - if (data_mq_->write((const MqDataType*)p_buf + total_written, avail_to_write) == 0) { - log::warn("len={} total_written={} failed", len, total_written); - break; - } - total_written += avail_to_write; - } else if (timeout_ms >= kDefaultDataWritePollIntervalMs) { - std::this_thread::sleep_for(std::chrono::milliseconds(kDefaultDataWritePollIntervalMs)); - timeout_ms -= kDefaultDataWritePollIntervalMs; - continue; - } else { - log::warn("{}/{} no data {} ms", len - total_written, len, - kDefaultDataWriteTimeoutMs - timeout_ms); - break; - } - } while (total_written < len); - - if (timeout_ms < (kDefaultDataWriteTimeoutMs - kDefaultDataWritePollIntervalMs) && - timeout_ms >= kDefaultDataWritePollIntervalMs) { - log::verbose("underflow {} -> {} read {} ms", len, total_written, - kDefaultDataWriteTimeoutMs - timeout_ms); - } else { - log::verbose("{} -> {} written", len, total_written); - } - - source_->LogBytesWritten(total_written); - return total_written; -} - -void BluetoothAudioClientInterface::SetCodecPriority(CodecId codec_id, int32_t priority) { - log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); - auto aidl_retval = provider_->setCodecPriority(codec_id, priority); - if (!aidl_retval.isOk()) { - log::error("BluetoothAudioHal::setCodecPriority failure: {}", aidl_retval.getDescription()); - } -} - -std::vector -BluetoothAudioClientInterface::GetLeAudioAseConfiguration( - std::optional< - std::vector>>& - remoteSinkAudioCapabilities, - std::optional< - std::vector>>& - remoteSourceAudioCapabilities, - std::vector& requirements) { - log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); - - std::vector configurations; - auto aidl_retval = provider_->getLeAudioAseConfiguration(remoteSinkAudioCapabilities, - remoteSourceAudioCapabilities, - requirements, &configurations); - - if (!aidl_retval.isOk()) { - log::error("BluetoothAudioHal::getLeAudioAseConfiguration failure: {}", - aidl_retval.getDescription()); - } else { - log::info( - "BluetoothAudioHal::getLeAudioAseConfiguration returned {} " - "configurations.", - configurations.size()); - } - - return configurations; -} - -IBluetoothAudioProvider::LeAudioAseQosConfigurationPair -BluetoothAudioClientInterface::getLeAudioAseQosConfiguration( - IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement& qosRequirement) { - log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); - - IBluetoothAudioProvider::LeAudioAseQosConfigurationPair qos_configuration; - auto aidl_retval = provider_->getLeAudioAseQosConfiguration(qosRequirement, &qos_configuration); - - if (!aidl_retval.isOk()) { - log::error("BluetoothAudioHal::getLeAudioAseQosConfiguration failure: {}", - aidl_retval.getDescription()); - } - return qos_configuration; -} - -void BluetoothAudioClientInterface::onSinkAseMetadataChanged( - IBluetoothAudioProvider::AseState state, int32_t cigId, int32_t cisId, - std::optional>>& metadata) { - log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); - - auto aidl_retval = provider_->onSinkAseMetadataChanged(state, cigId, cisId, metadata); - - if (!aidl_retval.isOk()) { - log::error("BluetoothAudioHal::onSinkAseMetadataChanged failure: {}", - aidl_retval.getDescription()); - } -} - -void BluetoothAudioClientInterface::onSourceAseMetadataChanged( - IBluetoothAudioProvider::AseState state, int32_t cigId, int32_t cisId, - std::optional>>& metadata) { - log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); - - auto aidl_retval = provider_->onSourceAseMetadataChanged(state, cigId, cisId, metadata); - - if (!aidl_retval.isOk()) { - log::error("BluetoothAudioHal::onSourceAseMetadataChanged failure: {}", - aidl_retval.getDescription()); - } -} - -IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting -BluetoothAudioClientInterface::getLeAudioBroadcastConfiguration( - const std::optional< - std::vector>>& - remoteSinkAudioCapabilities, - const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& requirement) { - log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); - - IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting setting; - auto aidl_retval = provider_->getLeAudioBroadcastConfiguration(remoteSinkAudioCapabilities, - requirement, &setting); - - if (!aidl_retval.isOk()) { - log::error("BluetoothAudioHal::getLeAudioBroadcastConfiguration failure: {}", - aidl_retval.getDescription()); - } - - return setting; -} - } // namespace a2dp } // namespace aidl } // namespace audio diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h index 818037a7014..fd8f1606e26 100644 --- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h @@ -71,7 +71,8 @@ BluetoothAudioStatusToHalStatus(BluetoothAudioStatus ack) { case BluetoothAudioStatus::SUCCESS: return ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus::SUCCESS; case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: - return ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION; + return ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus:: + UNSUPPORTED_CODEC_CONFIGURATION; case BluetoothAudioStatus::PENDING: case BluetoothAudioStatus::FAILURE: default: @@ -87,9 +88,10 @@ BluetoothAudioStatusToHalStatus(BluetoothAudioStatus ack) { class BluetoothAudioClientInterface { public: BluetoothAudioClientInterface(IBluetoothTransportInstance* instance); - virtual ~BluetoothAudioClientInterface() = default; + virtual ~BluetoothAudioClientInterface(); bool IsValid() const; + IBluetoothTransportInstance* GetTransportInstance() const { return transport_; } std::vector GetAudioCapabilities() const; @@ -123,35 +125,10 @@ public: bool SetAllowedLatencyModes(std::vector latency_modes); - void FlushAudioData(); - - void SetCodecPriority(CodecId codec_id, int32_t priority); - - std::vector GetLeAudioAseConfiguration( - std::optional< - std::vector>>& - remoteSinkAudioCapabilities, - std::optional< - std::vector>>& - remoteSourceAudioCapabilities, - std::vector& requirements); - - IBluetoothAudioProvider::LeAudioAseQosConfigurationPair getLeAudioAseQosConfiguration( - IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement& qosRequirement); - - void onSinkAseMetadataChanged(IBluetoothAudioProvider::AseState state, int32_t cigId, - int32_t cisId, - std::optional>>& metadata); - - void onSourceAseMetadataChanged(IBluetoothAudioProvider::AseState state, int32_t cigId, - int32_t cisId, - std::optional>>& metadata); - - IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting getLeAudioBroadcastConfiguration( - const std::optional< - std::vector>>& - remoteSinkAudioCapabilities, - const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& requirement); + /*** + * Read data from audio HAL through fmq + ***/ + size_t ReadAudioData(uint8_t* p_buf, uint32_t len); static constexpr PcmConfiguration kInvalidPcmConfiguration = {}; @@ -170,7 +147,6 @@ protected: static void binderDiedCallbackAidl(void* cookie_ptr); std::shared_ptr provider_; - std::shared_ptr provider_factory_; bool session_started_; @@ -186,59 +162,11 @@ private: IBluetoothTransportInstance* transport_; std::vector capabilities_; std::vector latency_modes_; -}; - -/*** - * The client interface connects an IBluetoothTransportInstance to - * IBluetoothAudioProvider and helps to route callbacks to - * IBluetoothTransportInstance - ***/ -class BluetoothAudioSinkClientInterface : public BluetoothAudioClientInterface { -public: - /*** - * Constructs an BluetoothAudioSinkClientInterface to communicate to - * BluetoothAudio HAL. |sink| is the implementation for the transport. - ***/ - BluetoothAudioSinkClientInterface(IBluetoothSinkTransportInstance* sink); - virtual ~BluetoothAudioSinkClientInterface(); - - IBluetoothSinkTransportInstance* GetTransportInstance() const { return sink_; } - - /*** - * Read data from audio HAL through fmq - ***/ - size_t ReadAudioData(uint8_t* p_buf, uint32_t len); - -private: - IBluetoothSinkTransportInstance* sink_; static constexpr int kDefaultDataReadTimeoutMs = 10; static constexpr int kDefaultDataReadPollIntervalMs = 1; }; -class BluetoothAudioSourceClientInterface : public BluetoothAudioClientInterface { -public: - /*** - * Constructs an BluetoothAudioSourceClientInterface to communicate to - * BluetoothAudio HAL. |source| is the implementation for the transport. - ***/ - BluetoothAudioSourceClientInterface(IBluetoothSourceTransportInstance* source); - virtual ~BluetoothAudioSourceClientInterface(); - - IBluetoothSourceTransportInstance* GetTransportInstance() const { return source_; } - - /*** - * Write data to audio HAL through fmq - ***/ - size_t WriteAudioData(const uint8_t* p_buf, uint32_t len); - -private: - IBluetoothSourceTransportInstance* source_; - - static constexpr int kDefaultDataWriteTimeoutMs = 10; - static constexpr int kDefaultDataWritePollIntervalMs = 1; -}; - } // namespace a2dp } // namespace aidl } // namespace audio diff --git a/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.cc b/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.cc index d9c85c5a577..cb4a601f0ac 100644 --- a/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/codec_status_aidl.cc @@ -59,7 +59,7 @@ using ::aidl::android::hardware::bluetooth::audio::SbcConfiguration; namespace { -// capabilities from BluetoothAudioSinkClientInterface::GetAudioCapabilities() +// capabilities from BluetoothAudioClientInterface::GetAudioCapabilities() std::vector audio_hal_capabilities(0); // capabilities that audio HAL supports and frameworks / Bluetooth SoC / runtime // preference would like to use. @@ -475,7 +475,7 @@ bool A2dpOpusToHalConfig(CodecConfiguration* codec_config, A2dpCodecConfig* a2dp bool UpdateOffloadingCapabilities( const std::vector& framework_preference) { - audio_hal_capabilities = BluetoothAudioSinkClientInterface::GetAudioCapabilities( + audio_hal_capabilities = BluetoothAudioClientInterface::GetAudioCapabilities( SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); std::unordered_set codec_type_set; for (auto preference : framework_preference) { diff --git a/system/audio_hal_interface/aidl/a2dp/transport_instance.h b/system/audio_hal_interface/aidl/a2dp/transport_instance.h index 2bf574e8a13..274f23636c3 100644 --- a/system/audio_hal_interface/aidl/a2dp/transport_instance.h +++ b/system/audio_hal_interface/aidl/a2dp/transport_instance.h @@ -43,7 +43,6 @@ public: virtual ~IBluetoothTransportInstance() = default; SessionType GetSessionType() const { return session_type_; } - AudioConfiguration GetAudioConfiguration() const { return audio_config_; } void UpdateAudioConfiguration(const AudioConfiguration& audio_config) { @@ -56,75 +55,38 @@ public: audio_config_.set( audio_config.get()); break; - case AudioConfiguration::hfpConfig: - audio_config_.set( - audio_config.get()); + case AudioConfiguration::a2dp: + audio_config_.set(audio_config.get()); break; case AudioConfiguration::leAudioConfig: - audio_config_.set( - audio_config.get()); - break; case AudioConfiguration::leAudioBroadcastConfig: - audio_config_.set( - audio_config.get()); - break; - case AudioConfiguration::a2dp: - audio_config_.set(audio_config.get()); + case AudioConfiguration::hfpConfig: + // Unused by the A2DP client interface. break; } } virtual BluetoothAudioStatus StartRequest(bool is_low_latency) = 0; - virtual BluetoothAudioStatus SuspendRequest() = 0; - virtual void StopRequest() = 0; virtual void SetLatencyMode(LatencyMode latency_mode) = 0; - virtual bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed, timespec* data_position) = 0; - virtual void SourceMetadataChanged(const source_metadata_v7_t& source_metadata) = 0; - virtual void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) = 0; - /*** * Invoked when the transport is requested to reset presentation position ***/ virtual void ResetPresentationPosition() = 0; -private: - const SessionType session_type_; - AudioConfiguration audio_config_; -}; - -/*** - * An IBluetoothSinkTransportInstance needs to be implemented by a Bluetooth - * audio transport, such as A2DP, Hearing Aid or LeAudio, to handle callbacks - * from Audio HAL. - ***/ -class IBluetoothSinkTransportInstance : public IBluetoothTransportInstance { -public: - IBluetoothSinkTransportInstance(SessionType sessionType, AudioConfiguration audioConfig) - : IBluetoothTransportInstance{sessionType, audioConfig} {} - virtual ~IBluetoothSinkTransportInstance() = default; - /*** * Invoked when the transport is requested to log bytes read ***/ virtual void LogBytesRead(size_t bytes_readed) = 0; -}; -class IBluetoothSourceTransportInstance : public IBluetoothTransportInstance { -public: - IBluetoothSourceTransportInstance(SessionType sessionType, AudioConfiguration audioConfig) - : IBluetoothTransportInstance{sessionType, audioConfig} {} - virtual ~IBluetoothSourceTransportInstance() = default; - - /*** - * Invoked when the transport is requested to log bytes written - ***/ - virtual void LogBytesWritten(size_t bytes_written) = 0; +private: + const SessionType session_type_; + AudioConfiguration audio_config_; }; } // namespace a2dp diff --git a/system/audio_hal_interface/aidl/audio_aidl_interfaces.h b/system/audio_hal_interface/aidl/audio_aidl_interfaces.h index e8fb9ba5e8b..fbc302ade2e 100644 --- a/system/audio_hal_interface/aidl/audio_aidl_interfaces.h +++ b/system/audio_hal_interface/aidl/audio_aidl_interfaces.h @@ -28,11 +28,6 @@ #include #include -#include -#include -#include -#include -#include #include #include #include @@ -47,10 +42,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -58,10 +49,6 @@ #include #include #include -#include -#include -#include -#include #include @@ -75,4 +62,4 @@ #undef LOG_DEBUG #endif -// clang-format on \ No newline at end of file +// clang-format on diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.cc b/system/audio_hal_interface/aidl/client_interface_aidl.cc index 15a20be5b95..fc6555223f0 100644 --- a/system/audio_hal_interface/aidl/client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/client_interface_aidl.cc @@ -127,50 +127,6 @@ BluetoothAudioClientInterface::GetProviderInfo( return provider_info; } -std::optional BluetoothAudioClientInterface::GetA2dpConfiguration( - std::vector const& remote_capabilities, - A2dpConfigurationHint const& hint) const { - if (!is_aidl_available()) { - return std::nullopt; - } - - if (provider_ == nullptr) { - log::error("can't get a2dp configuration from unknown provider"); - return std::nullopt; - } - - std::optional configuration = std::nullopt; - auto aidl_retval = provider_->getA2dpConfiguration(remote_capabilities, hint, &configuration); - - if (!aidl_retval.isOk()) { - log::error("getA2dpConfiguration failure: {}", aidl_retval.getDescription()); - return std::nullopt; - } - - return configuration; -} - -std::optional BluetoothAudioClientInterface::ParseA2dpConfiguration( - const CodecId& codec_id, const std::vector& configuration, - CodecParameters* codec_parameters) const { - A2dpStatus a2dp_status; - - if (provider_ == nullptr) { - log::error("can not parse A2DP configuration because of unknown provider"); - return std::nullopt; - } - - auto aidl_retval = provider_->parseA2dpConfiguration(codec_id, configuration, codec_parameters, - &a2dp_status); - - if (!aidl_retval.isOk()) { - log::error("parseA2dpConfiguration failure: {}", aidl_retval.getDescription()); - return std::nullopt; - } - - return std::make_optional(a2dp_status); -} - void BluetoothAudioClientInterface::FetchAudioProvider() { if (!is_aidl_available()) { log::error("aidl is not supported on this platform."); diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.h b/system/audio_hal_interface/aidl/client_interface_aidl.h index b5bb309ab22..a3c60384ab5 100644 --- a/system/audio_hal_interface/aidl/client_interface_aidl.h +++ b/system/audio_hal_interface/aidl/client_interface_aidl.h @@ -34,10 +34,6 @@ namespace bluetooth { namespace audio { namespace aidl { -using ::aidl::android::hardware::bluetooth::audio::A2dpConfiguration; -using ::aidl::android::hardware::bluetooth::audio::A2dpConfigurationHint; -using ::aidl::android::hardware::bluetooth::audio::A2dpRemoteCapabilities; -using ::aidl::android::hardware::bluetooth::audio::A2dpStatus; using ::aidl::android::hardware::bluetooth::audio::AudioCapabilities; using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; using ::aidl::android::hardware::bluetooth::audio::CodecId; @@ -80,16 +76,7 @@ public: SessionType session_type, std::shared_ptr provider_factory = nullptr); - std::optional ParseA2dpConfiguration(const CodecId& codec_id, - const std::vector& configuration, - CodecParameters* codec_parameters) const; - - std::optional GetA2dpConfiguration( - std::vector const& remote_capabilities, - A2dpConfigurationHint const& hint) const; - void StreamStarted(const BluetoothAudioCtrlAck& ack); - void StreamSuspended(const BluetoothAudioCtrlAck& ack); int StartSession(); -- GitLab From 4ebc6a043cbff7ac2aa30db82866a1bacf50e785 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Mon, 23 Sep 2024 22:07:49 +0000 Subject: [PATCH 123/875] Test case to reconnect after restart Pair over BR/EDR. Restart BT. Ensure that the devices are still bonded. Test: atest BumbleBluetoothTests:PairingTests Bug: 297156490 Flag: TEST_ONLY Change-Id: I5f1de1ab38e324b80c7c1e478c2cfc0d76853755 --- .../bluetooth/pairing/PairingTest.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java index 7fc8d58ae05..7d5e3108a49 100644 --- a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java +++ b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java @@ -493,6 +493,96 @@ public class PairingTest { BluetoothDevice.ACTION_PAIRING_REQUEST); } + /** + * Test if bonded BR/EDR device can reconnect after BT restart + * + *

    Prerequisites: + * + *

      + *
    1. Bumble and Android are not bonded + *
    + * + *

    Steps: + * + *

      + *
    1. Bumble is discoverable and connectable over BR/EDR + *
    2. Android pairs with Bumble over BR/EDR + *
    3. Android restarts + *
    4. Bumble is connectable over BR/EDR + *
    5. Android reconnects to Bumble successfully and re-encrypts the link + *
    + * + *

    Expectation: Pairing succeeds + */ + @Test + public void testBondBredr_Reconnect() { + registerIntentActions(BluetoothDevice.ACTION_ACL_CONNECTED); + + testStep_BondBredr(); + assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice); + + testStep_restartBt(); + + assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice); + + assertThat(mBumbleDevice.connect()).isEqualTo(BluetoothStatusCodes.SUCCESS); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_CONNECTED), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + verifyNoMoreInteractions(mReceiver); + unregisterIntentActions(BluetoothDevice.ACTION_ACL_CONNECTED); + } + + private void testStep_BondBredr() { + registerIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_PAIRING_REQUEST); + + StreamObserver pairingEventAnswerObserver = + mBumble.security() + .withDeadlineAfter(BOND_INTENT_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS) + .onPairing(mPairingEventStreamObserver); + + assertThat(mBumbleDevice.createBond(BluetoothDevice.TRANSPORT_BREDR)).isTrue(); + + verifyIntentReceivedUnordered( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_CONNECTED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR)); + verifyIntentReceivedUnordered( + hasAction(BluetoothDevice.ACTION_PAIRING_REQUEST), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra( + BluetoothDevice.EXTRA_PAIRING_VARIANT, + BluetoothDevice.PAIRING_VARIANT_CONSENT)); + + // Approve pairing from Android + assertThat(mBumbleDevice.setPairingConfirmation(true)).isTrue(); + + PairingEvent pairingEvent = mPairingEventStreamObserver.iterator().next(); + assertThat(pairingEvent.hasJustWorks()).isTrue(); + pairingEventAnswerObserver.onNext( + PairingEventAnswer.newBuilder().setEvent(pairingEvent).setConfirm(true).build()); + + // Ensure that pairing succeeds + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + + verifyNoMoreInteractions(mReceiver); + unregisterIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_PAIRING_REQUEST); + } + private void testStep_restartBt() { assertThat(BlockingBluetoothAdapter.disable(true)).isTrue(); assertThat(BlockingBluetoothAdapter.enable()).isTrue(); -- GitLab From 018da51fc3016669ff03ff78374488dd0eba5161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 27 Mar 2024 09:00:06 +0000 Subject: [PATCH 124/875] BluetoothLeAudio: Deprecated location invalid As per new Bluetooth Assigned Number, there is no more invalid location. Bug: 330847930 Bug: 331139722 Test: mmm packages/modules/Bluetooth Flag: com::android::bluetooth:flags::leaudio_mono_location_errata Change-Id: Id5904e8c96be6095e8b528f05f294c60e2217ccd --- framework/api/system-current.txt | 2 +- framework/java/android/bluetooth/BluetoothLeAudio.java | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 5d5b4dd4553..907009de036 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -479,7 +479,7 @@ package android.bluetooth { field public static final int AUDIO_LOCATION_FRONT_RIGHT = 2; // 0x2 field public static final int AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER = 128; // 0x80 field public static final int AUDIO_LOCATION_FRONT_RIGHT_WIDE = 33554432; // 0x2000000 - field public static final int AUDIO_LOCATION_INVALID = 0; // 0x0 + field @Deprecated @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata") public static final int AUDIO_LOCATION_INVALID = 0; // 0x0 field public static final int AUDIO_LOCATION_LEFT_SURROUND = 67108864; // 0x4000000 field public static final int AUDIO_LOCATION_LOW_FREQ_EFFECTS_ONE = 8; // 0x8 field public static final int AUDIO_LOCATION_LOW_FREQ_EFFECTS_TWO = 512; // 0x200 diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index b9f9952578a..c11efe16835 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -363,9 +363,14 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { /** * This represents an invalid audio location. * + * @deprecated As per Bluetooth Assigned Numbers, previously location invalid is now replaced + * with a meaning MONO. * @hide */ - @SystemApi public static final int AUDIO_LOCATION_INVALID = 0; + @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA) + @Deprecated + @SystemApi + public static final int AUDIO_LOCATION_INVALID = 0; /** * This represents an Mono audio location. -- GitLab From 603732828a765b4dcb29743d9f02f314330cda0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 1 Oct 2024 05:32:19 +0000 Subject: [PATCH 125/875] Flag: hap_connect_only_requested_device Bug: 370405555 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: Ifd788443905ac054b05bea3117ea5d65c829c507 --- flags/hap.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/hap.aconfig b/flags/hap.aconfig index 0e83e9015f5..860774b7881 100644 --- a/flags/hap.aconfig +++ b/flags/hap.aconfig @@ -15,3 +15,13 @@ flag { description: "Allow user to control the preset of hearing aid devices" bug: "306236481" } + +flag { + name: "hap_connect_only_requested_device" + namespace: "bluetooth" + description: "On profile connection, connect only requested device, not whole group it belongs to" + bug: "370405555" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 0e32c5644ccaf0dc3b91841aad351d8825a16ca6 Mon Sep 17 00:00:00 2001 From: Ying Hsu Date: Mon, 23 Sep 2024 14:43:11 +0000 Subject: [PATCH 126/875] Add test for AdapterSuspend Bug: 327644045 Test: m -j Test: atest AdapterSuspendTest Flag: Exempt, test only Change-Id: I5336ca97f8145c21e9e4ae2f1c5b18c99cd9397d --- .../bluetooth/btservice/AdapterSuspend.java | 13 ++- .../btservice/AdapterSuspendTest.java | 106 ++++++++++++++++++ 2 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterSuspendTest.java diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java b/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java index ab5187b14b1..751bb3d6dc2 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java @@ -27,6 +27,8 @@ import android.os.Looper; import android.util.Log; import android.view.Display; +import com.android.internal.annotations.VisibleForTesting; + import java.util.Arrays; public class AdapterSuspend { @@ -75,12 +77,18 @@ public class AdapterSuspend { mDisplayManager.unregisterDisplayListener(mDisplayListener); } + @VisibleForTesting + boolean isSuspended() { + return mSuspended; + } + private boolean isScreenOn() { return Arrays.stream(mDisplayManager.getDisplays()) .anyMatch(display -> display.getState() == Display.STATE_ON); } - private void handleSuspend() { + @VisibleForTesting + void handleSuspend() { if (mSuspended) { return; } @@ -102,7 +110,8 @@ public class AdapterSuspend { Log.i(TAG, "ready to suspend"); } - private void handleResume() { + @VisibleForTesting + void handleResume() { if (!mSuspended) { return; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterSuspendTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterSuspendTest.java new file mode 100644 index 00000000000..65bf7560deb --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterSuspendTest.java @@ -0,0 +1,106 @@ +/* + * 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. + */ +package com.android.bluetooth.btservice; + +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE; +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.os.test.TestLooper; + +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 org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AdapterSuspendTest { + private TestLooper mTestLooper; + private DisplayManager mDisplayManager; + private AdapterSuspend mAdapterSuspend; + + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterNativeInterface mAdapterNativeInterface; + + @Before + public void setUp() throws Exception { + Context context = InstrumentationRegistry.getTargetContext(); + mTestLooper = new TestLooper(); + mDisplayManager = context.getSystemService(DisplayManager.class); + + mAdapterSuspend = + new AdapterSuspend( + mAdapterNativeInterface, mTestLooper.getLooper(), mDisplayManager); + } + + private void triggerSuspend() throws Exception { + mAdapterSuspend.handleSuspend(); + } + + private void triggerResume() throws Exception { + mAdapterSuspend.handleResume(); + } + + private boolean isSuspended() throws Exception { + return mAdapterSuspend.isSuspended(); + } + + @Test + public void testSuspend() throws Exception { + assertThat(isSuspended()).isFalse(); + + triggerSuspend(); + + verify(mAdapterNativeInterface).setDefaultEventMaskExcept(anyLong(), anyLong()); + verify(mAdapterNativeInterface) + .setScanMode(AdapterService.convertScanModeToHal(SCAN_MODE_NONE)); + verify(mAdapterNativeInterface).clearEventFilter(); + verify(mAdapterNativeInterface).clearFilterAcceptList(); + verify(mAdapterNativeInterface).disconnectAllAcls(); + assertThat(isSuspended()).isTrue(); + } + + @Test + public void testResume() throws Exception { + triggerSuspend(); + assertThat(isSuspended()).isTrue(); + + clearInvocations(mAdapterNativeInterface); + triggerResume(); + + verify(mAdapterNativeInterface).setDefaultEventMaskExcept(0, 0); + verify(mAdapterNativeInterface).clearEventFilter(); + verify(mAdapterNativeInterface).restoreFilterAcceptList(); + verify(mAdapterNativeInterface) + .setScanMode(AdapterService.convertScanModeToHal(SCAN_MODE_CONNECTABLE)); + assertThat(isSuspended()).isFalse(); + } +} -- GitLab From f908728261a3b05d7699fbf83e4d8b416ffc8b57 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 19 Sep 2024 14:27:33 -0700 Subject: [PATCH 127/875] move profiles connection away from main thread By using the main handler to perform binder task, we may load the app main thread un-necessarily. Instead use a lock to prevent race condition and block whatever is the thread that call into getProfileProxy (delegating the responsibilities of a slow call to the caller thread management) Test: atest pts-bot (any test that requires the profiles) Flag: Exempt refactor Bug: 367914132 Bug: 370815283 Change-Id: Ib7ad3119375b95938751eeec20081f2455ec01b5 --- .../android/bluetooth/BluetoothAdapter.java | 108 +++++++++++------- 1 file changed, 69 insertions(+), 39 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 252e25832b8..4acad674dd3 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -893,6 +893,7 @@ public final class BluetoothAdapter { mListener = listener; } + @GuardedBy("BluetoothAdapter.sProfileLock") void connect(BluetoothProfile proxy, IBinder binder) { Log.d(TAG, BluetoothProfile.getProfileName(mProfile) + " connected"); mConnected = true; @@ -900,6 +901,7 @@ public final class BluetoothAdapter { mListener.onServiceConnected(mProfile, proxy); } + @GuardedBy("BluetoothAdapter.sProfileLock") void disconnect(BluetoothProfile proxy) { Log.d(TAG, BluetoothProfile.getProfileName(mProfile) + " disconnected"); mConnected = false; @@ -908,6 +910,9 @@ public final class BluetoothAdapter { } } + private static final Object sProfileLock = new Object(); + + @GuardedBy("sProfileLock") private final Map mProfileConnections = new ConcurrentHashMap<>(); @@ -3651,16 +3656,25 @@ public final class BluetoothAdapter { BluetoothProfile profileProxy = constructor.apply(context, this); ProfileConnection connection = new ProfileConnection(profile, listener); - mMainHandler.post( + Runnable connectAction = () -> { - mProfileConnections.put(profileProxy, connection); - - IBinder binder = getProfile(profile); - if (binder != null) { - connection.connect(profileProxy, binder); + synchronized (sProfileLock) { + // Synchronize with the binder callback to prevent performing the + // connection.connect + // concurrently + mProfileConnections.put(profileProxy, connection); + + IBinder binder = getProfile(profile); + if (binder != null) { + connection.connect(profileProxy, binder); + } } - }); - + }; + if (Flags.getProfileUseLock()) { + connectAction.run(); + return true; + } + mMainHandler.post(connectAction); return true; } @@ -3697,13 +3711,15 @@ public final class BluetoothAdapter { return; } - ProfileConnection connection = mProfileConnections.remove(proxy); - if (connection != null) { - if (proxy instanceof BluetoothLeCallControl callControl) { - callControl.unregisterBearer(); - } + synchronized (sProfileLock) { + ProfileConnection connection = mProfileConnections.remove(proxy); + if (connection != null) { + if (proxy instanceof BluetoothLeCallControl callControl) { + callControl.unregisterBearer(); + } - connection.disconnect(proxy); + connection.disconnect(proxy); + } } } @@ -3876,37 +3892,50 @@ public final class BluetoothAdapter { @RequiresNoPermission public void onBluetoothOn() { - mMainHandler.post( + Runnable btOnAction = () -> { - mProfileConnections.forEach( - (proxy, connection) -> { - if (connection.mConnected) return; - - IBinder binder = getProfile(connection.mProfile); - if (binder != null) { - connection.connect(proxy, binder); - } else { - Log.e( - TAG, - "onBluetoothOn: Binder null for " - + BluetoothProfile.getProfileName( - connection.mProfile)); - } - }); - }); + synchronized (sProfileLock) { + mProfileConnections.forEach( + (proxy, connection) -> { + if (connection.mConnected) return; + + IBinder binder = getProfile(connection.mProfile); + if (binder != null) { + connection.connect(proxy, binder); + } else { + Log.e( + TAG, + "onBluetoothOn: Binder null for " + + BluetoothProfile.getProfileName(connection.mProfile)); + } + }); + } + }; + if (Flags.getProfileUseLock()) { + btOnAction.run(); + return; + } + mMainHandler.post(btOnAction); } @RequiresNoPermission public void onBluetoothOff() { - mMainHandler.post( + Runnable btOffAction = () -> { - mProfileConnections.forEach( - (proxy, connection) -> { - if (connection.mConnected) { - connection.disconnect(proxy); - } - }); - }); + synchronized (sProfileLock) { + mProfileConnections.forEach( + (proxy, connection) -> { + if (connection.mConnected) { + connection.disconnect(proxy); + } + }); + } + }; + if (Flags.getProfileUseLock()) { + btOffAction.run(); + return; + } + mMainHandler.post(btOffAction); } }; @@ -4203,6 +4232,7 @@ public final class BluetoothAdapter { } /** Return a binder to a Profile service */ + @GuardedBy("sProfileLock") private @Nullable IBinder getProfile(int profile) { mServiceLock.readLock().lock(); try { -- GitLab From 3bac67043ad441a528100f95072968bc8f6ca29d Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 2 Oct 2024 11:43:26 -0700 Subject: [PATCH 128/875] SystemServer: test race condition on enable This race condition is no longer possible due to the threading management of enable happening on the correct thread. Adding test to prevent further regression Test: atest ServiceBluetoothTests:BluetoothManagerServiceTest Bug: 328846833 Flag: TEST_ONLY Change-Id: I0275a64fb01ce3f685b8349370a4b5dbef585b0d --- .../BluetoothManagerServiceTest.java | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java index 6e9222a7449..446562a78aa 100644 --- a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java +++ b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java @@ -302,14 +302,8 @@ public class BluetoothManagerServiceTest { IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder); verify(mAdapterBinder).offToBleOn(anyBoolean(), any()); - // AdapterService is sending AdapterState.BLE_TURN_ON that will trigger this callback - // and in parallel it call its `bringUpBle()` - btCallback.onBluetoothStateChange(STATE_OFF, STATE_BLE_TURNING_ON); - syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE); assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON); - // assertThat(mManagerService.waitForManagerState(STATE_BLE_TURNING_ON)).isTrue(); - // GattService has been started by AdapterService and it will enable native side then // trigger the stateChangeCallback from native btCallback.onBluetoothStateChange(STATE_BLE_TURNING_ON, STATE_BLE_ON); @@ -319,7 +313,7 @@ public class BluetoothManagerServiceTest { private IBluetoothCallback transition_offToOn() throws Exception { IBluetoothCallback btCallback = transition_offToBleOn(); - verify(mAdapterBinder, times(1)).bleOnToOn(any()); + verify(mAdapterBinder).bleOnToOn(any()); // AdapterService go to turning_on and start all profile on its own btCallback.onBluetoothStateChange(STATE_BLE_ON, STATE_TURNING_ON); @@ -336,6 +330,45 @@ public class BluetoothManagerServiceTest { return btCallback; } + @Test + public void enable_whileTurningToBleOn_shouldEnable() throws Exception { + mManagerService.enableBle("enable_whileTurningToBleOn_shouldEnable", mBinder); + syncHandler(MESSAGE_ENABLE); + + acceptBluetoothBinding(mBinder, "btservice.AdapterService", 1); + IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder); + 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); + + btCallback.onBluetoothStateChange(STATE_BLE_TURNING_ON, STATE_BLE_ON); + syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE); + + verify(mAdapterBinder).bleOnToOn(any()); + } + + @Test + public void enable_whileNotYetBoundToBle_shouldEnable() throws Exception { + mManagerService.enableBle("enable_whileTurningToBleOn_shouldEnable", mBinder); + 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); + + acceptBluetoothBinding(mBinder, "btservice.AdapterService", 1); + IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder); + 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()); + } + @Test public void offToBleOn() throws Exception { mManagerService.enableBle("test_offToBleOn", mBinder); -- GitLab From 374b17a6ce8674e837a8db416e4fc727d22fb330 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Wed, 2 Oct 2024 18:41:18 +0000 Subject: [PATCH 129/875] Use TRANSPORT_LE for unknown device type This commit fixes an issue where using BT_TRANSPORT_AUTO with an unknown device type resulted in the allocation of a control block for TRANSPORT_AUTO, preventing callbacks from being invoked after connection. This change effectively reverts the logic unintentionally introduced in aosp/3185968, which caused this issue. Bug: 369765048 Flag: EXEMPT, revert of aosp/3185968 Test: atest GattClientTest Change-Id: I4858d89ba0390890936dd71955c66793d52085e3 --- system/btif/src/btif_gatt_client.cc | 2 ++ system/btif/src/btif_gatt_server.cc | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/system/btif/src/btif_gatt_client.cc b/system/btif/src/btif_gatt_client.cc index 717e3574bca..e7276bb34e9 100644 --- a/system/btif/src/btif_gatt_client.cc +++ b/system/btif/src/btif_gatt_client.cc @@ -349,6 +349,8 @@ void btif_gattc_open_impl(int client_if, RawAddress address, tBLE_ADDR_TYPE addr default: log::error("Unknown device type {}", DeviceTypeText(device_type)); + // transport must not be AUTO for finding control blocks. Use LE for backward compatibility. + transport = BT_TRANSPORT_LE; break; } } diff --git a/system/btif/src/btif_gatt_server.cc b/system/btif/src/btif_gatt_server.cc index 653384aff5a..fab86d75798 100644 --- a/system/btif/src/btif_gatt_server.cc +++ b/system/btif/src/btif_gatt_server.cc @@ -322,6 +322,8 @@ static void btif_gatts_open_impl(int server_if, const RawAddress& address, bool default: log::error("Unknown device type {}", DeviceTypeText(device_type)); + // transport must not be AUTO for finding control blocks. Use LE for backward compatibility. + transport = BT_TRANSPORT_LE; break; } } @@ -355,6 +357,8 @@ static void btif_gatts_open_impl_use_address_type(int server_if, const RawAddres default: log::error("Unknown device type {}", DeviceTypeText(device_type)); + // transport must not be AUTO for finding control blocks. Use LE for backward compatibility. + transport = BT_TRANSPORT_LE; break; } } -- GitLab From 1cc68cfda6041a3626c646a525b24f633bb7211d Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 30 Sep 2024 18:45:55 -0700 Subject: [PATCH 130/875] Remove the init_flags module All existing init flags have been migrated to feature flags or removed and the rust module can now be deleted. Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: I38be97fad7f9bd42f432d74e5b8090a08dc4502a --- Cargo.toml | 2 - android/app/Android.bp | 1 - ...oid_bluetooth_btservice_AdapterService.cpp | 33 +-- .../btservice/AdapterNativeInterface.java | 3 - .../bluetooth/btservice/AdapterService.java | 13 - system/audio/Android.bp | 2 - system/audio_hal_interface/Android.bp | 6 - system/audio_hal_interface/BUILD.gn | 1 - system/audio_hal_interface/fuzzer/Android.bp | 2 - system/bta/Android.bp | 35 +-- system/bta/BUILD.gn | 1 - system/btcore/Android.bp | 2 - system/btcore/BUILD.gn | 5 - system/btcore/fuzzer/Android.bp | 3 - system/btif/Android.bp | 19 +- system/btif/BUILD.gn | 1 - system/common/Android.bp | 2 - system/common/BUILD.gn | 1 - system/device/Android.bp | 5 - system/device/BUILD.gn | 2 - system/device/fuzzer/Android.bp | 2 - system/gd/Android.bp | 19 -- system/gd/BUILD.gn | 2 - system/gd/common/Android.bp | 1 - system/gd/common/init_flags.h | 37 --- system/gd/common/init_flags_test.cc | 19 -- system/gd/os/BUILD.gn | 2 - system/gd/packet/BUILD.gn | 1 - system/gd/rust/common/Android.bp | 10 + system/gd/rust/common/src/init_flags.rs | 241 ------------------ system/gd/rust/common/src/lib.rs | 3 - system/gd/rust/linux/service/Cargo.toml | 1 - system/gd/rust/linux/service/src/main.rs | 4 - system/gd/rust/linux/stack/Cargo.toml | 1 - .../rust/linux/stack/src/bluetooth_admin.rs | 3 - system/gd/rust/shim/Android.bp | 116 --------- system/gd/rust/shim/BUILD.gn | 44 ---- system/gd/rust/shim/Cargo.toml | 30 --- system/gd/rust/shim/src/init_flags.rs | 28 -- system/gd/rust/shim/src/lib.rs | 3 - system/gd/rust/topshim/Android.bp | 9 +- system/gd/rust/topshim/facade/Android.bp | 2 - system/gd/rust/topshim/facade/src/main.rs | 2 - system/gd/rust/topshim/src/btif.rs | 1 - system/gd/shim/BUILD.gn | 1 - system/hci/Android.bp | 1 - system/include/hardware/bluetooth.h | 5 +- system/main/Android.bp | 8 +- system/main/shim/BUILD.gn | 4 - system/osi/Android.bp | 3 - system/osi/BUILD.gn | 1 - system/profile/avrcp/Android.bp | 5 - system/profile/avrcp/BUILD.gn | 1 - system/rust/Android.bp | 10 +- system/rust/BUILD.gn | 1 - system/rust/src/lib.rs | 7 - system/stack/Android.bp | 62 +---- system/stack/BUILD.gn | 3 +- system/stack/mmc/codec_server/BUILD.gn | 1 - system/stack/test/fuzzers/Android.bp | 1 - system/test/Android.bp | 7 - system/test/common/init_flags.cc | 17 -- system/test/headless/Android.bp | 1 - system/test/headless/headless.cc | 2 +- system/test/suite/Android.bp | 1 - system/test/suite/adapter/bluetooth_test.cc | 4 +- system/test/tool/mockcify.pl | 2 - system/udrv/Android.bp | 1 - 68 files changed, 45 insertions(+), 824 deletions(-) delete mode 100644 system/gd/common/init_flags.h delete mode 100644 system/gd/common/init_flags_test.cc delete mode 100644 system/gd/rust/common/src/init_flags.rs delete mode 100644 system/gd/rust/shim/Android.bp delete mode 100644 system/gd/rust/shim/BUILD.gn delete mode 100644 system/gd/rust/shim/Cargo.toml delete mode 100644 system/gd/rust/shim/src/init_flags.rs delete mode 100644 system/gd/rust/shim/src/lib.rs delete mode 100644 system/test/common/init_flags.cc diff --git a/Cargo.toml b/Cargo.toml index 5ed873e057f..d3cee8799b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ [workspace] default-members = [ - "system/gd/rust/shim", "system/gd/rust/topshim", "system/gd/rust/linux/mgmt", "system/gd/rust/linux/service", @@ -26,7 +25,6 @@ default-members = [ ] members = [ - "system/gd/rust/shim", "system/gd/rust/topshim", "system/gd/rust/linux/mgmt", "system/gd/rust/linux/service", diff --git a/android/app/Android.bp b/android/app/Android.bp index b80bd4057c5..8a883b640ff 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -125,7 +125,6 @@ cc_library_shared { "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbtcore", "libbtdevice", "libbte", diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index 8036b43681d..b4cf5eb3262 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -1020,8 +1020,7 @@ int hal_util_load_bt_library(const bt_interface_t** interface) { } static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest, jboolean isCommonCriteriaMode, - int configCompareResult, jobjectArray initFlags, jboolean isAtvDevice, - jstring userDataDirectory) { + int configCompareResult, jboolean isAtvDevice, jstring userDataDirectory) { std::unique_lock lock(jniObjMutex); log::verbose(""); @@ -1036,34 +1035,15 @@ static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest, jboolean isCo return JNI_FALSE; } - int flagCount = env->GetArrayLength(initFlags); - jstring* flagObjs = new jstring[flagCount]; - const char** flags = nullptr; - if (flagCount > 0) { - flags = new const char*[flagCount + 1]; - flags[flagCount] = nullptr; - } - - for (int i = 0; i < flagCount; i++) { - flagObjs[i] = (jstring)env->GetObjectArrayElement(initFlags, i); - flags[i] = env->GetStringUTFChars(flagObjs[i], NULL); - } - const char* user_data_directory = env->GetStringUTFChars(userDataDirectory, NULL); - int ret = sBluetoothInterface->init(&sBluetoothCallbacks, isGuest == JNI_TRUE ? 1 : 0, - isCommonCriteriaMode == JNI_TRUE ? 1 : 0, configCompareResult, - flags, isAtvDevice == JNI_TRUE ? 1 : 0, user_data_directory); + int ret = + sBluetoothInterface->init(&sBluetoothCallbacks, isGuest == JNI_TRUE ? 1 : 0, + isCommonCriteriaMode == JNI_TRUE ? 1 : 0, configCompareResult, + nullptr, isAtvDevice == JNI_TRUE ? 1 : 0, user_data_directory); env->ReleaseStringUTFChars(userDataDirectory, user_data_directory); - for (int i = 0; i < flagCount; i++) { - env->ReleaseStringUTFChars(flagObjs[i], flags[i]); - } - - delete[] flags; - delete[] flagObjs; - if (ret != BT_STATUS_SUCCESS) { log::error("Error while setting the callbacks: {}", ret); sBluetoothInterface = NULL; @@ -2245,8 +2225,7 @@ static jboolean restoreFilterAcceptListNative(JNIEnv* /* env */, jobject /* obj int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) { const JNINativeMethod methods[] = { - {"initNative", "(ZZI[Ljava/lang/String;ZLjava/lang/String;)Z", - reinterpret_cast(initNative)}, + {"initNative", "(ZZIZLjava/lang/String;)Z", reinterpret_cast(initNative)}, {"cleanupNative", "()V", reinterpret_cast(cleanupNative)}, {"enableNative", "()Z", reinterpret_cast(enableNative)}, {"disableNative", "()Z", reinterpret_cast(disableNative)}, diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java index 28bff10bb75..87cd3536a4e 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java @@ -64,7 +64,6 @@ public class AdapterNativeInterface { boolean startRestricted, boolean isCommonCriteriaMode, int configCompareResult, - String[] initFlags, boolean isAtvDevice, String userDataDirectory) { mJniCallbacks = new JniCallbacks(service, adapterProperties); @@ -72,7 +71,6 @@ public class AdapterNativeInterface { startRestricted, isCommonCriteriaMode, configCompareResult, - initFlags, isAtvDevice, userDataDirectory); } @@ -297,7 +295,6 @@ public class AdapterNativeInterface { boolean startRestricted, boolean isCommonCriteriaMode, int configCompareResult, - String[] initFlags, boolean isAtvDevice, String userDataDirectory); diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 5acdcd0197e..19c8aee207c 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -700,7 +700,6 @@ public class AdapterService extends Service { mUserManager.isGuestUser(), isCommonCriteriaMode, configCompareResult, - getInitFlags(), isAtvDevice, getApplicationInfo().dataDir); mNativeAvailable = true; @@ -6441,18 +6440,6 @@ public class AdapterService extends Service { } } - private String[] getInitFlags() { - final DeviceConfig.Properties properties = - DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH); - ArrayList initFlags = new ArrayList<>(); - for (String property : properties.getKeyset()) { - if (property.startsWith("INIT_")) { - initFlags.add(property + "=" + properties.getString(property, null)); - } - } - return initFlags.toArray(new String[0]); - } - private final Object mDeviceConfigLock = new Object(); /** diff --git a/system/audio/Android.bp b/system/audio/Android.bp index 9165555cf68..d5dde594e1a 100644 --- a/system/audio/Android.bp +++ b/system/audio/Android.bp @@ -37,7 +37,6 @@ cc_library_static { "libbase", "libbluetooth_hci_pdl", "libbluetooth_log", - "libbt_shim_bridge", "libflatbuffers-cpp", ], host_supported: true, @@ -77,7 +76,6 @@ cc_library_host_shared { "libbluetooth_hci_pdl", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", "libchrome", "libevent", "libflatbuffers-cpp", diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index 9704c1589bd..6fd00375620 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -31,7 +31,6 @@ cc_library_static { "bluetooth_flags_c_lib", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", "libosi", ], target: { @@ -121,7 +120,6 @@ cc_test { "libbluetooth_log", "libbt-audio-hal-interface", "libbt-common", - "libbt_shim_bridge", "libchrome", ], header_libs: ["libbluetooth_headers"], @@ -188,7 +186,6 @@ cc_test { "libbluetooth-types", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", "libchrome", "libflagtest", "libfmq", @@ -238,14 +235,12 @@ cc_defaults { "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", - "libbluetooth_rust_interop", "libbt-common", // needed for MessageLoopThread "libbt-jni-thread", "libbt-sbc-decoder", "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbtcore", "libbtdevice", "libbte", @@ -315,7 +310,6 @@ cc_test { "libbt-bta", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libchrome", "libevent", "libgmock", diff --git a/system/audio_hal_interface/BUILD.gn b/system/audio_hal_interface/BUILD.gn index 5e26e14d209..a637d5afd68 100644 --- a/system/audio_hal_interface/BUILD.gn +++ b/system/audio_hal_interface/BUILD.gn @@ -27,7 +27,6 @@ static_library("audio_hal_interface") { "//bt/system/bta/include", "//bt/system/btif/include", "//bt/system/stack/include", - "//bt/system/gd/rust/shim", ] configs += [ diff --git a/system/audio_hal_interface/fuzzer/Android.bp b/system/audio_hal_interface/fuzzer/Android.bp index 5b03d9fa3e9..e55a9d62add 100644 --- a/system/audio_hal_interface/fuzzer/Android.bp +++ b/system/audio_hal_interface/fuzzer/Android.bp @@ -67,7 +67,6 @@ cc_defaults { "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", - "libbluetooth_rust_interop", "libbt-audio-hal-interface", "libbt-bta", "libbt-bta-core", @@ -79,7 +78,6 @@ cc_defaults { "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbtcore", "libbtdevice", "libbte", diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 2a045eb9477..3f74fe22943 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -150,7 +150,6 @@ cc_library_static { "libbt-audio-asrc", "libbt-bta-core", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libcom.android.sysprop.bluetooth.wrapped", "liblc3", ], @@ -218,7 +217,6 @@ cc_library_static { "libbluetooth_log", "libbt-audio-hal-interface", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libcom.android.sysprop.bluetooth.wrapped", "libflatbuffers-cpp", "server_configurable_flags", @@ -317,8 +315,6 @@ cc_test { "libbt-btu-main-thread", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libbtdevice", "libchrome", @@ -398,8 +394,6 @@ cc_test { "libbt-bta-core", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", @@ -438,6 +432,7 @@ cc_test { static_libs: [ "bluetooth_flags_c_lib", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", @@ -447,8 +442,6 @@ cc_test { "libbt-btu-main-thread", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libchrome", "libgmock", @@ -501,8 +494,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libbtdevice", "libchrome", @@ -570,8 +561,6 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcutils", "libgmock", @@ -620,8 +609,6 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libgmock", "libosi", @@ -682,8 +669,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libgmock", "server_configurable_flags", @@ -839,8 +824,6 @@ cc_test { "libbt-audio-hal-interface", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libflatbuffers-cpp", @@ -951,8 +934,6 @@ cc_test { "libbt-audio-asrc", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libflatbuffers-cpp", @@ -1039,8 +1020,6 @@ cc_test { "libbt-audio-hal-interface", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libflagtest", @@ -1134,8 +1113,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libflagtest", "libflatbuffers-cpp", @@ -1212,8 +1189,6 @@ cc_test { "libbt-audio-hal-interface", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libflagtest", @@ -1282,8 +1257,6 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libgmock", ], @@ -1350,14 +1323,13 @@ cc_test { static_libs: [ "bluetooth_flags_c_lib", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_hci_pdl", "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", "libevent", @@ -1423,14 +1395,13 @@ cc_test { static_libs: [ "bluetooth_flags_c_lib", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_hci_pdl", "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", "libevent", diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn index 306aaae1e9f..ba89c1cb693 100644 --- a/system/bta/BUILD.gn +++ b/system/bta/BUILD.gn @@ -172,7 +172,6 @@ static_library("bta") { "//bt/system/bta:install_audio_set_scenarios_bfbs", "//bt/system/bta:install_audio_set_configurations_bfbs", "//bt/system:libbt-platform-protos-lite", - "//bt/system/gd/rust/shim:init_flags_bridge_header", ] libs = [ diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp index 6410de70bcb..96da5abf573 100644 --- a/system/btcore/Android.bp +++ b/system/btcore/Android.bp @@ -57,7 +57,6 @@ cc_library_static { }, static_libs: [ "libbluetooth_log", - "libbt_shim_bridge", ], } @@ -71,7 +70,6 @@ cc_library_static { min_sdk_version: "Tiramisu", static_libs: [ "libbluetooth_log", - "libbt_shim_bridge", ], } diff --git a/system/btcore/BUILD.gn b/system/btcore/BUILD.gn index f7b86f2023c..76853554cf9 100644 --- a/system/btcore/BUILD.gn +++ b/system/btcore/BUILD.gn @@ -32,11 +32,6 @@ static_library("btcore") { "//bt/system:target_defaults", "//bt/system/log:log_defaults", ] - - deps = [ - "//bt/system/gd/rust/shim:init_flags_bridge_header", - "//bt/system/gd/rust/shim:libbluetooth_rust_interop", - ] } if (use.test) { diff --git a/system/btcore/fuzzer/Android.bp b/system/btcore/fuzzer/Android.bp index 746fdb9244f..746a3b31b50 100644 --- a/system/btcore/fuzzer/Android.bp +++ b/system/btcore/fuzzer/Android.bp @@ -35,10 +35,7 @@ cc_defaults { "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_log", - "libbluetooth_rust_interop", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libchrome", "libevent", diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 9b1bc412956..958c079471a 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -60,7 +60,6 @@ cc_library_static { srcs: ["src/btif_jni_task.cc"], static_libs: [ "libbluetooth_log", - "libbt_shim_bridge", "libosi", ], shared_libs: [ @@ -163,7 +162,6 @@ cc_library_static { "libbt-platform-protos-lite", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbtif-core", "libflatbuffers-cpp", ], @@ -244,7 +242,6 @@ cc_library_static { "libbt-jni-thread", "libbt-platform-protos-lite", "libbt-stack-core", - "libbt_shim_bridge", "libcom.android.sysprop.bluetooth.wrapped", "libflatbuffers-cpp", "libstatslog_bt", @@ -320,7 +317,6 @@ cc_test { "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbtcore", "libbtdevice", "libbtif", @@ -389,8 +385,6 @@ cc_test { "libbluetooth-types", "libbluetooth_gd", "libbluetooth_log", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libosi", ], @@ -428,8 +422,6 @@ cc_test { static_libs: [ "libbluetooth-types", "libbluetooth_log", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libosi", ], @@ -477,8 +469,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", ], @@ -520,10 +510,9 @@ cc_test { ], static_libs: [ "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_log", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", "libgmock", @@ -609,6 +598,7 @@ cc_test { "lib-bt-packets-avrcp", "lib-bt-packets-base", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", @@ -620,8 +610,6 @@ cc_test { "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libbtif", "libbtif-core", @@ -732,6 +720,7 @@ cc_test { "lib-bt-packets-avrcp", "lib-bt-packets-base", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_hci_pdl", @@ -743,8 +732,6 @@ cc_test { "libbt-platform-protos-lite", "libbt-sbc-decoder", "libbt-sbc-encoder", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libbtif", "libbtif-core", diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn index 7e4897fe6da..5129a1efb37 100644 --- a/system/btif/BUILD.gn +++ b/system/btif/BUILD.gn @@ -113,7 +113,6 @@ static_library("btif") { "//bt/sysprop:libcom.android.sysprop.bluetooth", "//bt/system:libbt-platform-protos-lite", "//bt/system/common", - "//bt/system/gd/rust/shim:init_flags_bridge_header", "//bt/system/profile/avrcp:profile_avrcp", "//bt/system/gd:libbluetooth-gdx", ] diff --git a/system/common/Android.bp b/system/common/Android.bp index f50de9f23ea..3009c77ec0e 100644 --- a/system/common/Android.bp +++ b/system/common/Android.bp @@ -57,7 +57,6 @@ cc_library_static { "libbluetooth_crypto_toolbox", "libbluetooth_log", "libbt-platform-protos-lite", - "libbt_shim_bridge", ], } @@ -107,7 +106,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libchrome", "libevent", "libgmock", diff --git a/system/common/BUILD.gn b/system/common/BUILD.gn index 52c14aaa0fb..8352d2bcc41 100644 --- a/system/common/BUILD.gn +++ b/system/common/BUILD.gn @@ -34,7 +34,6 @@ static_library("common") { deps = [ "//bt/system:libbt-platform-protos-lite", - "//bt/system/gd/rust/shim:init_flags_bridge_header", ] configs += [ diff --git a/system/device/Android.bp b/system/device/Android.bp index 21d2344bf3e..f4b06790fc1 100644 --- a/system/device/Android.bp +++ b/system/device/Android.bp @@ -39,7 +39,6 @@ cc_library_static { "libaconfig_storage_read_api_cc", "libbluetooth_hci_pdl", "libbluetooth_log", - "libbt_shim_bridge", "libflatbuffers-cpp", "server_configurable_flags", ], @@ -66,8 +65,6 @@ cc_test { "libbluetooth-types", "libbluetooth_gd", "libbluetooth_log", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libbtdevice", "libchrome", @@ -106,8 +103,6 @@ cc_test { "libbluetooth-types", "libbluetooth_log", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libbtdevice", "libchrome", diff --git a/system/device/BUILD.gn b/system/device/BUILD.gn index 08cf2291134..12d38b33c4a 100644 --- a/system/device/BUILD.gn +++ b/system/device/BUILD.gn @@ -34,8 +34,6 @@ static_library("device") { deps = [ "//bt/flags:bluetooth_flags_c_lib", - "//bt/system/gd/rust/shim:init_flags_bridge_header", - "//bt/system/gd/rust/shim:libbluetooth_rust_interop", "//bt/system/pdl:BluetoothGeneratedPackets_h", ] } diff --git a/system/device/fuzzer/Android.bp b/system/device/fuzzer/Android.bp index 64271ae1460..0b5e6c1296d 100644 --- a/system/device/fuzzer/Android.bp +++ b/system/device/fuzzer/Android.bp @@ -49,8 +49,6 @@ cc_fuzz { "libbluetooth_gd", "libbluetooth_hci_pdl", "libbluetooth_log", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtcore", "libbtdevice", "libchrome", diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 1e4950d41cf..d09e184f923 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -178,11 +178,8 @@ cc_defaults { "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_log", - "libbluetooth_rust_interop", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libcom.android.sysprop.bluetooth.wrapped", "libosi", "server_configurable_flags", @@ -192,7 +189,6 @@ cc_defaults { "packages/modules/Bluetooth/system/stack/include", "packages/modules/Bluetooth/system/types", ], - export_static_lib_headers: ["libbluetooth_rust_interop"], } cc_library { @@ -329,11 +325,8 @@ cc_binary { "libbluetooth_l2cap_pdl", "libbluetooth_log", "libbluetooth_ras_pdl", - "libbluetooth_rust_interop", "libbluetooth_smp_pdl", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", "libflatbuffers-cpp", @@ -501,12 +494,9 @@ cc_test { "libbluetooth_l2cap_pdl", "libbluetooth_log", "libbluetooth_ras_pdl", - "libbluetooth_rust_interop", "libbluetooth_smp_pdl", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", "libflagtest", @@ -569,8 +559,6 @@ cc_test { "libbt-btu-main-thread", "libbt-common", "libbt-jni-thread", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libflatbuffers-cpp", @@ -611,9 +599,6 @@ cc_test { static_libs: [ "libbase", "libbluetooth_log", - "libbluetooth_rust_interop", - "libbt_shim_bridge", - "libbt_shim_ffi", "liblog", ], target: { @@ -649,10 +634,7 @@ cc_defaults { "libbluetooth_crypto_toolbox", "libbluetooth_gd_fuzzing", "libbluetooth_log", - "libbluetooth_rust_interop", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", "libgmock", @@ -746,7 +728,6 @@ cc_benchmark { "libbase", "libbluetooth_gd", "libbluetooth_log", - "libbt_shim_bridge", "libchrome", "liblog", "server_configurable_flags", diff --git a/system/gd/BUILD.gn b/system/gd/BUILD.gn index 914ec302579..4e14df9a254 100644 --- a/system/gd/BUILD.gn +++ b/system/gd/BUILD.gn @@ -50,7 +50,6 @@ group("gd_default_deps") { "//bt/system:libbt-platform-protos-lite", "//bt/system/gd:BluetoothGeneratedDumpsysDataSchema_h", "//bt/system/gd/dumpsys:libbluetooth-dumpsys", - "//bt/system/gd/rust/shim:init_flags_bridge_header", "//bt/system/pdl:BluetoothGeneratedPackets_h", ] } @@ -77,7 +76,6 @@ static_library("libbluetooth_gd") { configs += [ ":gd_defaults" ] deps = [ "//bt/system/gd/rust/topshim:libbluetooth_topshim", - "//bt/system/gd/rust/shim:libbluetooth_rust_interop", "//bt/system/gd/common:BluetoothCommonSources", "//bt/system/gd/dumpsys:BluetoothDumpsysSources", "//bt/system/gd/hal:BluetoothHalSources", diff --git a/system/gd/common/Android.bp b/system/gd/common/Android.bp index 36da276e450..5e8b927058d 100644 --- a/system/gd/common/Android.bp +++ b/system/gd/common/Android.bp @@ -24,7 +24,6 @@ filegroup { "blocking_queue_unittest.cc", "byte_array_test.cc", "circular_buffer_test.cc", - "init_flags_test.cc", "list_map_test.cc", "lru_cache_test.cc", "metric_id_manager_unittest.cc", diff --git a/system/gd/common/init_flags.h b/system/gd/common/init_flags.h deleted file mode 100644 index de3d56103f0..00000000000 --- a/system/gd/common/init_flags.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 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 "src/init_flags.rs.h" - -namespace bluetooth { -namespace common { - -class InitFlags final { -public: - inline static void Load(const char** flags) { - rust::Vec rusted_flags = rust::Vec(); - while (flags != nullptr && *flags != nullptr) { - rusted_flags.push_back(rust::String(*flags)); - flags++; - } - init_flags::load(std::move(rusted_flags)); - } -}; - -} // namespace common -} // namespace bluetooth diff --git a/system/gd/common/init_flags_test.cc b/system/gd/common/init_flags_test.cc deleted file mode 100644 index 98a1779989a..00000000000 --- a/system/gd/common/init_flags_test.cc +++ /dev/null @@ -1,19 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 \ No newline at end of file diff --git a/system/gd/os/BUILD.gn b/system/gd/os/BUILD.gn index e56c6883ddd..6824184ad01 100644 --- a/system/gd/os/BUILD.gn +++ b/system/gd/os/BUILD.gn @@ -27,7 +27,6 @@ source_set("BluetoothOsSources_chromeos") { ] deps = [ "//bt/system:libbt-platform-protos-lite", - "//bt/system/gd/rust/shim:init_flags_bridge_header", ] } @@ -46,7 +45,6 @@ source_set("BluetoothOsSources_linux") { ] deps = [ "//bt/system:libbt-platform-protos-lite", - "//bt/system/gd/rust/shim:init_flags_bridge_header", ] } diff --git a/system/gd/packet/BUILD.gn b/system/gd/packet/BUILD.gn index 871209a43b8..2dbe5b1f982 100644 --- a/system/gd/packet/BUILD.gn +++ b/system/gd/packet/BUILD.gn @@ -28,7 +28,6 @@ source_set("BluetoothPacketSources") { include_dirs = [ "//bt/system/gd" ] - deps = [ "//bt/system/gd/rust/shim:init_flags_bridge_header" ] configs += [ "//bt/system:target_defaults", "//bt/system/log:log_defaults", diff --git a/system/gd/rust/common/Android.bp b/system/gd/rust/common/Android.bp index 188225ecf21..a1e8c4a977f 100644 --- a/system/gd/rust/common/Android.bp +++ b/system/gd/rust/common/Android.bp @@ -7,6 +7,16 @@ package { default_applicable_licenses: ["system_bt_license"], } +rust_defaults { + name: "gd_rust_defaults", + target: { + darwin: { + enabled: false, + }, + }, + host_supported: true, +} + rust_library { name: "libbt_common", defaults: ["libbt_common_defaults"], diff --git a/system/gd/rust/common/src/init_flags.rs b/system/gd/rust/common/src/init_flags.rs deleted file mode 100644 index feb0ed96a9b..00000000000 --- a/system/gd/rust/common/src/init_flags.rs +++ /dev/null @@ -1,241 +0,0 @@ -use log::{error, info}; -use paste::paste; -use std::collections::{BTreeMap, HashMap}; -use std::fmt; -use std::sync::LazyLock; -use std::sync::Mutex; - -// Fallback to bool when type is not specified -macro_rules! type_expand { - () => { - bool - }; - ($type:ty) => { - $type - }; -} - -macro_rules! default_value { - () => { - false - }; - ($type:ty) => { - <$type>::default() - }; - ($($type:ty)? = $default:tt) => { - $default - }; -} - -#[cfg(test)] -macro_rules! call_getter_fn { - ($flag:ident) => { - paste! { - [<$flag _is_enabled>]() - } - }; -} - -macro_rules! create_getter_fn { - ($flag:ident) => { - paste! { - #[doc = concat!(" Return true if ", stringify!($flag), " is enabled")] - pub fn [<$flag _is_enabled>]() -> bool { - FLAGS.lock().unwrap().$flag - } - } - }; -} - -macro_rules! init_flags { - ( - name: $name:ident - $($args:tt)* - ) => { - init_flags_struct! { - name: $name - $($args)* - } - - init_flags_getters! { - $($args)* - } - } -} - -trait FlagHolder: Default { - fn get_defaults_for_test() -> Self; - fn parse(flags: Vec) -> Self; - fn dump(&self) -> BTreeMap<&'static str, String>; -} - -macro_rules! init_flags_struct { - ( - name: $name:ident - flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* }) => { - - struct $name { - $($flag : type_expand!($($type)?),)* - } - - impl $name { - pub const fn new() -> Self { - Self { - $($flag : default_value!($($type)? $(= $default)?),)* - } - } - } - - impl Default for $name { - fn default() -> Self { - Self::new() - } - } - - impl FlagHolder for $name { - fn get_defaults_for_test() -> Self { - Self { - $($flag: true,)* - } - } - - fn dump(&self) -> BTreeMap<&'static str, String> { - [ - $((stringify!($flag), format!("{}", self.$flag)),)* - ].into() - } - - fn parse(flags: Vec) -> Self { - let mut init_flags = Self::default(); - - for flag in flags { - let values: Vec<&str> = flag.split("=").collect(); - if values.len() != 2 { - error!("Bad flag {}, must be in = format", flag); - continue; - } - - match values[0] { - $(concat!("INIT_", stringify!($flag)) => - init_flags.$flag = values[1].parse().unwrap_or_else(|e| { - error!("Parse failure on '{}': {}", flag, e); - default_value!($($type)? $(= $default)?)}),)* - _ => error!("Unsaved flag: {} = {}", values[0], values[1]) - } - } - - init_flags - } - } - - impl fmt::Display for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - concat!($(concat!(stringify!($flag), "={}")),*), - $(self.$flag),*) - } - } - - } -} - -macro_rules! init_flags_getters { - (flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* }) => { - - $(create_getter_fn!($flag $($type)?);)* - - #[cfg(test)] - mod tests_autogenerated { - use super::*; - $(paste! { - #[test] - pub fn []() { - let _guard = tests::ASYNC_LOCK.lock().unwrap(); - tests::test_load(vec![ - &*format!(concat!(concat!("INIT_", stringify!($flag)), "={}"), true) - ]); - let get_value = call_getter_fn!($flag); - drop(_guard); // Prevent poisonning other tests if a panic occurs - assert_eq!(get_value, true); - } - })* - } - } -} - -#[allow(dead_code)] -#[derive(Default)] -struct ExplicitTagSettings { - map: HashMap, -} - -impl fmt::Display for ExplicitTagSettings { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.map) - } -} - -/// Sets all bool flags to true -/// Set all other flags and extra fields to their default type value -pub fn set_all_for_testing() { - *FLAGS.lock().unwrap() = InitFlags::get_defaults_for_test(); -} - -init_flags!( - name: InitFlags - flags: { - use_unified_connection_manager, - } -); - -/// Store some flag values -static FLAGS: Mutex = Mutex::new(InitFlags::new()); -/// Store the uid of bluetooth -pub static AID_BLUETOOTH: Mutex = Mutex::new(1002); -/// Store the prefix for file system -pub static MISC: LazyLock> = LazyLock::new(|| Mutex::new("/data/misc/".to_string())); - -/// Loads the flag values from the passed-in vector of string values -pub fn load(raw_flags: Vec) { - crate::init_logging(); - - let flags = InitFlags::parse(raw_flags); - info!("Flags loaded: {}", flags); - *FLAGS.lock().unwrap() = flags; -} - -/// Dumps all flag K-V pairs, storing values as strings -pub fn dump() -> BTreeMap<&'static str, String> { - FLAGS.lock().unwrap().dump() -} - -#[cfg(test)] -mod tests { - use super::*; - - /// do not run concurrent tests as they all use the same global init_flag struct and - /// accessor - pub(super) static ASYNC_LOCK: Mutex = Mutex::new(false); - - pub(super) fn test_load(raw_flags: Vec<&str>) { - let raw_flags = raw_flags.into_iter().map(|x| x.to_string()).collect(); - load(raw_flags); - } - - init_flags_struct!( - name: InitFlagsForTest - flags: { - cat, - } - ); - - #[test] - fn test_dumpsys() { - let flags = InitFlagsForTest { ..Default::default() }; - - let out = flags.dump(); - - assert_eq!(out.len(), 1); - assert_eq!(out["cat"], "false"); - } -} diff --git a/system/gd/rust/common/src/lib.rs b/system/gd/rust/common/src/lib.rs index c4001f575af..165aaa50632 100644 --- a/system/gd/rust/common/src/lib.rs +++ b/system/gd/rust/common/src/lib.rs @@ -1,7 +1,4 @@ //! Bluetooth common library -/// Provides runtime configured-at-startup flags -pub mod init_flags; - mod logging; pub use logging::*; diff --git a/system/gd/rust/linux/service/Cargo.toml b/system/gd/rust/linux/service/Cargo.toml index 69049107b90..2ff5c1dbea9 100644 --- a/system/gd/rust/linux/service/Cargo.toml +++ b/system/gd/rust/linux/service/Cargo.toml @@ -6,7 +6,6 @@ build = "build.rs" [dependencies] bt_topshim = { path = "../../topshim" } -bt_shim = { path = "../../shim" } btstack = { path = "../stack" } clap = "2.33.3" dbus_projection = { path = "../dbus_projection" } diff --git a/system/gd/rust/linux/service/src/main.rs b/system/gd/rust/linux/service/src/main.rs index df781794a19..f326bb62ee7 100644 --- a/system/gd/rust/linux/service/src/main.rs +++ b/system/gd/rust/linux/service/src/main.rs @@ -9,10 +9,6 @@ use std::time::Duration; use tokio::runtime::Builder; use tokio::sync::mpsc::Sender; -// Necessary to link right entries. -#[allow(clippy::single_component_path_imports, unused_imports)] -use bt_shim; - use bt_topshim::{btif::get_btinterface, topstack}; use btstack::{ battery_manager::BatteryManager, diff --git a/system/gd/rust/linux/stack/Cargo.toml b/system/gd/rust/linux/stack/Cargo.toml index 2562617b3d1..da42d9face9 100644 --- a/system/gd/rust/linux/stack/Cargo.toml +++ b/system/gd/rust/linux/stack/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" [dependencies] bt_common = { path = "../../common" } bt_topshim = { path = "../../topshim" } -bt_shim = { path = "../../shim" } bt_utils = { path = "../utils" } btif_macros = { path = "btif_macros" } diff --git a/system/gd/rust/linux/stack/src/bluetooth_admin.rs b/system/gd/rust/linux/stack/src/bluetooth_admin.rs index 5a8e2386fdb..ce34bc45a45 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_admin.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_admin.rs @@ -423,10 +423,7 @@ mod tests { use crate::bluetooth_admin::{BluetoothAdmin, BluetoothAdminPolicyHelper}; use bt_topshim::btif::Uuid; - // A workaround needed for linking. For more details, check the comment in - // system/gd/rust/topshim/facade/src/main.rs #[allow(unused)] - use bt_shim::*; use serde_json::{json, Value}; #[test] diff --git a/system/gd/rust/shim/Android.bp b/system/gd/rust/shim/Android.bp deleted file mode 100644 index 295f766ad2a..00000000000 --- a/system/gd/rust/shim/Android.bp +++ /dev/null @@ -1,116 +0,0 @@ -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"], -} - -rust_defaults { - name: "gd_rust_defaults", - target: { - darwin: { - enabled: false, - }, - }, - host_supported: true, -} - -cc_defaults { - name: "gd_ffi_defaults", - target: { - darwin: { - enabled: false, - }, - }, -} - -rust_defaults { - name: "libbt_shim_defaults", - defaults: ["gd_rust_defaults"], - crate_name: "bt_shim", - srcs: ["src/lib.rs"], - rustlibs: [ - "libbt_common", - "libcxx", - ], - proc_macros: [ - "libpaste", - ], - apex_available: [ - "com.android.btservices", - ], - min_sdk_version: "30", -} - -rust_library_rlib { - name: "libbt_shim", - defaults: ["libbt_shim_defaults"], -} - -rust_ffi_static { - name: "libbt_shim_ffi", - defaults: ["libbt_shim_defaults"], -} - -cc_library_static { - name: "libbt_shim_bridge", - defaults: [ - "gd_ffi_defaults", - ], - generated_headers: [ - "cxx-bridge-header", - "libbt_init_flags_bridge_header", - ], - generated_sources: [ - "libbt_init_flags_bridge_code", - ], - export_generated_headers: [ - "cxx-bridge-header", - "libbt_init_flags_bridge_header", - ], - include_dirs: [ - "packages/modules/Bluetooth/system/gd", - ], - cflags: [ - "-Wno-unused-const-variable", - ], - host_supported: true, - apex_available: [ - "com.android.btservices", - ], - min_sdk_version: "30", -} - -cc_library_static { - name: "libbluetooth_rust_interop", - defaults: [ - "gd_ffi_defaults", - ], - static_libs: [ - "libbt_shim_bridge", - "libbt_shim_ffi", - ], - host_supported: true, - apex_available: [ - "com.android.btservices", - ], - min_sdk_version: "30", -} - -genrule { - name: "libbt_init_flags_bridge_header", - tools: ["cxxbridge"], - cmd: "$(location cxxbridge) $(in) --header > $(out)", - srcs: ["src/init_flags.rs"], - out: ["src/init_flags.rs.h"], -} - -genrule { - name: "libbt_init_flags_bridge_code", - tools: ["cxxbridge"], - cmd: "$(location cxxbridge) $(in) >> $(out)", - srcs: ["src/init_flags.rs"], - out: ["init_flags.cc"], -} diff --git a/system/gd/rust/shim/BUILD.gn b/system/gd/rust/shim/BUILD.gn deleted file mode 100644 index 363c63958cd..00000000000 --- a/system/gd/rust/shim/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2020 Google -# -# 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. -# - -import("//common-mk/cxxbridge.gni") - -config("rust_shim_config") { - include_dirs = [ "//bt/system/gd/rust/shim" ] -} - -cxxbridge_header("init_flags_bridge_header") { - sources = [ "src/init_flags.rs" ] - all_dependent_configs = [ ":rust_shim_config" ] - deps = [ ":cxxlibheader" ] -} - -cxxbridge_cc("init_flags_bridge_code") { - sources = [ "src/init_flags.rs" ] - deps = [ ":init_flags_bridge_header" ] - configs = [ "//bt/system/gd:gd_defaults" ] -} - -cxxbridge_libheader("cxxlibheader") { - deps = [] -} - -static_library("libbluetooth_rust_interop") { - deps = [ - ":cxxlibheader", - ":init_flags_bridge_code", - ] -} diff --git a/system/gd/rust/shim/Cargo.toml b/system/gd/rust/shim/Cargo.toml deleted file mode 100644 index 4731d798115..00000000000 --- a/system/gd/rust/shim/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2021 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. - -[package] -name = "bt_shim" -version = "0.0.1" -edition = "2018" - -[dependencies] -# BT dependencies -bt_common = { path = "../common" } - -# All external dependencies. Keep all versions at build/rust/Cargo.toml -cxx = { version = "1.0.42", features = ["c++17"] } -env_logger = "0.8" - -[lib] -path = "src/lib.rs" diff --git a/system/gd/rust/shim/src/init_flags.rs b/system/gd/rust/shim/src/init_flags.rs deleted file mode 100644 index a4819bd0963..00000000000 --- a/system/gd/rust/shim/src/init_flags.rs +++ /dev/null @@ -1,28 +0,0 @@ -#[cxx::bridge(namespace = bluetooth::common::init_flags)] -#[allow(unsafe_op_in_unsafe_fn)] -mod ffi { - struct InitFlagWithValue { - flag: &'static str, - value: String, - } - - extern "Rust" { - fn load(flags: Vec); - fn set_all_for_testing(); - - fn dump() -> Vec; - - fn use_unified_connection_manager_is_enabled() -> bool; - } -} - -use crate::init_flags::ffi::InitFlagWithValue; - -fn dump() -> Vec { - bt_common::init_flags::dump() - .into_iter() - .map(|(flag, value)| InitFlagWithValue { flag, value }) - .collect() -} - -use bt_common::init_flags::*; diff --git a/system/gd/rust/shim/src/lib.rs b/system/gd/rust/shim/src/lib.rs deleted file mode 100644 index 4a3910a1234..00000000000 --- a/system/gd/rust/shim/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! The main entry point for the legacy C++ code - -mod init_flags; diff --git a/system/gd/rust/topshim/Android.bp b/system/gd/rust/topshim/Android.bp index 1ce52154411..af5ed8cb5b3 100644 --- a/system/gd/rust/topshim/Android.bp +++ b/system/gd/rust/topshim/Android.bp @@ -39,9 +39,6 @@ rust_library_host_rlib { cc_library_static { name: "libbt_topshim_cxx", - defaults: [ - "gd_ffi_defaults", - ], srcs: [ "btav/btav_shim.cc", "btav_sink/btav_sink_shim.cc", @@ -57,7 +54,6 @@ cc_library_static { generated_headers: [ "BluetoothGeneratedDumpsysDataSchema_h", "cxx-bridge-header", - "libbt_init_flags_bridge_header", "libbt_topshim_bridge_header", ], generated_sources: ["libbt_topshim_bridge_code"], @@ -75,6 +71,11 @@ cc_library_static { "libchrome", "libflatbuffers-cpp", ], + target: { + darwin: { + enabled: false, + }, + }, } gensrcs { diff --git a/system/gd/rust/topshim/facade/Android.bp b/system/gd/rust/topshim/facade/Android.bp index 8e31ae7201c..cfecd4465b4 100644 --- a/system/gd/rust/topshim/facade/Android.bp +++ b/system/gd/rust/topshim/facade/Android.bp @@ -21,7 +21,6 @@ rust_defaults { rustlibs: [ "libbluetooth_core_rs_for_facade", "libbt_common", - "libbt_shim", "libbt_topshim", "libbt_topshim_facade_protobuf", "libclap", @@ -56,7 +55,6 @@ rust_defaults { "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbt_topshim_cxx", "libbtcore", "libbtdevice", diff --git a/system/gd/rust/topshim/facade/src/main.rs b/system/gd/rust/topshim/facade/src/main.rs index 65ac4c72a17..a8a9745752e 100644 --- a/system/gd/rust/topshim/facade/src/main.rs +++ b/system/gd/rust/topshim/facade/src/main.rs @@ -31,8 +31,6 @@ mod utils; // This is fine for now since bt_shim doesn't export anything #[allow(unused)] use bluetooth_core_rs_for_facade::*; -#[allow(unused)] -use bt_shim::*; fn main() { // SAFETY: There is no signal handler installed before this. diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index b5df64fb7e8..5a6d76b7705 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -1215,7 +1215,6 @@ impl BluetoothInterface { /// # Arguments /// /// * `callbacks` - Dispatcher struct that accepts [`BaseCallbacks`] - /// * `init_flags` - List of flags sent to libbluetooth for init. /// * `hci_index` - Index of the hci adapter in use pub fn initialize(&mut self, callbacks: BaseCallbacksDispatcher, hci_index: i32) -> bool { if get_dispatchers().lock().unwrap().set::(Arc::new(Mutex::new(callbacks))) { diff --git a/system/gd/shim/BUILD.gn b/system/gd/shim/BUILD.gn index addc7527150..2747594cf46 100644 --- a/system/gd/shim/BUILD.gn +++ b/system/gd/shim/BUILD.gn @@ -22,7 +22,6 @@ source_set("BluetoothShimSources") { "//bt/flags:bluetooth_flags_c_lib", "//bt/system/gd/dumpsys:libbluetooth-dumpsys", "//bt/system/gd/dumpsys/bundler:BluetoothGeneratedBundlerSchema_h_bfbs", - "//bt/system/gd/rust/shim:init_flags_bridge_header", ] configs += [ diff --git a/system/hci/Android.bp b/system/hci/Android.bp index b0773d34c16..5e493288a7b 100644 --- a/system/hci/Android.bp +++ b/system/hci/Android.bp @@ -34,7 +34,6 @@ cc_library_static { header_libs: ["libbluetooth_headers"], static_libs: [ "libbluetooth_log", - "libbt_shim_bridge", ], } diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index bf53607a8da..7e891573b9e 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -687,9 +687,8 @@ typedef struct { * config file. These devices are deleted upon leaving restricted mode. * The |is_common_criteria_mode| flag inits the adapter in common criteria * mode. The |config_compare_result| flag show the config checksum check - * result if is in common criteria mode. The |init_flags| are config flags - * that cannot change during run. The |is_atv| flag indicates whether the - * local device is an Android TV + * result if is in common criteria mode. The |is_atv| flag indicates whether + * the local device is an Android TV */ int (*init)(bt_callbacks_t* callbacks, bool guest_mode, bool is_common_criteria_mode, int config_compare_result, const char** init_flags, bool is_atv, diff --git a/system/main/Android.bp b/system/main/Android.bp index f1b07c05442..62445e59e78 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -55,7 +55,6 @@ cc_library_static { "libbluetooth_gd", "libbluetooth_log", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libcom.android.sysprop.bluetooth.wrapped", ], header_libs: ["libbluetooth_headers"], @@ -149,7 +148,6 @@ cc_library_static { "bluetooth_flags_c_lib", "libbluetooth_log", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libcom.android.sysprop.bluetooth.wrapped", ], } @@ -209,14 +207,13 @@ cc_test { "libbluetooth-dumpsys", "libbluetooth-gdx", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_hci_pdl", "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", @@ -295,14 +292,13 @@ cc_test { "libbluetooth-dumpsys", "libbluetooth-gdx", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_hci_pdl", "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", diff --git a/system/main/shim/BUILD.gn b/system/main/shim/BUILD.gn index 93ac01f9926..88bbba0c6b8 100644 --- a/system/main/shim/BUILD.gn +++ b/system/main/shim/BUILD.gn @@ -24,7 +24,6 @@ source_set("BluetoothStackManagerSources") { "//bt/system", "//bt/system/btif/include", "//bt/system/gd", - "//bt/system/gd/rust/shim", "//bt/system/stack/include", "//bt/system/types", ] @@ -36,7 +35,6 @@ source_set("BluetoothStackManagerSources") { "//bt/system/gd/hci:BluetoothHciSources", "//bt/system/gd/os:BluetoothOsSources_linux_generic", "//bt/system/gd/packet:BluetoothPacketSources", - "//bt/system/gd/rust/shim:libbluetooth_rust_interop", "//bt/system/gd/rust/topshim:libbluetooth_topshim", "//bt/system/osi", "//bt/system/pdl:BluetoothGeneratedPackets_h", @@ -71,7 +69,6 @@ source_set("LibBluetoothShimSources") { "//bt/system", "//bt/system/btif/include", "//bt/system/gd", - "//bt/system/gd/rust/shim", "//bt/system/stack/include", "//bt/system/types", ] @@ -84,7 +81,6 @@ source_set("LibBluetoothShimSources") { "//bt/system/gd/hci:BluetoothHciSources", "//bt/system/gd/os:BluetoothOsSources_linux_generic", "//bt/system/gd/packet:BluetoothPacketSources", - "//bt/system/gd/rust/shim:libbluetooth_rust_interop", "//bt/system/gd/rust/topshim:libbluetooth_topshim", "//bt/system/osi", "//bt/system/pdl:BluetoothGeneratedPackets_h", diff --git a/system/osi/Android.bp b/system/osi/Android.bp index 9a9358b9b93..04e9a1f8390 100644 --- a/system/osi/Android.bp +++ b/system/osi/Android.bp @@ -92,7 +92,6 @@ cc_library_static { "libaconfig_storage_read_api_cc", "libbluetooth_log", "libbt-platform-protos-lite", - "libbt_shim_bridge", "server_configurable_flags", ], } @@ -142,8 +141,6 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", diff --git a/system/osi/BUILD.gn b/system/osi/BUILD.gn index af410b55d91..fdd2736fab4 100644 --- a/system/osi/BUILD.gn +++ b/system/osi/BUILD.gn @@ -56,7 +56,6 @@ static_library("osi") { deps = [ "//bt/flags:bluetooth_flags_c_lib", "//bt/system/common", - "//bt/system/gd/rust/shim:init_flags_bridge_header", ] configs += [ diff --git a/system/profile/avrcp/Android.bp b/system/profile/avrcp/Android.bp index 60b2947ddd3..8616ca25cf6 100644 --- a/system/profile/avrcp/Android.bp +++ b/system/profile/avrcp/Android.bp @@ -30,7 +30,6 @@ cc_library_static { "lib-bt-packets", "libbluetooth-types", "libbluetooth_log", - "libbt_shim_bridge", "libosi", ], whole_static_libs: [ @@ -81,8 +80,6 @@ cc_test { "libbluetooth-types", "libbluetooth_gd", "libbluetooth_log", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libcutils", @@ -130,8 +127,6 @@ cc_fuzz { "libbluetooth-types", "libbluetooth_gd", "libbluetooth_log", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libcutils", "libevent", diff --git a/system/profile/avrcp/BUILD.gn b/system/profile/avrcp/BUILD.gn index 84bff495f66..3305fc09485 100644 --- a/system/profile/avrcp/BUILD.gn +++ b/system/profile/avrcp/BUILD.gn @@ -40,7 +40,6 @@ static_library("profile_avrcp") { deps = [ "//bt/flags:bluetooth_flags_c_lib", - "//bt/system/gd/rust/shim:libbluetooth_rust_interop", ] configs += [ diff --git a/system/rust/Android.bp b/system/rust/Android.bp index 4281cae7aea..f3fddcd3b99 100644 --- a/system/rust/Android.bp +++ b/system/rust/Android.bp @@ -22,7 +22,6 @@ rust_defaults { "libbase", ], static_libs: [ - "libbt_shim_bridge", "libchrome", "libevent", "libmodpb64", @@ -35,7 +34,6 @@ rust_defaults { "libanyhow", "libbitflags", "libbt_common", - "libbt_shim", "libbytes", "libcxx", "liblog_rust", @@ -45,11 +43,6 @@ rust_defaults { whole_static_libs: [ "libbluetooth_core_rs_bridge", ], - features: [ - // used to hide libbt_shim in Cargo builds, but - // expose it to Soong to work around linker bug - "via_android_bp", - ], target: { android: { shared_libs: [ @@ -130,8 +123,6 @@ cc_library_static { static_libs: [ "libbluetooth_hci_pdl", "libbluetooth_log", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libflatbuffers-cpp", ], @@ -143,6 +134,7 @@ cc_library_static { "BluetoothGeneratedDumpsysDataSchema_h", ], export_generated_headers: [ + "cxx-bridge-header", "libbluetooth_core_rs_bridge_codegen_header", ], host_supported: true, diff --git a/system/rust/BUILD.gn b/system/rust/BUILD.gn index 202e9dff760..5c386e5a0f7 100644 --- a/system/rust/BUILD.gn +++ b/system/rust/BUILD.gn @@ -43,7 +43,6 @@ static_library("core_rs") { deps = [ ":cxxlibheader", - "//bt/system/gd/rust/shim:init_flags_bridge_header", "//bt/system/pdl:BluetoothGeneratedPackets_h", ] diff --git a/system/rust/src/lib.rs b/system/rust/src/lib.rs index b3361bad1e8..b8154a1cd97 100644 --- a/system/rust/src/lib.rs +++ b/system/rust/src/lib.rs @@ -26,13 +26,6 @@ use tokio::runtime::Builder; use tokio::sync::mpsc; -#[cfg(feature = "via_android_bp")] -mod do_not_use { - // DO NOT USE - #[allow(unused)] - use bt_shim::*; -} - pub mod connection; pub mod core; pub mod gatt; diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 152b866cc3e..15532a9acdd 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -21,7 +21,6 @@ cc_library_static { ], static_libs: [ "libbluetooth_log", - "libbt_shim_bridge", ], shared_libs: [ "libchrome", @@ -147,7 +146,6 @@ cc_library_static { "libbt-hci", "libbt-platform-protos-lite", "libbt-stack-core", - "libbt_shim_bridge", "liblc3", ], whole_static_libs: [ @@ -329,6 +327,7 @@ cc_library_static { ], generated_headers: [ "BluetoothGeneratedDumpsysDataSchema_h", + "cxx-bridge-header", ], cflags: [ /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ @@ -344,7 +343,6 @@ cc_library_static { "libbluetooth_log", "libbt-hci", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libcom.android.sysprop.bluetooth.wrapped", "server_configurable_flags", ], @@ -454,8 +452,6 @@ cc_fuzz { "libbluetooth-types", "libbluetooth_log", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", ], shared_libs: [ "libaconfig_storage_read_api_cc", @@ -510,14 +506,13 @@ cc_fuzz { "bluetooth_flags_c_lib", "libaconfig_storage_read_api_cc", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_hci_pdl", "libbluetooth_l2cap_pdl", "libbluetooth_log", "libbluetooth_smp_pdl", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", ], } @@ -565,14 +560,13 @@ cc_fuzz { static_libs: [ "bluetooth_flags_c_lib", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_hci_pdl", "libbluetooth_l2cap_pdl", "libbluetooth_log", "libbluetooth_smp_pdl", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", ], } @@ -621,8 +615,6 @@ cc_fuzz { "libbluetooth_smp_pdl", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libevent", ], } @@ -665,8 +657,6 @@ cc_fuzz { "libbluetooth_log", "libbluetooth_smp_pdl", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", ], } @@ -716,8 +706,6 @@ cc_fuzz { "libbluetooth_log", "libbluetooth_smp_pdl", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libcom.android.sysprop.bluetooth.wrapped", ], } @@ -760,8 +748,6 @@ cc_fuzz { "libbluetooth_log", "libbluetooth_smp_pdl", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", ], shared_libs: [ "libaconfig_storage_read_api_cc", @@ -846,7 +832,6 @@ cc_test { "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbtcore", "libbtdevice", "libbtif", @@ -952,8 +937,6 @@ cc_test { "libbt-btu-main-thread", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", @@ -1044,8 +1027,6 @@ cc_test { "libbt-btu-main-thread", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", @@ -1125,8 +1106,6 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", @@ -1179,12 +1158,11 @@ cc_test { "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", @@ -1257,8 +1235,6 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", @@ -1370,8 +1346,6 @@ cc_test { "libbt-common", "libbt-sbc-decoder", "libbt-sbc-encoder", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libgmock", "liblog", @@ -1423,7 +1397,6 @@ cc_test { "libbluetooth_crypto_toolbox", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", "libchrome", "liblog", "libosi", @@ -1482,13 +1455,12 @@ cc_test { "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", @@ -1548,7 +1520,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libchrome", "libgmock", "liblog", @@ -1625,8 +1596,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libevent", "libgmock", @@ -1750,6 +1719,7 @@ cc_test { "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", @@ -1757,8 +1727,6 @@ cc_test { "libbt-platform-protos-lite", "libbt-sbc-decoder", "libbt-sbc-encoder", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", @@ -1814,7 +1782,6 @@ cc_test { "libbluetooth_crypto_toolbox", "libbluetooth_log", "libbt-common", - "libbt_shim_bridge", "libbtdevice", "libbte", "libchrome", @@ -1874,8 +1841,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libbte", "libchrome", @@ -1954,8 +1919,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libevent", @@ -2040,13 +2003,12 @@ cc_test { "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libevent", @@ -2140,8 +2102,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libevent", @@ -2231,12 +2191,11 @@ cc_test { static_libs: [ "bluetooth_flags_c_lib", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_gd", "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libcutils", @@ -2332,6 +2291,7 @@ cc_test { "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-types", + "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", @@ -2339,8 +2299,6 @@ cc_test { "libbt-platform-protos-lite", "libbt-sbc-decoder", "libbt-sbc-encoder", - "libbt_shim_bridge", - "libbt_shim_ffi", "libbtdevice", "libchrome", "libcom.android.sysprop.bluetooth.wrapped", @@ -2411,8 +2369,6 @@ cc_test { "libbluetooth_log", "libbt-common", "libbt-platform-protos-lite", - "libbt_shim_bridge", - "libbt_shim_ffi", "libchrome", "libflagtest", "libgmock", diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn index ebb070c4ec2..cc966337c4a 100644 --- a/system/stack/BUILD.gn +++ b/system/stack/BUILD.gn @@ -40,7 +40,6 @@ source_set("nonstandard_codecs") { ] deps = [ - "//bt/system/gd/rust/shim:init_flags_bridge_header", "//bt/system/stack/mmc", ] @@ -223,9 +222,9 @@ source_set("stack") { deps = [ "//bt/sysprop:libcom.android.sysprop.bluetooth", "//bt/system/gd/crypto_toolbox:crypto_toolbox", + "//bt/system/gd/rust/topshim:cxxlibheader", ":nonstandard_codecs", "//bt/system:libbt-platform-protos-lite", - "//bt/system/gd/rust/shim:init_flags_bridge_header", "//bt/system/stack/mmc", "//bt/system/types", ] diff --git a/system/stack/mmc/codec_server/BUILD.gn b/system/stack/mmc/codec_server/BUILD.gn index a8f6b143d91..0d7a3a7f9d3 100644 --- a/system/stack/mmc/codec_server/BUILD.gn +++ b/system/stack/mmc/codec_server/BUILD.gn @@ -27,7 +27,6 @@ source_set("libcodec_server_a2dp_aac") { "//bt/system/stack/include", ] deps = [ - "//bt/system/gd/rust/shim:init_flags_bridge_header", "//bt/system/stack/mmc/proto:mmc_config_proto", ] sources = [ "a2dp_aac_mmc_encoder.cc" ] diff --git a/system/stack/test/fuzzers/Android.bp b/system/stack/test/fuzzers/Android.bp index 92de791e1b1..8d146834d61 100644 --- a/system/stack/test/fuzzers/Android.bp +++ b/system/stack/test/fuzzers/Android.bp @@ -57,7 +57,6 @@ cc_defaults { "libbt-sbc-encoder", "libbt-stack", "libbt-stack-core", - "libbt_shim_bridge", "libbtcore", "libbtdevice", "libbte", diff --git a/system/test/Android.bp b/system/test/Android.bp index 2970d10640f..a78ed4e8ef8 100644 --- a/system/test/Android.bp +++ b/system/test/Android.bp @@ -552,13 +552,6 @@ filegroup { srcs: ["common/sync_main_handler.cc"], } -filegroup { - name: "TestCommonInitFlags", - srcs: [ - "common/init_flags.cc", - ], -} - filegroup { name: "TestCommonStackConfig", srcs: [ diff --git a/system/test/common/init_flags.cc b/system/test/common/init_flags.cc deleted file mode 100644 index 97be602fe3a..00000000000 --- a/system/test/common/init_flags.cc +++ /dev/null @@ -1,17 +0,0 @@ - - -#include "common/init_flags.h" - -#include -#include - -namespace bluetooth { -namespace common { - -bool InitFlags::logging_debug_enabled_for_all = false; -std::unordered_map InitFlags::logging_debug_explicit_tag_settings = {}; -void InitFlags::Load(const char** flags) {} -void InitFlags::SetAll(bool value) { InitFlags::logging_debug_enabled_for_all = value; } - -} // namespace common -} // namespace bluetooth diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp index 3349dc607ea..9e0a234742c 100644 --- a/system/test/headless/Android.bp +++ b/system/test/headless/Android.bp @@ -88,7 +88,6 @@ cc_binary { "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", - "libbluetooth_rust_interop", "libbt-audio-asrc", "libbt-audio-hal-interface", "libbt-bta", diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc index 0ff3155258e..dd15c2a557a 100644 --- a/system/test/headless/headless.cc +++ b/system/test/headless/headless.cc @@ -258,7 +258,7 @@ void HeadlessStack::SetUp() { const bool is_atv = false; int status = bluetoothInterface.init(&bt_callbacks, start_restricted, is_common_criteria_mode, - config_compare_result, {}, is_atv, nullptr); + config_compare_result, nullptr, is_atv, nullptr); if (status == BT_STATUS_SUCCESS) { log::info("Initialized bluetooth callbacks"); diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp index ce0e3f4eb8d..c8776665d28 100644 --- a/system/test/suite/Android.bp +++ b/system/test/suite/Android.bp @@ -129,7 +129,6 @@ cc_test { "libbt-btu-main-thread", "libbt-jni-thread", "libbt-platform-protos-lite", - "libbt_shim_bridge", "libchrome", "libevent", "libflags_rust_cpp_bridge", diff --git a/system/test/suite/adapter/bluetooth_test.cc b/system/test/suite/adapter/bluetooth_test.cc index cea06fad0df..ce7f0c4479b 100644 --- a/system/test/suite/adapter/bluetooth_test.cc +++ b/system/test/suite/adapter/bluetooth_test.cc @@ -96,8 +96,8 @@ void BluetoothTest::TearDown() { } void BluetoothTest::ClearSemaphore(btsemaphore& sem) { - while (sem.try_wait()) - ; + while (sem.try_wait()) { + } } const bt_interface_t* BluetoothTest::bt_interface() { return &bluetoothInterface; } diff --git a/system/test/tool/mockcify.pl b/system/test/tool/mockcify.pl index 1f9978489e3..dadd768c056 100755 --- a/system/test/tool/mockcify.pl +++ b/system/test/tool/mockcify.pl @@ -210,7 +210,6 @@ if ($COMPILE_SCREEN_ENABLED) { sub reject_include_list { my @incs = (); foreach (@_) { - next if (/init_flags/); push(@incs, $_); } return @incs; @@ -239,7 +238,6 @@ sub compilation_screen { ## Verious external or generated header not needed for mocks foreach(( "test/mock/mock.h", - "src/init_flags.rs.h", "src/message_loop_thread.rs.h", "android/hardware/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.h", "android/hardware/bluetooth/audio/2.2/types.h", diff --git a/system/udrv/Android.bp b/system/udrv/Android.bp index 0e8be074e0c..5a69d8e886c 100644 --- a/system/udrv/Android.bp +++ b/system/udrv/Android.bp @@ -30,6 +30,5 @@ cc_library_static { header_libs: ["libbluetooth_headers"], static_libs: [ "libbluetooth_log", - "libbt_shim_bridge", ], } -- GitLab From ab4312c862ec9056b4e61b4655e1cfe0704807e1 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 2 Oct 2024 14:17:27 -0700 Subject: [PATCH 131/875] Fix build failure on acceptBluetoothBinding Bug: 311772251 Flag: TEST_ONLY Test: atest ServiceBluetoothTests Change-Id: I54cbb2f7eb9e07cbf928e8883cbccb35e2c54ea1 --- .../android/server/bluetooth/BluetoothManagerServiceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java index 80f9ea416f1..d8ad9794056 100644 --- a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java +++ b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java @@ -341,7 +341,7 @@ public class BluetoothManagerServiceTest { mManagerService.enableBle("enable_whileTurningToBleOn_shouldEnable", mBinder); syncHandler(MESSAGE_ENABLE); - acceptBluetoothBinding(mBinder, "btservice.AdapterService", 1); + acceptBluetoothBinding(); IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder); assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON); @@ -365,7 +365,7 @@ public class BluetoothManagerServiceTest { mManagerService.enable("enable_whileTurningToBleOn_shouldEnable"); syncHandler(MESSAGE_ENABLE); - acceptBluetoothBinding(mBinder, "btservice.AdapterService", 1); + acceptBluetoothBinding(); IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder); assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON); -- GitLab From 2c5add83a18d87ea4a46bc8ab7f675e32c8d6a56 Mon Sep 17 00:00:00 2001 From: Billy Huang Date: Wed, 2 Oct 2024 14:27:47 -0700 Subject: [PATCH 132/875] RESTRICT AUTOMERGE backport "opp: validate that content uri belongs to current user" Bug: 296915500 Flag: EXEMPT trivial fix with complete testing coverage Test: atest GoogleBluetoothInstrumentationTests:BluetoothOppSendFileInfoTest Ignore-AOSP-First: fix for undisclosed vulnerability Merged-In: I76b25fcd446d5e0530308e21deafa68d0b768edc Change-Id: I0b6423025c95c13eeea3cbf584212913b5fbf307 --- .../opp/BluetoothOppSendFileInfo.java | 15 +++ .../opp/BluetoothOppSendFileInfoTest.java | 107 +++++++++++++++++- 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java index 2adb8e5f44c..7ce134341aa 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java @@ -32,6 +32,8 @@ package com.android.bluetooth.opp; +import static android.os.UserHandle.myUserId; + import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; @@ -39,6 +41,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteException; import android.net.Uri; import android.provider.OpenableColumns; +import android.text.TextUtils; import android.util.EventLog; import android.util.Log; @@ -49,6 +52,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Objects; /** * This class stores information about a single sending file It will only be @@ -117,6 +121,11 @@ public class BluetoothOppSendFileInfo { return SEND_FILE_INFO_ERROR; } + if (isContentUriForOtherUser(uri)) { + Log.e(TAG, "Uri: " + uri + " is invalid for user " + myUserId()); + return SEND_FILE_INFO_ERROR; + } + contentType = contentResolver.getType(uri); Cursor metadataCursor; try { @@ -253,6 +262,12 @@ public class BluetoothOppSendFileInfo { return new BluetoothOppSendFileInfo(fileName, contentType, length, is, 0); } + private static boolean isContentUriForOtherUser(Uri uri) { + String uriUserId = uri.getUserInfo(); + return !TextUtils.isEmpty(uriUserId) + && !Objects.equals(uriUserId, String.valueOf(myUserId())); + } + private static long getStreamSize(FileInputStream is) throws IOException { long length = 0; byte[] unused = new byte[4096]; diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java index 756836afaa8..acb58272fbb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java @@ -17,6 +17,8 @@ package com.android.bluetooth.opp; +import static android.os.UserHandle.myUserId; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -31,7 +33,6 @@ import android.content.res.AssetFileDescriptor; import android.database.MatrixCursor; import android.net.Uri; import android.provider.OpenableColumns; -import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -120,6 +121,110 @@ public class BluetoothOppSendFileInfoTest { assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR); } + @Test + public void generateFileInfo_withContentUriForOtherUser_returnsSendFileInfoError() + throws Exception { + String type = "image/jpeg"; + Uri uri = buildContentUriWithEncodedAuthority((myUserId() + 1) + "@media"); + + long fileLength = 1000; + String fileName = "pic.jpg"; + + FileInputStream fs = mock(FileInputStream.class); + AssetFileDescriptor fd = mock(AssetFileDescriptor.class); + doReturn(fileLength).when(fd).getLength(); + doReturn(fs).when(fd).createInputStream(); + + doReturn(fd).when(mCallProxy).contentResolverOpenAssetFileDescriptor(any(), eq(uri), any()); + + mCursor = + new MatrixCursor(new String[] {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}); + mCursor.addRow(new Object[] {fileName, fileLength}); + + doReturn(mCursor) + .when(mCallProxy) + .contentResolverQuery(any(), eq(uri), any(), any(), any(), any()); + + BluetoothOppSendFileInfo info = + BluetoothOppSendFileInfo.generateFileInfo(mContext, uri, type, true); + + assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR); + } + + @Test + public void generateFileInfo_withContentUriForImplicitUser_returnsInfoWithCorrectLength() + throws Exception { + String type = "image/jpeg"; + Uri uri = buildContentUriWithEncodedAuthority("media"); + + long fileLength = 1000; + String fileName = "pic.jpg"; + + FileInputStream fs = mock(FileInputStream.class); + AssetFileDescriptor fd = mock(AssetFileDescriptor.class); + doReturn(fileLength).when(fd).getLength(); + doReturn(fs).when(fd).createInputStream(); + + doReturn(fd).when(mCallProxy).contentResolverOpenAssetFileDescriptor(any(), eq(uri), any()); + + mCursor = + new MatrixCursor(new String[] {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}); + mCursor.addRow(new Object[] {fileName, fileLength}); + + doReturn(mCursor) + .when(mCallProxy) + .contentResolverQuery(any(), eq(uri), any(), any(), any(), any()); + + BluetoothOppSendFileInfo info = + BluetoothOppSendFileInfo.generateFileInfo(mContext, uri, type, true); + + assertThat(info.mInputStream).isEqualTo(fs); + assertThat(info.mFileName).isEqualTo(fileName); + assertThat(info.mLength).isEqualTo(fileLength); + assertThat(info.mStatus).isEqualTo(0); + } + + @Test + public void generateFileInfo_withContentUriForSameUser_returnsInfoWithCorrectLength() + throws Exception { + String type = "image/jpeg"; + Uri uri = buildContentUriWithEncodedAuthority(myUserId() + "@media"); + + long fileLength = 1000; + String fileName = "pic.jpg"; + + FileInputStream fs = mock(FileInputStream.class); + AssetFileDescriptor fd = mock(AssetFileDescriptor.class); + doReturn(fileLength).when(fd).getLength(); + doReturn(fs).when(fd).createInputStream(); + + doReturn(fd).when(mCallProxy).contentResolverOpenAssetFileDescriptor(any(), eq(uri), any()); + + mCursor = + new MatrixCursor(new String[] {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}); + mCursor.addRow(new Object[] {fileName, fileLength}); + + doReturn(mCursor) + .when(mCallProxy) + .contentResolverQuery(any(), eq(uri), any(), any(), any(), any()); + + BluetoothOppSendFileInfo info = + BluetoothOppSendFileInfo.generateFileInfo(mContext, uri, type, true); + + assertThat(info.mInputStream).isEqualTo(fs); + assertThat(info.mFileName).isEqualTo(fileName); + assertThat(info.mLength).isEqualTo(fileLength); + assertThat(info.mStatus).isEqualTo(0); + } + + private static Uri buildContentUriWithEncodedAuthority(String authority) { + return new Uri.Builder() + .scheme("content") + .encodedAuthority(authority) + .path("external/images/media/1") + .build(); + } + @Test public void generateFileInfo_withoutPermissionForAccessingUri_returnsSendFileInfoError() { String type = "text/plain"; -- GitLab From 5bcfd347823f1d3893d843db2286f2013923fad8 Mon Sep 17 00:00:00 2001 From: Billy Huang Date: Wed, 2 Oct 2024 14:45:37 -0700 Subject: [PATCH 133/875] RESTRICT AUTOMERGE backport "opp: validate that content uri belongs to current user" Bug: 296915500 Flag: EXEMPT trivial fix with complete testing coverage Test: atest GoogleBluetoothInstrumentationTests:BluetoothOppSendFileInfoTest Ignore-AOSP-First: fix for undisclosed vulnerability Merged-In: I76b25fcd446d5e0530308e21deafa68d0b768edc Change-Id: Ibff36089bfde4b5bb28d797aeae1423b668943a2 --- .../opp/BluetoothOppSendFileInfo.java | 15 ++ .../opp/BluetoothOppSendFileInfoTest.java | 205 ++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java index 46e3ba144e7..10087c9f16c 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java @@ -32,6 +32,8 @@ package com.android.bluetooth.opp; +import static android.os.UserHandle.myUserId; + import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; @@ -39,6 +41,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteException; import android.net.Uri; import android.provider.OpenableColumns; +import android.text.TextUtils; import android.util.EventLog; import android.util.Log; @@ -48,6 +51,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Objects; /** * This class stores information about a single sending file It will only be @@ -116,6 +120,11 @@ public class BluetoothOppSendFileInfo { return SEND_FILE_INFO_ERROR; } + if (isContentUriForOtherUser(uri)) { + Log.e(TAG, "Uri: " + uri + " is invalid for user " + myUserId()); + return SEND_FILE_INFO_ERROR; + } + contentType = contentResolver.getType(uri); Cursor metadataCursor; try { @@ -247,6 +256,12 @@ public class BluetoothOppSendFileInfo { return new BluetoothOppSendFileInfo(fileName, contentType, length, is, 0); } + private static boolean isContentUriForOtherUser(Uri uri) { + String uriUserId = uri.getUserInfo(); + return !TextUtils.isEmpty(uriUserId) + && !Objects.equals(uriUserId, String.valueOf(myUserId())); + } + private static long getStreamSize(FileInputStream is) throws IOException { long length = 0; byte[] unused = new byte[4096]; diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java new file mode 100644 index 00000000000..9fb93ac9683 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java @@ -0,0 +1,205 @@ +/* + * 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. + */ +package com.android.bluetooth.opp; + +import static android.os.UserHandle.myUserId; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.IContentProvider; +import android.content.pm.ApplicationInfo; +import android.content.res.AssetFileDescriptor; +import android.database.MatrixCursor; +import android.net.Uri; +import android.os.Build; +import android.provider.OpenableColumns; +import android.test.mock.MockContentProvider; +import android.test.mock.MockContext; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.FileInputStream; + +@RunWith(AndroidJUnit4.class) +public class BluetoothOppSendFileInfoTest { + public static final String PROVIDER_NAME_MEDIA = "media"; + TestContext mContext; + TestContentResolver mContentResolver; + MockContentProvider mContentProvider; + MatrixCursor mCursor; + + private static Uri buildContentUriWithEncodedAuthority(String authority) { + return new Uri.Builder().scheme("content") + .encodedAuthority(authority) + .path("external/images/media/1") + .build(); + } + + @Before + public void setUp() { + mContext = new TestContext(); + mContentResolver = mContext.getContentResolver(); + mContentProvider = mContext.getContentProvider(); + } + + @Test + public void generateFileInfo_withContentUriForOtherUser_returnsSendFileInfoError() + throws Exception { + String type = "image/jpeg"; + Uri uri = buildContentUriWithEncodedAuthority((myUserId() + 1) + "@" + PROVIDER_NAME_MEDIA); + doReturn(type).when(mContentProvider).getType(any()); + long fileLength = 1000; + String fileName = "pic.jpg"; + FileInputStream fs = mock(FileInputStream.class); + AssetFileDescriptor fd = mock(AssetFileDescriptor.class); + doReturn(fileLength).when(fd).getLength(); + doReturn(fs).when(fd).createInputStream(); + doReturn(fd).when(mContentProvider).openAssetFile(eq(uri), any(), any()); + mCursor = + new MatrixCursor(new String[]{OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}); + mCursor.addRow(new Object[]{fileName, fileLength}); + doReturn(mCursor).when(mContentProvider).query(eq(uri), any(), any(), any(), any()); + BluetoothOppSendFileInfo info = + BluetoothOppSendFileInfo.generateFileInfo(mContext, uri, type, true); + assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR); + } + + @Test + public void generateFileInfo_withContentUriForImplicitUser_returnsInfoWithCorrectLength() + throws Exception { + String type = "image/jpeg"; + Uri uri = buildContentUriWithEncodedAuthority(PROVIDER_NAME_MEDIA); + doReturn(type).when(mContentProvider).getType(any()); + long fileLength = 1000; + String fileName = "pic.jpg"; + FileInputStream fs = mock(FileInputStream.class); + AssetFileDescriptor fd = mock(AssetFileDescriptor.class); + doReturn(fileLength).when(fd).getLength(); + doReturn(fs).when(fd).createInputStream(); + doReturn(fd).when(mContentProvider).openAssetFile(eq(uri), any(), any()); + mCursor = + new MatrixCursor(new String[]{OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}); + mCursor.addRow(new Object[]{fileName, fileLength}); + doReturn(mCursor).when(mContentProvider).query(eq(uri), any(), any(), any(), any()); + BluetoothOppSendFileInfo info = + BluetoothOppSendFileInfo.generateFileInfo(mContext, uri, type, true); + assertThat(info.mInputStream).isEqualTo(fs); + assertThat(info.mFileName).isEqualTo(fileName); + assertThat(info.mLength).isEqualTo(fileLength); + assertThat(info.mStatus).isEqualTo(0); + } + + @Test + public void generateFileInfo_withContentUriForSameUser_returnsInfoWithCorrectLength() + throws Exception { + String type = "image/jpeg"; + Uri uri = buildContentUriWithEncodedAuthority(myUserId() + "@" + PROVIDER_NAME_MEDIA); + doReturn(type).when(mContentProvider).getType(any()); + long fileLength = 1000; + String fileName = "pic.jpg"; + FileInputStream fs = mock(FileInputStream.class); + AssetFileDescriptor fd = mock(AssetFileDescriptor.class); + doReturn(fileLength).when(fd).getLength(); + doReturn(fs).when(fd).createInputStream(); + doReturn(fd).when(mContentProvider).openAssetFile(eq(uri), any(), any()); + mCursor = + new MatrixCursor(new String[]{OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}); + mCursor.addRow(new Object[]{fileName, fileLength}); + doReturn(mCursor).when(mContentProvider).query(eq(uri), any(), any(), any(), any()); + BluetoothOppSendFileInfo info = + BluetoothOppSendFileInfo.generateFileInfo(mContext, uri, type, true); + assertThat(info.mInputStream).isEqualTo(fs); + assertThat(info.mFileName).isEqualTo(fileName); + assertThat(info.mLength).isEqualTo(fileLength); + assertThat(info.mStatus).isEqualTo(0); + } + + public static final class TestContext extends MockContext { + private final TestContentResolver mContentResolver; + private final MockContentProvider mContentProvider; + + public TestContext() { + mContentProvider = spy(new MockContentProvider(this)); + mContentResolver = new TestContentResolver(this, mContentProvider); + } + + @Override + public TestContentResolver getContentResolver() { + return mContentResolver; + } + + public MockContentProvider getContentProvider() { + return mContentProvider; + } + + @Override + public String getOpPackageName() { + return "test.package"; + } + + @Override + public ApplicationInfo getApplicationInfo() { + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.targetSdkVersion = Build.VERSION.SDK_INT; + return applicationInfo; + } + } + + public static final class TestContentResolver extends ContentResolver { + private final MockContentProvider mContentProvider; + + public TestContentResolver(Context context, MockContentProvider contentProvider) { + super(context, contentProvider); + mContentProvider = contentProvider; + } + + @Override + protected IContentProvider acquireProvider(Context c, String name) { + return mContentProvider.getIContentProvider(); + } + + @Override + public boolean releaseProvider(IContentProvider icp) { + return true; + } + + @Override + protected IContentProvider acquireUnstableProvider(Context c, String name) { + return mContentProvider.getIContentProvider(); + } + + @Override + public boolean releaseUnstableProvider(IContentProvider icp) { + return true; + } + + @Override + public void unstableProviderDied(IContentProvider icp) { + } + } +} -- GitLab From 145b8b9082324b0e7bd9db9a5280b9315c34e4de Mon Sep 17 00:00:00 2001 From: Jayden Kim Date: Thu, 3 Oct 2024 00:08:40 +0000 Subject: [PATCH 134/875] Add copyright and fix cpplint error Bug: 342012881 Test: m com.android.btservices Change-Id: Ibf3014f6e3ccf88067b1c9c4f7e7f4bcdf67b7ff --- system/btif/include/btif_sock_l2cap.h | 16 ++++++++++++++++ system/btif/src/btif_sock.cc | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/system/btif/include/btif_sock_l2cap.h b/system/btif/include/btif_sock_l2cap.h index d527ed8347a..c08ef532d7f 100644 --- a/system/btif/include/btif_sock_l2cap.h +++ b/system/btif/include/btif_sock_l2cap.h @@ -1,3 +1,19 @@ +/* + * 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. + */ + /******************************************************************************* * L2CAP Socket Interface ******************************************************************************/ diff --git a/system/btif/src/btif_sock.cc b/system/btif/src/btif_sock.cc index 95f27891376..04b43dda0e6 100644 --- a/system/btif/src/btif_sock.cc +++ b/system/btif/src/btif_sock.cc @@ -114,7 +114,7 @@ bt_status_t btif_sock_init(uid_set_t* uid_set) { return BT_STATUS_SUCCESS; -error:; +error: thread_free(thread); thread = NULL; if (thread_handle != -1) { -- GitLab From eb065ba6ca3acc327541f36838782decad987bf3 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 2 Oct 2024 23:09:55 +0000 Subject: [PATCH 135/875] system/btif: Fix -Wmissing-prototypes errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor fixes Change-Id: Iee711ff3e996fb095722c80c0037fe1e13172fad --- system/bta/dm/bta_dm_act.cc | 2 -- system/btif/include/btif_acl.h | 21 ---------------- system/btif/include/btif_dm.h | 24 ++++++++++++++----- system/btif/include/btif_sdp.h | 6 ++++- system/btif/src/bluetooth.cc | 1 - system/btif/src/btif_core.cc | 6 ----- system/btif/src/btif_dm.cc | 32 ++++++++++--------------- system/btif/src/btif_gatt_client.cc | 4 +--- system/btif/src/btif_gatt_server.cc | 4 +--- system/btif/src/btif_hd.cc | 7 +++--- system/btif/src/btif_hh.cc | 15 +++--------- system/btif/src/btif_profile_storage.cc | 2 -- system/btif/src/btif_rc.cc | 1 - system/btif/src/btif_sdp.cc | 5 ++-- system/btif/test/btif_dm_test.cc | 17 ++----------- system/stack/btm/btm_inq.cc | 2 +- system/test/mock/mock_btif_dm.cc | 8 ------- 17 files changed, 48 insertions(+), 109 deletions(-) delete mode 100644 system/btif/include/btif_acl.h diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index f908268bdcf..1d1d5c589de 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -73,8 +73,6 @@ using bluetooth::Uuid; using namespace bluetooth; bool ble_vnd_is_included(); -void BTIF_dm_disable(); -void BTIF_dm_enable(); void btm_ble_scanner_init(void); static void bta_dm_check_av(); diff --git a/system/btif/include/btif_acl.h b/system/btif/include/btif_acl.h deleted file mode 100644 index cab40b43f66..00000000000 --- a/system/btif/include/btif_acl.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2020 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 "stack/include/acl_api_types.h" - -void BTIF_dm_report_inquiry_status_change(tBTM_INQUIRY_STATE inquiry_state); diff --git a/system/btif/include/btif_dm.h b/system/btif/include/btif_dm.h index 5db8b50d47e..15a5bfa1ae4 100644 --- a/system/btif/include/btif_dm.h +++ b/system/btif/include/btif_dm.h @@ -16,8 +16,7 @@ * ******************************************************************************/ -#ifndef BTIF_DM_H -#define BTIF_DM_H +#pragma once #include "bta/include/bta_api.h" #include "bta/include/bta_sec_api.h" @@ -25,6 +24,7 @@ #include "hci/le_rand_callback.h" #include "internal_include/bt_target.h" #include "internal_include/bte_appl.h" +#include "stack/include/acl_api_types.h" #include "types/raw_address.h" /******************************************************************************* @@ -97,13 +97,12 @@ bool btif_dm_proc_rmt_oob(const RawAddress& bd_addr, Octet16* p_c, Octet16* p_r) void btif_dm_generate_local_oob_data(tBT_TRANSPORT transport); void btif_check_device_in_inquiry_db(const RawAddress& address); +bool btif_get_address_type(const RawAddress& bda, tBLE_ADDR_TYPE* p_addr_type); +bool btif_get_device_type(const RawAddress& bda, int* p_device_type); void btif_dm_clear_event_filter(); - void btif_dm_clear_event_mask(); - void btif_dm_clear_filter_accept_list(); - void btif_dm_disconnect_all_acls(); void btif_dm_le_rand(bluetooth::hci::LeRandCallback callback); @@ -121,6 +120,12 @@ void btif_dm_hh_open_failed(RawAddress* bdaddr); /*callout for reading SMP properties from Text file*/ bool btif_dm_get_smp_config(tBTE_APPL_CFG* p_cfg); +void btif_dm_enable_service(tBTA_SERVICE_ID service_id, bool enable); + +void BTIF_dm_disable(); +void BTIF_dm_enable(); +void BTIF_dm_report_inquiry_status_change(tBTM_INQUIRY_STATE inquiry_state); + typedef struct { bool is_penc_key_rcvd; tBTM_LE_PENC_KEYS penc_key; /* received peer encryption key */ @@ -150,4 +155,11 @@ bool check_cod_hid(const RawAddress& bd_addr); bool check_cod_hid_major(const RawAddress& bd_addr, uint32_t cod); bool is_device_le_audio_capable(const RawAddress bd_addr); bool is_le_audio_capable_during_service_discovery(const RawAddress& bd_addr); -#endif + +namespace bluetooth::legacy::testing { +void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time, tBTM_BLE_RX_TIME_MS rx_time, + tBTM_BLE_IDLE_TIME_MS idle_time, tBTM_BLE_ENERGY_USED energy_used, + tBTM_CONTRL_STATE ctrl_state, tBTA_STATUS status); +void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, const BD_NAME bd_name, + bool during_device_search); +} // namespace bluetooth::legacy::testing diff --git a/system/btif/include/btif_sdp.h b/system/btif/include/btif_sdp.h index 9f0daed3979..c1d719a3885 100644 --- a/system/btif/include/btif_sdp.h +++ b/system/btif/include/btif_sdp.h @@ -29,6 +29,10 @@ #include -btsdp_interface_t* btif_sdp_get_interface(); +const btsdp_interface_t* btif_sdp_get_interface(); +bt_status_t btif_sdp_execute_service(bool b_enable); + +bt_status_t sdp_server_init(); +void sdp_server_cleanup(); #endif diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 46c04cc4769..7096b4315a4 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -195,7 +195,6 @@ extern VolumeControlInterface* btif_volume_control_get_interface(); bt_status_t btif_av_sink_execute_service(bool b_enable); bt_status_t btif_hh_execute_service(bool b_enable); bt_status_t btif_hf_client_execute_service(bool b_enable); -bt_status_t btif_sdp_execute_service(bool b_enable); bt_status_t btif_hd_execute_service(bool b_enable); extern void gatt_tcb_dump(int fd); diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index c73a5cea06a..c6e277c3c14 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -109,12 +109,6 @@ static uint8_t btif_dut_mode = 0; static base::AtExitManager* exit_manager; static uid_set_t* uid_set; -/******************************************************************************* - * Externs - ******************************************************************************/ -void btif_dm_enable_service(tBTA_SERVICE_ID service_id, bool enable); -void btif_dm_load_local_oob(void); - /******************************************************************************* * * Function btif_is_dut_mode diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index f08036de9eb..082dded39db 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -61,6 +61,7 @@ #include "btif_config.h" #include "btif_dm.h" #include "btif_metrics_logging.h" +#include "btif_sdp.h" #include "btif_storage.h" #include "btif_util.h" #include "common/lru_cache.h" @@ -105,12 +106,6 @@ #include #endif -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -bool btif_get_address_type(const RawAddress& bda, tBLE_ADDR_TYPE* p_addr_type); -bool btif_get_device_type(const RawAddress& bda, int* p_device_type); - using bluetooth::Uuid; using namespace bluetooth; @@ -297,7 +292,6 @@ static void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, co /****************************************************************************** * Externs *****************************************************************************/ -bt_status_t btif_sdp_execute_service(bool b_enable); void btif_iot_update_remote_info(tBTA_DM_AUTH_CMPL* p_auth_cmpl, bool is_ble, bool is_ssp); /****************************************************************************** @@ -323,7 +317,7 @@ void btif_dm_cleanup(void) { } } -bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id, bool b_enable) { +static bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id, bool b_enable) { log::verbose("service_id:{}", service_id); if (service_id == BTA_SDP_SERVICE_ID) { @@ -496,14 +490,10 @@ static uint32_t get_cod(const RawAddress* remote_bdaddr) { return remote_cod; } -bool check_cod(const RawAddress* remote_bdaddr, uint32_t cod) { +static bool check_cod(const RawAddress* remote_bdaddr, uint32_t cod) { return (get_cod(remote_bdaddr) & COD_DEVICE_MASK) == cod; } -bool check_cod_hid(const RawAddress* remote_bdaddr) { - return (get_cod(remote_bdaddr) & COD_HID_MASK) == COD_HID_MAJOR; -} - bool check_cod_hid(const RawAddress& bd_addr) { return (get_cod(&bd_addr) & COD_HID_MASK) == COD_HID_MAJOR; } @@ -514,9 +504,10 @@ bool check_cod_hid_major(const RawAddress& bd_addr, uint32_t cod) { (remote_cod & COD_HID_SUB_MAJOR) == (cod & COD_HID_SUB_MAJOR); } -bool check_cod_le_audio(const RawAddress& bd_addr) { +static bool check_cod_le_audio(const RawAddress& bd_addr) { return (get_cod(&bd_addr) & COD_CLASS_LE_AUDIO) == COD_CLASS_LE_AUDIO; } + /***************************************************************************** * * Function check_sdp_bl @@ -1183,7 +1174,7 @@ static void btif_dm_auth_cmpl_evt(tBTA_DM_AUTH_CMPL* p_auth_cmpl) { state = BT_BOND_STATE_BONDED; bd_addr = p_auth_cmpl->bd_addr; - if (check_sdp_bl(&bd_addr) && check_cod_hid(&bd_addr)) { + if (check_sdp_bl(&bd_addr) && check_cod_hid(bd_addr)) { log::warn("skip SDP"); skip_sdp = true; } @@ -1717,8 +1708,8 @@ static void btif_on_service_discovery_results(RawAddress bd_addr, } } -void btif_on_gatt_results(RawAddress bd_addr, std::vector& services, - bool is_transport_le) { +static void btif_on_gatt_results(RawAddress bd_addr, std::vector& services, + bool is_transport_le) { std::vector prop; std::vector property_value; std::set uuids; @@ -1892,13 +1883,14 @@ static void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, co } } -void btif_on_name_read_from_btm(const RawAddress& bd_addr, DEV_CLASS /* dc */, BD_NAME bd_name) { +static void btif_on_name_read_from_btm(const RawAddress& bd_addr, DEV_CLASS /* dc */, + BD_NAME bd_name) { log::info("{} {}", bd_addr, reinterpret_cast(bd_name)); btif_on_name_read(bd_addr, HCI_SUCCESS, bd_name, false /* during_device_search */); } -void btif_on_did_received(RawAddress bd_addr, uint8_t vendor_id_src, uint16_t vendor_id, - uint16_t product_id, uint16_t version) { +static void btif_on_did_received(RawAddress bd_addr, uint8_t vendor_id_src, uint16_t vendor_id, + uint16_t product_id, uint16_t version) { bt_vendor_product_info_t vp_info{ .vendor_id_src = vendor_id_src, .vendor_id = vendor_id, diff --git a/system/btif/src/btif_gatt_client.cc b/system/btif/src/btif_gatt_client.cc index e7276bb34e9..a873664183f 100644 --- a/system/btif/src/btif_gatt_client.cc +++ b/system/btif/src/btif_gatt_client.cc @@ -43,6 +43,7 @@ #include "bta/include/bta_sec_api.h" #include "btif/include/btif_common.h" #include "btif/include/btif_config.h" +#include "btif/include/btif_dm.h" #include "btif/include/btif_gatt.h" #include "btif/include/btif_gatt_util.h" #include "hci/controller_interface.h" @@ -68,9 +69,6 @@ using bluetooth::Uuid; using namespace bluetooth; using std::vector; -bool btif_get_address_type(const RawAddress& bda, tBLE_ADDR_TYPE* p_addr_type); -bool btif_get_device_type(const RawAddress& bda, int* p_device_type); - static bt_status_t btif_gattc_test_command_impl(int command, const btgatt_test_params_t* params); extern const btgatt_callbacks_t* bt_gatt_callbacks; diff --git a/system/btif/src/btif_gatt_server.cc b/system/btif/src/btif_gatt_server.cc index fab86d75798..558148e427b 100644 --- a/system/btif/src/btif_gatt_server.cc +++ b/system/btif/src/btif_gatt_server.cc @@ -38,6 +38,7 @@ #include "bta/include/bta_gatt_api.h" #include "bta/include/bta_sec_api.h" #include "btif/include/btif_common.h" +#include "btif/include/btif_dm.h" #include "btif/include/btif_gatt.h" #include "btif/include/btif_gatt_util.h" #include "osi/include/allocator.h" @@ -49,9 +50,6 @@ #include "types/bt_transport.h" #include "types/raw_address.h" -bool btif_get_address_type(const RawAddress& bda, tBLE_ADDR_TYPE* p_addr_type); -bool btif_get_device_type(const RawAddress& bda, int* p_device_type); - using base::Bind; using bluetooth::Uuid; using std::vector; diff --git a/system/btif/src/btif_hd.cc b/system/btif/src/btif_hd.cc index 742e9fd87e3..1ddc10fc509 100644 --- a/system/btif/src/btif_hd.cc +++ b/system/btif/src/btif_hd.cc @@ -37,6 +37,7 @@ #include "bta/sys/bta_sys.h" #include "bta_sec_api.h" #include "btif/include/btif_common.h" +#include "btif/include/btif_dm.h" #include "btif/include/btif_profile_storage.h" #include "btif/include/btif_util.h" #include "include/hardware/bt_hd.h" @@ -61,8 +62,6 @@ using namespace bluetooth; bool bta_dm_check_if_only_hd_connected(const RawAddress& peer_addr); -bool check_cod_hid(const RawAddress* remote_bdaddr); -bool check_cod_hid(const RawAddress& bd_addr); void btif_hh_service_registration(bool enable); /* HD request events */ @@ -222,8 +221,8 @@ static void btif_hd_upstreams_evt(uint16_t event, char* p_param) { break; case BTA_HD_OPEN_EVT: { - RawAddress* addr = (RawAddress*)&p_data->conn.bda; - log::warn("BTA_HD_OPEN_EVT, address={}", *addr); + RawAddress& addr = p_data->conn.bda; + log::warn("BTA_HD_OPEN_EVT, address={}", addr); /* Check if the connection is from hid host and not hid device */ if (check_cod_hid(addr)) { /* Incoming connection from hid device, reject it */ diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index 93720f51823..4a4bddd266f 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -143,17 +143,8 @@ static tHID_KB_LIST hid_kb_numlock_on_list[] = { ******************************************************************************/ static void btif_hh_transport_select(tAclLinkSpec& link_spec); - -/******************************************************************************* - * Externs - ******************************************************************************/ - -bool check_cod(const RawAddress* remote_bdaddr, uint32_t cod); -bool check_cod_hid(const RawAddress* remote_bdaddr); -bool check_cod_hid_major(const RawAddress& bd_addr, uint32_t cod); - -static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data); static void btif_hh_timer_timeout(void* data); +static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data); /******************************************************************************* * Functions @@ -870,7 +861,7 @@ static void hh_vc_unplug_handler(tBTA_HH_CBDATA& dev_status) { BTHH_STATE_UPDATE(p_dev->link_spec, p_dev->dev_status); if (!com::android::bluetooth::flags::remove_input_device_on_vup()) { - if (p_dev->local_vup || check_cod_hid(&(p_dev->link_spec.addrt.bda))) { + if (p_dev->local_vup || check_cod_hid(p_dev->link_spec.addrt.bda)) { p_dev->local_vup = false; BTA_DmRemoveDevice(p_dev->link_spec.addrt.bda); } else { @@ -890,7 +881,7 @@ static void hh_vc_unplug_handler(tBTA_HH_CBDATA& dev_status) { // Remove the HID device btif_hh_remove_device(p_dev->link_spec); - if (p_dev->local_vup || check_cod_hid(&(p_dev->link_spec.addrt.bda))) { + if (p_dev->local_vup || check_cod_hid(p_dev->link_spec.addrt.bda)) { // Remove the bond if locally initiated or remote device has major class HID p_dev->local_vup = false; BTA_DmRemoveDevice(p_dev->link_spec.addrt.bda); diff --git a/system/btif/src/btif_profile_storage.cc b/system/btif/src/btif_profile_storage.cc index 4c5fad6734e..d0949d6af1c 100644 --- a/system/btif/src/btif_profile_storage.cc +++ b/system/btif/src/btif_profile_storage.cc @@ -385,8 +385,6 @@ static bool btif_device_supports_classic_hid(const std::string& device) { * ******************************************************************************/ -bool btif_get_address_type(const RawAddress& bda, tBLE_ADDR_TYPE* p_addr_type); - std::vector> btif_storage_get_le_hid_devices(void) { std::vector> hid_addresses; for (const auto& bd_addr : btif_config_get_paired_devices()) { diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index 4eaf0e61e8a..5c82b54280b 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -375,7 +375,6 @@ static const uint8_t media_attr_list_no_cover_art_size = /***************************************************************************** * Externs *****************************************************************************/ -bool check_cod(const RawAddress& remote_bdaddr, uint32_t cod); void btif_rc_get_addr_by_handle(uint8_t handle, RawAddress& rc_addr) { log::verbose("handle: 0x{:x}", handle); diff --git a/system/btif/src/btif_sdp.cc b/system/btif/src/btif_sdp.cc index db75f5eac1b..a7e61c3c038 100644 --- a/system/btif/src/btif_sdp.cc +++ b/system/btif/src/btif_sdp.cc @@ -28,6 +28,8 @@ #define LOG_TAG "bt_btif_sdp" +#include "btif/include/btif_sdp.h" + #include #include #include @@ -40,9 +42,6 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/btif/test/btif_dm_test.cc b/system/btif/test/btif_dm_test.cc index 9d1a3d5e696..5d7595b1c5b 100644 --- a/system/btif/test/btif_dm_test.cc +++ b/system/btif/test/btif_dm_test.cc @@ -41,22 +41,9 @@ const RawAddress kRawAddress = {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; constexpr char kBdName[] = {'k', 'B', 'd', 'N', 'a', 'm', 'e', '\0'}; } // namespace -namespace bluetooth { -namespace legacy { -namespace testing { - +namespace bluetooth::legacy::testing { void set_interface_to_profiles(bluetooth::core::CoreInterface* interfaceToProfiles); - -void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time, tBTM_BLE_RX_TIME_MS rx_time, - tBTM_BLE_IDLE_TIME_MS idle_time, tBTM_BLE_ENERGY_USED energy_used, - tBTM_CONTRL_STATE ctrl_state, tBTA_STATUS status); - -void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, const BD_NAME bd_name, - bool during_device_search); - -} // namespace testing -} // namespace legacy -} // namespace bluetooth +} // namespace bluetooth::legacy::testing namespace { constexpr tBTM_BLE_TX_TIME_MS tx_time = 0x12345678; diff --git a/system/stack/btm/btm_inq.cc b/system/stack/btm/btm_inq.cc index 255b9cb69bc..b5456963d45 100644 --- a/system/stack/btm/btm_inq.cc +++ b/system/stack/btm/btm_inq.cc @@ -35,7 +35,7 @@ #include -#include "btif/include/btif_acl.h" +#include "btif/include/btif_dm.h" #include "common/time_util.h" #include "hci/controller_interface.h" #include "hci/event_checkers.h" diff --git a/system/test/mock/mock_btif_dm.cc b/system/test/mock/mock_btif_dm.cc index f4baf57ea1c..cc3bf79edd3 100644 --- a/system/test/mock/mock_btif_dm.cc +++ b/system/test/mock/mock_btif_dm.cc @@ -40,14 +40,6 @@ bool btif_dm_pairing_is_busy() { inc_func_call_count(__func__); return false; } -bool check_cod(const RawAddress* /* remote_bdaddr */, uint32_t /* cod */) { - inc_func_call_count(__func__); - return false; -} -bool check_cod_hid(const RawAddress* /* remote_bdaddr */) { - inc_func_call_count(__func__); - return false; -} bool check_cod_hid(const RawAddress& /* remote_bdaddr */) { inc_func_call_count(__func__); return false; -- GitLab From 144c8fa13858913b5649d2217578c0c5c0b8b0e7 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 2 Oct 2024 17:36:28 -0700 Subject: [PATCH 136/875] Move adapter flag outside of system_service Bug: 366432079 Flag: com.android.bluetooth.flags.adapter_suspend_mgmt Test: m . Change-Id: I0ceb7046648341c7bccd966353b8faeda10fe1a0 --- flags/Android.bp | 1 + flags/BUILD.gn | 1 + flags/adapter.aconfig | 9 +++++++++ flags/system_service.aconfig | 7 ------- 4 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 flags/adapter.aconfig diff --git a/flags/Android.bp b/flags/Android.bp index b619319c915..db47305e1e1 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -11,6 +11,7 @@ aconfig_declarations { srcs: [ "a2dp.aconfig", "active_device_manager.aconfig", + "adapter.aconfig", "asha.aconfig", "audio_routing.aconfig", "avrcp.aconfig", diff --git a/flags/BUILD.gn b/flags/BUILD.gn index fcc28552d3d..97ad76af503 100644 --- a/flags/BUILD.gn +++ b/flags/BUILD.gn @@ -5,6 +5,7 @@ aconfig("bluetooth_flags_c_lib") { sources = [ "a2dp.aconfig", "active_device_manager.aconfig", + "adapter.aconfig", "asha.aconfig", "audio_routing.aconfig", "avrcp.aconfig", diff --git a/flags/adapter.aconfig b/flags/adapter.aconfig new file mode 100644 index 00000000000..6fb5963a0cb --- /dev/null +++ b/flags/adapter.aconfig @@ -0,0 +1,9 @@ +package: "com.android.bluetooth.flags" +container: "com.android.btservices" + +flag { + name: "adapter_suspend_mgmt" + namespace: "bluetooth" + description: "Configure the BT adapter in a suspend state to avoid unexpected wake-up" + bug: "366432079" +} diff --git a/flags/system_service.aconfig b/flags/system_service.aconfig index df29c6f3af6..1c40504d979 100644 --- a/flags/system_service.aconfig +++ b/flags/system_service.aconfig @@ -84,10 +84,3 @@ flag { description: "Replace binder call to the system server with a Messenger to enforce thread safety" bug: "321804999" } - -flag { - name: "adapter_suspend_mgmt" - namespace: "bluetooth" - description: "Configure the BT adapter in a suspend state to avoid unexpected wake-up" - bug: "366432079" -} -- GitLab From 0c4f06b748ef7f3cc7b32f0d86395ffa3a894231 Mon Sep 17 00:00:00 2001 From: Wenyu Zhang Date: Thu, 3 Oct 2024 00:43:30 +0000 Subject: [PATCH 137/875] Inform AudioManager when hfp is disconnected Otherwise, the hfp device is always available in Audio framework even after the BT device is disconnected. Change-Id: Id410ff471244e034b4aba0edb1c4467cd4b11d42 Bug: b/370799841, b/355684672 Test: atest HeadsetServiceTest Flag: Exempt bugfixes --- .../src/com/android/bluetooth/hfp/HeadsetService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index 15f16e379b1..26b83a1892a 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -1395,6 +1395,17 @@ public class HeadsetService extends ProfileService { + disconnectStatus); } } + + // Make sure the Audio Manager knows the previous active device is no longer active. + if (Utils.isScoManagedByAudioEnabled()) { + mSystemInterface + .getAudioManager() + .handleBluetoothActiveDeviceChanged( + null, + mActiveDevice, + BluetoothProfileConnectionInfo.createHfpInfo()); + } + mActiveDevice = null; mNativeInterface.setActiveDevice(null); broadcastActiveDevice(null); -- GitLab From 9369d1cabbd46bef5a09bf30cfba1f715acc2d28 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 3 Oct 2024 01:25:53 +0000 Subject: [PATCH 138/875] system/btif: Fix -Wmissing-prototypes errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor fixes Change-Id: I53bf7520860a7d348298f1b85d75f3da8f6844d7 --- system/btif/include/btif_hf_client.h | 25 +++++++++++++++++ system/btif/src/bluetooth.cc | 4 +-- system/btif/src/btif_hf.cc | 13 ++++----- system/btif/src/btif_hf_client.cc | 40 +++++----------------------- 4 files changed, 38 insertions(+), 44 deletions(-) create mode 100644 system/btif/include/btif_hf_client.h diff --git a/system/btif/include/btif_hf_client.h b/system/btif/include/btif_hf_client.h new file mode 100644 index 00000000000..72090e3c515 --- /dev/null +++ b/system/btif/include/btif_hf_client.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * + * Copyright 2024 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: + * + * 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 +#include + +const bthf_client_interface_t* btif_hf_client_get_interface(); +bt_status_t btif_hf_client_execute_service(bool b_enable); diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 7096b4315a4..aeeb450a21c 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -70,6 +70,7 @@ #include "btif/include/btif_dm.h" #include "btif/include/btif_hd.h" #include "btif/include/btif_hf.h" +#include "btif/include/btif_hf_client.h" #include "btif/include/btif_hh.h" #include "btif/include/btif_keystore.h" #include "btif/include/btif_metrics_logging.h" @@ -161,8 +162,6 @@ bool is_local_device_atv = false; /* list all extended interfaces here */ -/* handsfree profile - client */ -extern const bthf_client_interface_t* btif_hf_client_get_interface(); /*rfc l2cap*/ extern const btsock_interface_t* btif_sock_get_interface(); /* hid host profile */ @@ -194,7 +193,6 @@ extern VolumeControlInterface* btif_volume_control_get_interface(); bt_status_t btif_av_sink_execute_service(bool b_enable); bt_status_t btif_hh_execute_service(bool b_enable); -bt_status_t btif_hf_client_execute_service(bool b_enable); bt_status_t btif_hd_execute_service(bool b_enable); extern void gatt_tcb_dump(int fd); diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index fb93ac1508a..317c00e2f3a 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -27,6 +27,8 @@ #define LOG_TAG "bt_btif_hf" +#include "btif/include/btif_hf.h" + #include #include #include @@ -55,15 +57,11 @@ #include "stack/include/btm_log_history.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace { constexpr char kBtmLogTag[] = "HFP"; } -namespace bluetooth { -namespace headset { +namespace bluetooth::headset { /******************************************************************************* * Constants & Macros @@ -271,7 +269,7 @@ static bool is_nth_bit_enabled(uint32_t value, int n) { return (value & (static_cast(1) << n)) != 0; } -void clear_phone_state_multihf(btif_hf_cb_t* hf_cb) { +static void clear_phone_state_multihf(btif_hf_cb_t* hf_cb) { hf_cb->call_setup_state = BTHF_CALL_STATE_IDLE; hf_cb->num_active = 0; hf_cb->num_held = 0; @@ -1622,5 +1620,4 @@ Interface* GetInterface() { return HeadsetInterface::GetInstance(); } -} // namespace headset -} // namespace bluetooth +} // namespace bluetooth::headset diff --git a/system/btif/src/btif_hf_client.cc b/system/btif/src/btif_hf_client.cc index 9a6eb128e35..79b9b543614 100644 --- a/system/btif/src/btif_hf_client.cc +++ b/system/btif/src/btif_hf_client.cc @@ -42,9 +42,9 @@ * ******************************************************************************/ -#ifndef LOG_TAG #define LOG_TAG "bt_btif_hfc" -#endif + +#include "btif_hf_client.h" #include #include @@ -68,9 +68,6 @@ #define BTIF_HF_CLIENT_SERVICE_NAME ("Handsfree") #endif -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /******************************************************************************* @@ -94,9 +91,8 @@ typedef struct { /****************************************************************************** * Local function declarations ******************************************************************************/ -btif_hf_client_cb_t* btif_hf_client_get_cb_by_handle(uint16_t handle); -btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& addr); -bool is_connected(const btif_hf_client_cb_t* cb); +static btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& addr); +static bool is_connected(const btif_hf_client_cb_t* cb); /******************************************************************************* * Static variables @@ -183,7 +179,7 @@ static void btif_in_hf_client_generic_evt(uint16_t event, char* p_param) { /******************************************************************************* * Functions ******************************************************************************/ -bool is_connected(const btif_hf_client_cb_t* cb) { +static bool is_connected(const btif_hf_client_cb_t* cb) { if ((cb->state == BTHF_CLIENT_CONNECTION_STATE_CONNECTED) || (cb->state == BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED)) { return true; @@ -193,28 +189,6 @@ bool is_connected(const btif_hf_client_cb_t* cb) { return false; } -/******************************************************************************* - * - * Function btif_hf_client_get_cb_by_handle - * - * Description Get control block by handle - * - * Returns btif_hf_client_cb_t pointer if available NULL otherwise - * - ******************************************************************************/ -btif_hf_client_cb_t* btif_hf_client_get_cb_by_handle(uint16_t handle) { - log::verbose("cb by handle {}", handle); - for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) { - // Block is valid only if it is allocated i.e. state is not DISCONNECTED - if (btif_hf_client_cb_arr.cb[i].state != BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED && - btif_hf_client_cb_arr.cb[i].handle == handle) { - return &btif_hf_client_cb_arr.cb[i]; - } - } - log::error("could not find block for handle {}", handle); - return NULL; -} - /******************************************************************************* * * Function btif_hf_client_get_cb_by_bda @@ -224,7 +198,7 @@ btif_hf_client_cb_t* btif_hf_client_get_cb_by_handle(uint16_t handle) { * Returns btif_hf_client_cb_t pointer if available NULL otherwise * ******************************************************************************/ -btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& bd_addr) { +static btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& bd_addr) { log::verbose("incoming addr {}", bd_addr); for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) { @@ -247,7 +221,7 @@ btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& bd_addr) { * Returns btif_hf_client_cb_t pointer if available NULL otherwise * ******************************************************************************/ -btif_hf_client_cb_t* btif_hf_client_allocate_cb() { +static btif_hf_client_cb_t* btif_hf_client_allocate_cb() { for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) { btif_hf_client_cb_t* cb = &btif_hf_client_cb_arr.cb[i]; if (cb->state == BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED) { -- GitLab From 3e0031ec65791747898df21eae404912685b36ae Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 2 Oct 2024 17:37:15 -0700 Subject: [PATCH 139/875] SystemServer: remove dead code in proxy Bug: 311772251 Flag: Exempt refactor Test: m Bluetooth Change-Id: I59508361143510e46809ae111d117803258ef840 --- .../com/android/server/bluetooth/BluetoothServerProxy.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothServerProxy.java b/service/src/com/android/server/bluetooth/BluetoothServerProxy.java index 7c6eb9882fb..5b05d5d53a9 100644 --- a/service/src/com/android/server/bluetooth/BluetoothServerProxy.java +++ b/service/src/com/android/server/bluetooth/BluetoothServerProxy.java @@ -63,10 +63,6 @@ class BluetoothServerProxy { return Settings.Secure.getString(contentResolver, name); } - int settingsGlobalGetInt(ContentResolver contentResolver, String name, int def) { - return Settings.Global.getInt(contentResolver, name, def); - } - int getBluetoothPersistedState(ContentResolver resolver, int defaultValue) { return Settings.Global.getInt(resolver, Settings.Global.BLUETOOTH_ON, defaultValue); } -- GitLab From 5ee00f2267fca49d829c4a647a70c86334b3387a Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 2 Oct 2024 17:38:40 -0700 Subject: [PATCH 140/875] SystemServer: parametrized test for current flags also fix current test mocking failure with the flag get_name_and_address_as_callback Flag: com.android.bluetooth.flags.get_name_and_address_as_callback Test: atest ServiceBluetoothTests Bug: 368114370 Change-Id: I6ba6b33bab661a8c3a934f8860e073bca149ad88 --- .../bluetooth/BluetoothManagerService.java | 9 ++++-- service/tests/Android.bp | 1 + .../BluetoothManagerServiceTest.java | 28 +++++++++++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 15b8ba5d314..6c0f74c635f 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -654,9 +654,14 @@ class BluetoothManagerService { mHandler); if (Flags.getNameAndAddressAsCallback()) { - mName = Settings.Secure.getString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); + mName = + BluetoothServerProxy.getInstance() + .settingsSecureGetString( + mContentResolver, Settings.Secure.BLUETOOTH_NAME); mAddress = - Settings.Secure.getString(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); + BluetoothServerProxy.getInstance() + .settingsSecureGetString( + mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); Log.d(TAG, "Local adapter: Name=" + mName + ", Address=" + logAddress(mAddress)); } else { diff --git a/service/tests/Android.bp b/service/tests/Android.bp index 12c2ef66cfe..e3b70c81d03 100644 --- a/service/tests/Android.bp +++ b/service/tests/Android.bp @@ -33,6 +33,7 @@ android_test { "libprotobuf-java-nano", "mockito-target-extended-minus-junit4", "platform-compat-test-rules", + "platform-parametric-runner-lib", "platform-test-annotations", // Linking source to test the working copy, not the on-device copy. diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java index d8ad9794056..4be1786c362 100644 --- a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java +++ b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java @@ -59,13 +59,17 @@ import android.os.Message; import android.os.UserHandle; import android.os.UserManager; import android.os.test.TestLooper; +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 androidx.test.runner.AndroidJUnit4; + +import com.android.bluetooth.flags.Flags; 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; @@ -73,11 +77,29 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import platform.test.runner.parameterized.ParameterizedAndroidJunit4; +import platform.test.runner.parameterized.Parameters; + +import java.util.List; import java.util.stream.IntStream; -@RunWith(AndroidJUnit4.class) +@RunWith(ParameterizedAndroidJunit4.class) public class BluetoothManagerServiceTest { - private static final String TAG = BluetoothManagerServiceTest.class.getSimpleName(); + + @Rule public final SetFlagsRule mSetFlagsRule; + + @Parameters(name = "{0}") + public static List getParams() { + return FlagsParameterization.allCombinationsOf( + Flags.FLAG_GET_NAME_AND_ADDRESS_AS_CALLBACK, + Flags.FLAG_ENFORCE_RESOLVE_SYSTEM_SERVICE_BEHAVIOR, + Flags.FLAG_REMOVE_ONE_TIME_GET_NAME_AND_ADDRESS); + } + + public BluetoothManagerServiceTest(FlagsParameterization flags) { + mSetFlagsRule = new SetFlagsRule(flags); + } + private static final int STATE_BLE_TURNING_ON = 14; // can't find the symbol because hidden api BluetoothManagerService mManagerService; -- GitLab From 71d1f5de248e7a7aab9538fd074cec8de3dd7114 Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Mon, 30 Sep 2024 11:47:03 +0000 Subject: [PATCH 141/875] Bass: Fix removing pending source operation by timeout Use proper argument in CANCEL_PENDING_SOURCE_OPERATION message. Add unit tests to check that it was queued properly. Bug: 370456946 Flag: Exempt, trivial fix covered with unit tests Test: atest BassClientStateMachineTest BassClientServiceTest Change-Id: I965976eefbef068e9d20de82a7cea7ddf8c4da34 --- .../bass_client/BassClientStateMachine.java | 4 +- .../BassClientStateMachineTest.java | 123 ++++++++++++++++++ 2 files changed, 125 insertions(+), 2 deletions(-) diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index 6ac75f70047..5c09299147d 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -2210,7 +2210,7 @@ public class BassClientStateMachine extends StateMachine { BassConstants.GATT_TXN_TIMEOUT_MS); sendMessageDelayed( CANCEL_PENDING_SOURCE_OPERATION, - metaData.getBroadcastCode(), + metaData.getBroadcastId(), BassConstants.SOURCE_OPERATION_TIMEOUT_MS); } else { Log.e(TAG, "ADD_BCAST_SOURCE: no Bluetooth Gatt handle, Fatal"); @@ -2255,7 +2255,7 @@ public class BassClientStateMachine extends StateMachine { BassConstants.GATT_TXN_TIMEOUT_MS); sendMessageDelayed( CANCEL_PENDING_SOURCE_OPERATION, - metaData.getBroadcastCode(), + metaData.getBroadcastId(), BassConstants.SOURCE_OPERATION_TIMEOUT_MS); } else { Log.e(TAG, "UPDATE_BCAST_SOURCE: no Bluetooth Gatt handle, Fatal"); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index ebfba1eac8f..1ce3773a410 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -2372,6 +2372,106 @@ public class BassClientStateMachineTest { assertThat(mBassClientStateMachine.hasPendingSourceOperation(metadata.getBroadcastId())) .isTrue(); + assertThat(mBassClientStateMachine.mMsgWhats).contains(CANCEL_PENDING_SOURCE_OPERATION); + assertThat(mBassClientStateMachine.mMsgAgr1).isEqualTo(TEST_BROADCAST_ID); + + /* Inject a cancel pending source operation event */ + Message msg = mBassClientStateMachine.obtainMessage(CANCEL_PENDING_SOURCE_OPERATION); + msg.arg1 = metadata.getBroadcastId(); + mBassClientStateMachine.sendMessage(msg); + + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + + /* Verify if pending add source operation is canceled */ + assertThat(mBassClientStateMachine.hasPendingSourceOperation(metadata.getBroadcastId())) + .isFalse(); + } + + @Test + public void cancelPendingUpdateBcastSourceMessage_inConnectedState() { + initToConnectedState(); + mBassClientStateMachine.connectGatt(true); + mBassClientStateMachine.mNumOfBroadcastReceiverStates = 2; + + // Prepare mBluetoothLeBroadcastReceiveStates for test + BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); + when(mBassClientService.getCallbacks()).thenReturn(callbacks); + int sourceId = 1; + int paSync = BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE; + byte[] value = + new byte[] { + (byte) sourceId, // sourceId + (byte) (mSourceTestDevice.getAddressType() & 0xFF), // sourceAddressType + Utils.getByteAddress(mSourceTestDevice)[5], + Utils.getByteAddress(mSourceTestDevice)[4], + Utils.getByteAddress(mSourceTestDevice)[3], + Utils.getByteAddress(mSourceTestDevice)[2], + Utils.getByteAddress(mSourceTestDevice)[1], + Utils.getByteAddress(mSourceTestDevice)[0], // sourceAddress + 0x00, // sourceAdvSid + 0x00, + 0x00, + 0x00, // broadcastIdBytes + (byte) paSync, + (byte) BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_BAD_CODE, + // 16 bytes badBroadcastCode + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, // numSubGroups + // SubGroup #1 + 0x00, + 0x00, + 0x00, + 0x00, // audioSyncIndex + 0x02, // metaDataLength + 0x00, + 0x00, // metadata + }; + BluetoothGattCharacteristic characteristic = + Mockito.mock(BluetoothGattCharacteristic.class); + when(characteristic.getValue()).thenReturn(value); + when(characteristic.getInstanceId()).thenReturn(sourceId); + when(characteristic.getUuid()).thenReturn(BassConstants.BASS_BCAST_RECEIVER_STATE); + mBassClientStateMachine.mGattCallback.onCharacteristicRead( + null, characteristic, GATT_SUCCESS); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + + BluetoothLeBroadcastMetadata metadata = createBroadcastMetadata(); + BassClientStateMachine.BluetoothGattTestableWrapper btGatt = + Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class); + mBassClientStateMachine.mBluetoothGatt = btGatt; + BluetoothGattCharacteristic scanControlPoint = + Mockito.mock(BluetoothGattCharacteristic.class); + mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; + + sendMessageAndVerifyTransition( + mBassClientStateMachine.obtainMessage( + UPDATE_BCAST_SOURCE, sourceId, paSync, metadata), + BassClientStateMachine.ConnectedProcessing.class); + verify(scanControlPoint).setValue(any(byte[].class)); + verify(btGatt).writeCharacteristic(any()); + + /* Verify if there is pending add source operation */ + assertThat(mBassClientStateMachine.hasPendingSourceOperation(metadata.getBroadcastId())) + .isTrue(); + + assertThat(mBassClientStateMachine.mMsgWhats).contains(CANCEL_PENDING_SOURCE_OPERATION); + assertThat(mBassClientStateMachine.mMsgAgr1).isEqualTo(TEST_BROADCAST_ID); + /* Inject a cancel pending source operation event */ Message msg = mBassClientStateMachine.obtainMessage(CANCEL_PENDING_SOURCE_OPERATION); msg.arg1 = metadata.getBroadcastId(); @@ -2798,6 +2898,7 @@ public class BassClientStateMachineTest { int mMsgAgr1; int mMsgArg2; Object mMsgObj; + long mMsgDelay; StubBassClientStateMachine( BluetoothDevice device, @@ -2826,6 +2927,28 @@ public class BassClientStateMachineTest { } } + @Override + public void sendMessageDelayed(int what, Object obj, long delayMillis) { + mMsgWhats.add(what); + mMsgWhat = what; + mMsgObj = obj; + mMsgDelay = delayMillis; + if (mShouldHandleMessage) { + super.sendMessageDelayed(what, obj, delayMillis); + } + } + + @Override + public void sendMessageDelayed(int what, int arg1, long delayMillis) { + mMsgWhats.add(what); + mMsgWhat = what; + mMsgAgr1 = arg1; + mMsgDelay = delayMillis; + if (mShouldHandleMessage) { + super.sendMessageDelayed(what, arg1, delayMillis); + } + } + public void notifyConnectionStateChanged(int status, int newState) { if (mGattCallback != null) { BluetoothGatt gatt = null; -- GitLab From f32474f50733e1fb9c5e4eba5143a650fbc40c98 Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Mon, 30 Sep 2024 17:35:37 +0000 Subject: [PATCH 142/875] PandoraServer: Implement new L2CAP interface Bug: 367808704 Test: atest pts-bot:L2CAP Change-Id: I93cf1a764a8e2a30da692bf2a38e60688a6c03b2 --- android/pandora/mmi2grpc/mmi2grpc/l2cap.py | 67 +++--- .../server/configs/pts_bot_tests_config.json | 1 + android/pandora/server/src/L2cap.kt | 211 ++++++++---------- 3 files changed, 127 insertions(+), 152 deletions(-) diff --git a/android/pandora/mmi2grpc/mmi2grpc/l2cap.py b/android/pandora/mmi2grpc/mmi2grpc/l2cap.py index 09ef10d7517..09136bedb8a 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/l2cap.py +++ b/android/pandora/mmi2grpc/mmi2grpc/l2cap.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import time import sys from mmi2grpc._helpers import assert_description @@ -22,15 +21,16 @@ from mmi2grpc._rootcanal import Dongle from pandora.host_grpc import Host from pandora.host_pb2 import PUBLIC, RANDOM, Connection +from pandora.l2cap_grpc import L2CAP +from pandora.l2cap_pb2 import CreditBasedChannelRequest from pandora.security_pb2 import PairingEventAnswer from pandora.security_grpc import Security -from pandora_experimental.l2cap_grpc import L2CAP -from typing import Optional +from typing import Optional, Dict class L2CAPProxy(ProfileProxy): - test_status_map = {} # record test status and pass them between MMI + test_status_map: Dict[str, str] = {} # record test status and pass them between MMI LE_DATA_PACKET_LARGE = "data: LE_DATA_PACKET_LARGE" LE_DATA_PACKET1 = "data: LE_PACKET1" connection: Optional[Connection] = None @@ -44,6 +44,7 @@ class L2CAPProxy(ProfileProxy): self.connection = None self.pairing_events = None + self.channel = None def test_started(self, test: str, **kwargs): self.rootcanal.select_pts_dongle(Dongle.CSR_RCK_PTS_DONGLE) @@ -63,16 +64,12 @@ class L2CAPProxy(ProfileProxy): tests_target_to_fail = [ 'L2CAP/LE/CFC/BV-01-C', 'L2CAP/LE/CFC/BV-04-C', - 'L2CAP/LE/CFC/BV-10-C', - 'L2CAP/LE/CFC/BV-11-C', - 'L2CAP/LE/CFC/BV-12-C', 'L2CAP/LE/CFC/BV-14-C', 'L2CAP/LE/CFC/BV-16-C', 'L2CAP/LE/CFC/BV-18-C', 'L2CAP/LE/CFC/BV-19-C', "L2CAP/LE/CFC/BV-21-C", ] - tests_require_secure_connection = [] # This MMI is called twice in 'L2CAP/LE/CFC/BV-04-C' # We are not sure whether the lower tester’s BluetoothServerSocket @@ -97,10 +94,13 @@ class L2CAPProxy(ProfileProxy): if test == 'L2CAP/LE/CFC/BV-12-C': psm = 0xF3 # default TSPX_psm_authorization_required value - secure_connection = test in tests_require_secure_connection - try: - self.l2cap.CreateLECreditBasedChannel(connection=self.connection, psm=psm, secure=secure_connection) + connect_response = self.l2cap.Connect(connection=self.connection, + le_credit_based=CreditBasedChannelRequest(spsm=psm)) + if connect_response.HasField('channel'): + self.channel = connect_response.channel + else: + raise Exception(connect_response.error) except Exception as e: if test in tests_target_to_fail: self.test_status_map[test] = 'OK' @@ -117,11 +117,13 @@ class L2CAPProxy(ProfileProxy): """ Place the IUT into LE connectable mode. """ + self.advertise = self.host.Advertise( legacy=True, connectable=True, own_address_type=PUBLIC, ) + # not strictly necessary, but can save time on waiting connection tests_to_open_bluetooth_server_socket = [ "L2CAP/COS/CFC/BV-01-C", @@ -129,31 +131,19 @@ class L2CAPProxy(ProfileProxy): "L2CAP/COS/CFC/BV-03-C", "L2CAP/COS/CFC/BV-04-C", "L2CAP/LE/CFC/BV-03-C", - "L2CAP/LE/CFC/BV-05-C", "L2CAP/LE/CFC/BV-06-C", "L2CAP/LE/CFC/BV-09-C", - "L2CAP/LE/CFC/BV-13-C", "L2CAP/LE/CFC/BV-20-C", "L2CAP/LE/CFC/BI-01-C", ] - tests_require_secure_connection = [ - "L2CAP/LE/CFC/BV-13-C", - ] - tests_connection_target_to_failed = [ - "L2CAP/LE/CFC/BV-05-C", - ] if test in tests_to_open_bluetooth_server_socket: - secure_connection = test in tests_require_secure_connection - self.l2cap.ListenL2CAPChannel(connection=self.connection, secure=secure_connection) - try: - self.l2cap.AcceptL2CAPChannel(connection=self.connection) - except Exception as e: - if test in tests_connection_target_to_failed: - self.test_status_map[test] = 'OK' - print(test, 'connection targets to fail', file=sys.stderr) - else: - raise e + wait_connection_response = self.l2cap.WaitConnection(le_credit_based=CreditBasedChannelRequest(spsm=0)) + if wait_connection_response.HasField('channel'): + self.channel = wait_connection_response.channel + else: + raise Exception(wait_connection_response.error) + return "OK" @assert_description @@ -171,7 +161,8 @@ class L2CAPProxy(ProfileProxy): # all data frames arrived # it seemed like when the time gap between the 1st frame and 2nd frame # larger than 100ms this problem will occur - self.l2cap.SendData(connection=self.connection, data=bytes(self.LE_DATA_PACKET_LARGE, "utf-8")) + assert self.channel + self.l2cap.Send(channel=self.channel, data=bytes(self.LE_DATA_PACKET_LARGE, "utf-8")) return "OK" @match_description @@ -198,8 +189,9 @@ class L2CAPProxy(ProfileProxy): Upper Tester command IUT to send at least 4 frames of LE data packets to the PTS. """ - self.l2cap.SendData( - connection=self.connection, + assert self.channel + self.l2cap.Send( + channel=self.channel, data=b"this is a large data package with at least 4 frames: MMI_UPPER_TESTER_SEND_LE_DATA_PACKET_LARGE") return "OK" @@ -208,8 +200,9 @@ class L2CAPProxy(ProfileProxy): """ IUT continue to send LE data packet(s) to the PTS. """ - self.l2cap.SendData( - connection=self.connection, + assert self.channel + self.l2cap.Send( + channel=self.channel, data=b"this is a large data package with at least 4 frames: MMI_UPPER_TESTER_SEND_LE_DATA_PACKET_LARGE") return "OK" @@ -232,7 +225,8 @@ class L2CAPProxy(ProfileProxy): """ Please confirm the Upper Tester receive data """ - data = self.l2cap.ReceiveData(connection=self.connection) + assert self.channel + data = next(self.l2cap.Receive(channel=self.channel)).data assert data, "data received should not be empty" return "OK" @@ -504,7 +498,8 @@ class L2CAPProxy(ProfileProxy): Description : The Implementation Under Test(IUT) should send none segmantation LE frame of LE data to the PTS. """ - self.l2cap.SendData(connection=self.connection, data=bytes(self.LE_DATA_PACKET1, "utf-8")) + assert self.channel + self.l2cap.Send(channel=self.channel, data=bytes(self.LE_DATA_PACKET1, "utf-8")) return "OK" @assert_description diff --git a/android/pandora/server/configs/pts_bot_tests_config.json b/android/pandora/server/configs/pts_bot_tests_config.json index 93102922458..3cfbe0d26ec 100644 --- a/android/pandora/server/configs/pts_bot_tests_config.json +++ b/android/pandora/server/configs/pts_bot_tests_config.json @@ -1048,6 +1048,7 @@ "L2CAP/CMC/BV-13-C", "L2CAP/CMC/BV-14-C", "L2CAP/CMC/BV-15-C", + "L2CAP/COS/CED/BI-02-C", "L2CAP/COS/CED/BV-10-C", "L2CAP/COS/CED/BV-12-C", "L2CAP/COS/CED/BV-13-C", diff --git a/android/pandora/server/src/L2cap.kt b/android/pandora/server/src/L2cap.kt index 77b96038f72..1d1e9c8a211 100644 --- a/android/pandora/server/src/L2cap.kt +++ b/android/pandora/server/src/L2cap.kt @@ -16,46 +16,35 @@ package com.android.pandora +import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothManager -import android.bluetooth.BluetoothServerSocket +import android.bluetooth.BluetoothSocket import android.content.Context import android.util.Log +import com.google.protobuf.Any import com.google.protobuf.ByteString import io.grpc.stub.StreamObserver import java.io.Closeable -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream +import java.util.concurrent.atomic.AtomicLong import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel -import kotlinx.coroutines.withContext -import pandora.HostProto.Connection -import pandora.L2CAPGrpc.L2CAPImplBase -import pandora.L2capProto.AcceptL2CAPChannelRequest -import pandora.L2capProto.AcceptL2CAPChannelResponse -import pandora.L2capProto.CreateLECreditBasedChannelRequest -import pandora.L2capProto.CreateLECreditBasedChannelResponse -import pandora.L2capProto.ListenL2CAPChannelRequest -import pandora.L2capProto.ListenL2CAPChannelResponse -import pandora.L2capProto.ReceiveDataRequest -import pandora.L2capProto.ReceiveDataResponse -import pandora.L2capProto.SendDataRequest -import pandora.L2capProto.SendDataResponse +import kotlinx.coroutines.flow.flow +import pandora.l2cap.L2CAPGrpc.L2CAPImplBase +import pandora.l2cap.L2CAPProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class L2cap(val context: Context) : L2CAPImplBase(), Closeable { private val TAG = "PandoraL2cap" private val scope: CoroutineScope private val BLUETOOTH_SERVER_SOCKET_TIMEOUT: Int = 10000 + private val channelIdCounter = AtomicLong(1) private val BUFFER_SIZE = 512 private val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager private val bluetoothAdapter = bluetoothManager.adapter - private var connectionInStreamMap: HashMap = hashMapOf() - private var connectionOutStreamMap: HashMap = hashMapOf() - private var connectionServerSocketMap: HashMap = hashMapOf() + private val channels: HashMap = hashMapOf() init { // Init the CoroutineScope @@ -67,127 +56,117 @@ class L2cap(val context: Context) : L2CAPImplBase(), Closeable { scope.cancel() } - suspend fun receive(inStream: InputStream): ByteArray { - return withContext(Dispatchers.IO) { - val buf = ByteArray(BUFFER_SIZE) - inStream.read(buf, 0, BUFFER_SIZE) // blocking - Log.i(TAG, "receive: $buf") - buf - } - } - - /** Open a BluetoothServerSocket to accept connections */ - override fun listenL2CAPChannel( - request: ListenL2CAPChannelRequest, - responseObserver: StreamObserver, + override fun connect( + request: ConnectRequest, + responseObserver: StreamObserver, ) { grpcUnary(scope, responseObserver) { - Log.i(TAG, "listenL2CAPChannel: secure=${request.secure}") - val connection = request.connection - val bluetoothServerSocket = - if (request.secure) { - bluetoothAdapter.listenUsingL2capChannel() - } else { - bluetoothAdapter.listenUsingInsecureL2capChannel() + val device = request.connection.toBluetoothDevice(bluetoothAdapter) + + val psm = + when { + request.hasBasic() -> request.basic.psm + request.hasLeCreditBased() -> request.leCreditBased.spsm + request.hasEnhancedCreditBased() -> request.enhancedCreditBased.spsm + else -> throw RuntimeException("unreachable") } - connectionServerSocketMap[connection] = bluetoothServerSocket - ListenL2CAPChannelResponse.newBuilder().build() - } - } + Log.i(TAG, "connect: $device psm: $psm") - override fun acceptL2CAPChannel( - request: AcceptL2CAPChannelRequest, - responseObserver: StreamObserver, - ) { - grpcUnary(scope, responseObserver) { - Log.i(TAG, "acceptL2CAPChannel") - - val connection = request.connection - val bluetoothServerSocket = connectionServerSocketMap[connection] - try { - val bluetoothSocket = - bluetoothServerSocket!!.accept(BLUETOOTH_SERVER_SOCKET_TIMEOUT) - connectionInStreamMap[connection] = bluetoothSocket.getInputStream()!! - connectionOutStreamMap[connection] = bluetoothSocket.getOutputStream()!! - } catch (e: IOException) { - Log.e(TAG, "bluetoothServerSocket not accepted", e) - throw e - } + val bluetoothSocket = device.createInsecureL2capChannel(psm) + bluetoothSocket.connect() + val channelId = getNewChannelId() + channels.put(channelId, bluetoothSocket) - AcceptL2CAPChannelResponse.newBuilder().build() + Log.d(TAG, "connect: channelId=$channelId") + ConnectResponse.newBuilder().setChannel(craftChannel(channelId)).build() } } - /** Set device to send LE based connection request */ - override fun createLECreditBasedChannel( - request: CreateLECreditBasedChannelRequest, - responseObserver: StreamObserver, + override fun waitConnection( + request: WaitConnectionRequest, + responseObserver: StreamObserver, ) { - // Creates a gRPC coroutine in a given coroutine scope which executes a given suspended - // function - // returning a gRPC response and sends it on a given gRPC stream observer. grpcUnary(scope, responseObserver) { - Log.i(TAG, "createLECreditBasedChannel: secure=${request.secure}, psm=${request.psm}") - val connection = request.connection - val device = request.connection.toBluetoothDevice(bluetoothAdapter) - val psm = request.psm + val device: BluetoothDevice? = + try { + request.connection.toBluetoothDevice(bluetoothAdapter) + } catch (e: Exception) { + Log.w(TAG, e) + null + } + + Log.i(TAG, "waitConnection: $device") - try { - val bluetoothSocket = - if (request.secure) { - device.createL2capChannel(psm) + val psm = + when { + request.hasBasic() -> request.basic.psm + request.hasLeCreditBased() -> request.leCreditBased.spsm + request.hasEnhancedCreditBased() -> request.enhancedCreditBased.spsm + else -> throw RuntimeException("unreachable") + } + + var bluetoothSocket: BluetoothSocket? + + while (true) { + val bluetoothServerSocket = + if (psm == 0) { + bluetoothAdapter.listenUsingInsecureL2capChannel() } else { - device.createInsecureL2capChannel(psm) + bluetoothAdapter.listenUsingInsecureL2capOn(psm) } - bluetoothSocket.connect() - connectionInStreamMap[connection] = bluetoothSocket.getInputStream()!! - connectionOutStreamMap[connection] = bluetoothSocket.getOutputStream()!! - } catch (e: IOException) { - Log.d(TAG, "bluetoothSocket not connected: $e") - throw e + bluetoothSocket = bluetoothServerSocket.accept() + bluetoothServerSocket.close() + if (device != null && !bluetoothSocket.getRemoteDevice().equals(device)) continue + break } - // Response sent to client - CreateLECreditBasedChannelResponse.newBuilder().build() + val channelId = getNewChannelId() + channels.put(channelId, bluetoothSocket!!) + + Log.d(TAG, "waitConnection: channelId=$channelId") + WaitConnectionResponse.newBuilder().setChannel(craftChannel(channelId)).build() } } - /** send data packet */ - override fun sendData( - request: SendDataRequest, - responseObserver: StreamObserver, - ) { + override fun send(request: SendRequest, responseObserver: StreamObserver) { grpcUnary(scope, responseObserver) { - Log.i(TAG, "sendDataPacket: data=${request.data}") - val buffer = request.data!!.toByteArray() - val connection = request.connection - val outputStream = connectionOutStreamMap[connection]!! + Log.i(TAG, "send") + val bluetoothSocket = request.channel.toBluetoothSocket(channels) + val outputStream = bluetoothSocket.outputStream - withContext(Dispatchers.IO) { - try { - outputStream.write(buffer) - outputStream.flush() - } catch (e: IOException) { - Log.e(TAG, "Exception during writing to sendDataPacket output stream", e) - } - } + outputStream.write(request.data.toByteArray()) + outputStream.flush() - // Response sent to client - SendDataResponse.newBuilder().build() + SendResponse.newBuilder().build() } } - override fun receiveData( - request: ReceiveDataRequest, - responseObserver: StreamObserver, + override fun receive( + request: ReceiveRequest, + responseObserver: StreamObserver, ) { - grpcUnary(scope, responseObserver) { - Log.i(TAG, "receiveData") - val connection = request.connection - val inputStream = connectionInStreamMap[connection]!! - val buf = receive(inputStream) - - ReceiveDataResponse.newBuilder().setData(ByteString.copyFrom(buf)).build() + Log.i(TAG, "receive") + val bluetoothSocket = request.channel.toBluetoothSocket(channels) + val inputStream = bluetoothSocket.inputStream + grpcServerStream(scope, responseObserver) { + flow { + val buffer = ByteArray(BUFFER_SIZE) + inputStream.read(buffer, 0, BUFFER_SIZE) + val data = ByteString.copyFrom(buffer) + val response = ReceiveResponse.newBuilder().setData(data).build() + emit(response) + } } } + + fun getNewChannelId(): Long = channelIdCounter.getAndIncrement() + + fun craftChannel(id: Long): Channel { + val cookie = Any.newBuilder().setValue(ByteString.copyFromUtf8(id.toString())).build() + val channel = Channel.newBuilder().setCookie(cookie).build() + return channel + } + + fun Channel.toBluetoothSocket(channels: HashMap): BluetoothSocket = + channels.get(this.cookie.value.toStringUtf8().toLong())!! } -- GitLab From 2a8fc4d13fb558d453ac7082c6fb6f8e83f5ead7 Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Mon, 30 Sep 2024 17:35:55 +0000 Subject: [PATCH 143/875] Pandora: remove experiemental l2cap.proto Bug: 367808704 Test: atest pts-bot:L2CAP Change-Id: I5a9793af0ed020391fe8f4574bf8ff95547db194 --- .../pandora_experimental/l2cap.proto | 62 ------------------- pandora/interfaces/python/Android.bp | 5 -- 2 files changed, 67 deletions(-) delete mode 100644 pandora/interfaces/pandora_experimental/l2cap.proto diff --git a/pandora/interfaces/pandora_experimental/l2cap.proto b/pandora/interfaces/pandora_experimental/l2cap.proto deleted file mode 100644 index 443010a00fc..00000000000 --- a/pandora/interfaces/pandora_experimental/l2cap.proto +++ /dev/null @@ -1,62 +0,0 @@ -syntax = "proto3"; - -package pandora; - -option java_outer_classname = "L2capProto"; - -import "google/protobuf/empty.proto"; -import "pandora/host.proto"; - -service L2CAP { - // Create a L2CAP connection to a peer. - rpc CreateLECreditBasedChannel(CreateLECreditBasedChannelRequest) returns (CreateLECreditBasedChannelResponse); - // Send some data - rpc SendData(SendDataRequest) returns (SendDataResponse); - // Receive data - rpc ReceiveData(ReceiveDataRequest) returns (ReceiveDataResponse); - // Listen L2CAP channel for connection - rpc ListenL2CAPChannel(ListenL2CAPChannelRequest) returns (ListenL2CAPChannelResponse); - // Accept L2CAP connection - rpc AcceptL2CAPChannel(AcceptL2CAPChannelRequest) returns (AcceptL2CAPChannelResponse); -} - -// Request for the `OpenSource` method. -message CreateLECreditBasedChannelRequest { - // The connection that will open the stream. - Connection connection = 1; - int32 psm = 2; - bool secure = 3; -} - -// Request for the `OpenSource` method. -message CreateLECreditBasedChannelResponse {} - -message SendDataRequest { - // The connection that will open the stream. - Connection connection = 1; - bytes data = 2; -} - -message SendDataResponse {} - -message ReceiveDataRequest { - // The connection that will open the stream. - Connection connection = 1; -} - -message ReceiveDataResponse { - bytes data = 1; -} - -message ListenL2CAPChannelRequest{ - Connection connection = 1; - bool secure = 2; -} - -message ListenL2CAPChannelResponse {} - -message AcceptL2CAPChannelRequest{ - Connection connection = 1; -} - -message AcceptL2CAPChannelResponse {} \ No newline at end of file diff --git a/pandora/interfaces/python/Android.bp b/pandora/interfaces/python/Android.bp index 4532716d91f..2abac309db9 100644 --- a/pandora/interfaces/python/Android.bp +++ b/pandora/interfaces/python/Android.bp @@ -54,10 +54,6 @@ genrule { "pandora_experimental/hid_grpc_aio.py", "pandora_experimental/hid_pb2.py", "pandora_experimental/hid_pb2.pyi", - "pandora_experimental/l2cap_grpc.py", - "pandora_experimental/l2cap_grpc_aio.py", - "pandora_experimental/l2cap_pb2.py", - "pandora_experimental/l2cap_pb2.pyi", "pandora_experimental/le_audio_grpc.py", "pandora_experimental/le_audio_grpc_aio.py", "pandora_experimental/le_audio_pb2.py", @@ -118,7 +114,6 @@ filegroup { ":pandora_experimental-python-gen-src{pandora_experimental/hap_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/hfp_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/hid_pb2.pyi}", - ":pandora_experimental-python-gen-src{pandora_experimental/l2cap_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/le_audio_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/map_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/mediaplayer_pb2.pyi}", -- GitLab From f0cba7267e3d03437f6678f1a9f43d76a1b2e4f0 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 5 Apr 2024 14:12:25 -0700 Subject: [PATCH 144/875] Remove //vendor:__subpackages__ from libbluetooth visibility Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, build change Change-Id: Ief644f1a5961fe7dbae37c58aa0c5c775f8a307e --- system/main/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/system/main/Android.bp b/system/main/Android.bp index f1b07c05442..c64fff5dfce 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -67,7 +67,6 @@ cc_library { visibility: [ "//cts/hostsidetests:__subpackages__", "//packages/modules/Bluetooth:__subpackages__", - "//vendor:__subpackages__", ], defaults: ["fluoride_defaults"], header_libs: ["libbluetooth_headers"], -- GitLab From 34dd83f45b815489bfc84eadfe06001ddff6d892 Mon Sep 17 00:00:00 2001 From: Cheng Li Date: Thu, 3 Oct 2024 17:39:49 +0000 Subject: [PATCH 145/875] Add trace points for HCI packets Bug: 365778358 Bug: 369428038 Test: m Test: Build and run locally with perfetto tracing enabled while using bluetooth Change-Id: Ic44db021cb0f7667fa156324485ca59b982d5484 --- system/gd/hal/BUILD.gn | 5 ++- system/gd/hal/snoop_logger.cc | 64 +++++++++++++++++++++++++++++++++++ system/gd/hal/snoop_logger.h | 4 +++ system/stack/Android.bp | 2 ++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/system/gd/hal/BUILD.gn b/system/gd/hal/BUILD.gn index ecdc60ed287..f0a2f9d159b 100644 --- a/system/gd/hal/BUILD.gn +++ b/system/gd/hal/BUILD.gn @@ -24,7 +24,10 @@ source_set("BluetoothHalSources") { ] configs += [ "//bt/system/gd:gd_defaults" ] - deps = [ "//bt/system/gd:gd_default_deps" ] + deps = [ + "//bt/flags:bluetooth_flags_c_lib", + "//bt/system/gd:gd_default_deps" + ] } source_set("BluetoothHalSources_hci_host") { diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc index 44cd8baaa46..6b9fc8a2d13 100644 --- a/system/gd/hal/snoop_logger.cc +++ b/system/gd/hal/snoop_logger.cc @@ -14,10 +14,16 @@ * limitations under the License. */ +#define ATRACE_TAG ATRACE_TAG_APP + #include "hal/snoop_logger.h" #include #include +#include +#ifdef __ANDROID__ +#include +#endif // __ANDROID__ #include #include @@ -28,6 +34,7 @@ #include "common/circular_buffer.h" #include "common/strings.h" #include "hal/snoop_logger_common.h" +#include "hci/hci_packets.h" #include "module_dumper_flatbuffer.h" #include "os/files.h" #include "os/parameter_provider.h" @@ -1123,6 +1130,13 @@ void SnoopLogger::Capture(const HciPacket& immutable_packet, Direction direction HciPacket mutable_packet(immutable_packet); HciPacket& packet = mutable_packet; ////////////////////////////////////////////////////////////////////////// + + #ifdef __ANDROID__ + if (com::android::bluetooth::flags::snoop_logger_tracing()) { + LogTracePoint(packet, direction, type); + } + #endif // __ANDROID__ + uint64_t timestamp_us = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); @@ -1401,5 +1415,55 @@ const ModuleFactory SnoopLogger::Factory = ModuleFactory([]() { IsBtSnoopLogPersisted()); }); +#ifdef __ANDROID__ +void SnoopLogger::LogTracePoint(const HciPacket& packet, Direction direction, PacketType type) { + switch (type) { + case PacketType::EVT: { + uint8_t evt_code = packet[0]; + + if (evt_code == static_cast(hci::EventCode::LE_META_EVENT) || + evt_code == static_cast(hci::EventCode::VENDOR_SPECIFIC)) { + uint8_t subevt_code = packet[2]; + std::string message = + fmt::format("BTSL:{}/{}/{}/{:02x}/{:02x}", static_cast(type), + static_cast(direction), packet.size(), evt_code, subevt_code); + + ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str()); + } else { + std::string message = fmt::format("BTSL:{}/{}/{}/{:02x}", static_cast(type), + static_cast(direction), packet.size(), evt_code); + + ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str()); + } + } break; + case PacketType::CMD: { + uint16_t op_code = packet[0] | (packet[1] << 8); + + std::string message = fmt::format("BTSL:{}/{}/{}/{:04x}", static_cast(type), + static_cast(direction), packet.size(), op_code); + + ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str()); + } break; + case PacketType::ACL: { + uint16_t handle = (packet[0] | (packet[1] << 8)) & 0x0fff; + uint8_t pb_flag = (packet[1] & 0x30) >> 4; + + std::string message = fmt::format("BTSL:{}/{}/{}/{:03x}/{}", static_cast(type), + static_cast(direction), packet.size(), handle, + pb_flag); + + ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str()); + } break; + case PacketType::ISO: + case PacketType::SCO: { + std::string message = fmt::format("BTSL:{}/{}/{}", static_cast(type), + static_cast(direction), packet.size()); + + ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str()); + } break; + } +} +#endif // __ANDROID__ + } // namespace hal } // namespace bluetooth diff --git a/system/gd/hal/snoop_logger.h b/system/gd/hal/snoop_logger.h index 656b3b1b369..3566630e70d 100644 --- a/system/gd/hal/snoop_logger.h +++ b/system/gd/hal/snoop_logger.h @@ -319,6 +319,10 @@ protected: std::unique_ptr snoop_logger_socket_thread_; + #ifdef __ANDROID__ + void LogTracePoint(const HciPacket& packet, Direction direction, PacketType type); + #endif // __ANDROID__ + private: static std::string btsnoop_mode_; std::string snoop_log_path_; diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 152b866cc3e..33d5138882a 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -1773,6 +1773,7 @@ cc_test { shared_libs: [ "libaconfig_storage_read_api_cc", "libcrypto", + "libcutils", "server_configurable_flags", ], sanitize: { @@ -2355,6 +2356,7 @@ cc_test { shared_libs: [ "libaconfig_storage_read_api_cc", "libcrypto", + "libcutils", "server_configurable_flags", ], sanitize: { -- GitLab From 79d5749512fd8f689eada24f7376222895fe4a99 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Thu, 3 Oct 2024 20:18:58 +0000 Subject: [PATCH 146/875] Fix a cpplint warining in LeAudioDevice constructor. Bug: 350102910 Bug: 353978074 Change-Id: I7dbc6b01934f8a25a8631f06cf96a1dc73bba528 Test: atest --host bluetooth_le_audio_client_test Flag: exempt --- system/bta/le_audio/devices.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/bta/le_audio/devices.h b/system/bta/le_audio/devices.h index d874e8dbdb0..d4c7d4ba2a0 100644 --- a/system/bta/le_audio/devices.h +++ b/system/bta/le_audio/devices.h @@ -113,9 +113,9 @@ public: alarm_t* link_quality_timer; uint16_t link_quality_timer_data; - LeAudioDevice(const RawAddress& address_, DeviceConnectState state, + LeAudioDevice(const RawAddress& address, DeviceConnectState state, int group_id = bluetooth::groups::kGroupUnknown) - : address_(address_), + : address_(address), connection_state_(state), known_service_handles_(false), notify_connected_after_read_(false), -- GitLab From 7d005d324560791a76b8179908e3c65f811e5b7f Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 3 Oct 2024 10:11:36 -0700 Subject: [PATCH 147/875] Convert leftover ALOGx macros in HFP JNI Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, minor refactor Change-Id: Ic7f3f17d2f8dbb9633579ddfddc6183ffa05c683 --- android/app/jni/com_android_bluetooth_hfp.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_hfp.cpp b/android/app/jni/com_android_bluetooth_hfp.cpp index 40b587ede3c..c1d982de173 100644 --- a/android/app/jni/com_android_bluetooth_hfp.cpp +++ b/android/app/jni/com_android_bluetooth_hfp.cpp @@ -16,6 +16,8 @@ #define LOG_TAG "BluetoothHeadsetServiceJni" +#include + #include #include @@ -24,7 +26,6 @@ #include "hardware/bluetooth_headset_callbacks.h" #include "hardware/bluetooth_headset_interface.h" #include "hardware/bt_hf.h" -#include "os/log.h" namespace android { @@ -948,22 +949,22 @@ static jboolean enableSwbNative(JNIEnv* env, jobject /* object */, jint swbCodec jbyteArray address) { std::shared_lock lock(interface_mutex); if (!sBluetoothHfpInterface) { - ALOGW("%s: sBluetoothHfpInterface is null", __func__); + log::warn("sBluetoothHfpInterface is null"); return JNI_FALSE; } jbyte* addr = env->GetByteArrayElements(address, NULL); if (!addr) { - ALOGE("%s: failed to get device address", __func__); + log::error("failed to get device address"); jniThrowIOException(env, EINVAL); return JNI_FALSE; } bt_status_t ret = sBluetoothHfpInterface->EnableSwb( (bluetooth::headset::bthf_swb_codec_t)swbCodec, (bool)enable, (RawAddress*)addr); if (ret != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed to %s", __func__, (enable ? "enable" : "disable")); + log::error("Failed to {}", (enable ? "enable" : "disable")); return JNI_FALSE; } - ALOGV("%s: Successfully %s", __func__, (enable ? "enabled" : "disabled")); + log::verbose("Successfully {}", (enable ? "enabled" : "disabled")); return JNI_TRUE; } -- GitLab From ec44ba1db5e437d90d6caa9e5dfd31b02efff19c Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Thu, 3 Oct 2024 20:15:34 +0000 Subject: [PATCH 148/875] Check in_use to prevent accessing deallocated cb Flag: EXEMPT, strict checking Bug: 273561907 Bug: 371114560 Test: atest GattClientTest Change-Id: I4423fbd6bb3808c575992efca89466bcf3734e82 --- system/bta/gatt/bta_gattc_act.cc | 7 ++++--- system/bta/gatt/bta_gattc_utils.cc | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index 636951cb8cf..95eb0a73376 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -297,7 +297,7 @@ 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->p_rcb != p_clreg) { + if (!p_clcb->in_use || p_clcb->p_rcb != p_clreg) { continue; } p_clreg->dereg_pending = true; @@ -1504,7 +1504,8 @@ void bta_gattc_process_api_refresh(const RawAddress& remote_bda) { 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->p_srcb == p_srvc_cb) { + if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srvc_cb) { + p_clcb = p_clcb_i.get(); found = true; break; } @@ -1576,7 +1577,7 @@ static bool bta_gattc_process_srvc_chg_ind(tCONN_ID conn_id, tBTA_GATTC_RCB* p_c 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->p_srcb == p_srcb && p_clcb_i->p_q_cmd == NULL) { + 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; } diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc index 36e05ba8b50..ca911dec784 100644 --- a/system/bta/gatt/bta_gattc_utils.cc +++ b/system/bta/gatt/bta_gattc_utils.cc @@ -145,7 +145,7 @@ 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->bta_conn_id == conn_id) { + if (p_clcb->in_use && p_clcb->bta_conn_id == conn_id) { return p_clcb.get(); } } @@ -960,6 +960,9 @@ void bta_gatt_client_dump(int fd) { 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: " << ADDRESS_TO_LOGGABLE_STR(p_clcb->bda) -- GitLab From 3166e689c0d117910dc99f76963de6d31a649e9b Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Thu, 3 Oct 2024 17:05:02 +0000 Subject: [PATCH 149/875] Pandora: mutualize pyright files Bug: 371207046 Test: N/A Change-Id: Ia6beb1a9479d5b500576951fc0372fbfa2bd2d18 --- OWNERS | 4 +-- android/pandora/mmi2grpc/pyrightconfig.json | 14 --------- android/pandora/test/pyrightconfig.json | 19 ------------ pyrightconfig.json | 34 +++++++++++++++++++++ 4 files changed, 36 insertions(+), 35 deletions(-) delete mode 100644 android/pandora/mmi2grpc/pyrightconfig.json delete mode 100644 android/pandora/test/pyrightconfig.json create mode 100644 pyrightconfig.json diff --git a/OWNERS b/OWNERS index a69eb5a72e7..70fe054e8b4 100644 --- a/OWNERS +++ b/OWNERS @@ -7,8 +7,8 @@ siyuanh@google.com #{LAST_RESORT_SUGGESTION} # Per-file ownership -# Build files / test_config / presubmit / preupload -per-file PREUPLOAD.cfg,TEST_MAPPING,*.bp,*.xml=file:/OWNERS_build +# Build files / test_config / presubmit / preupload / linter file +per-file PREUPLOAD.cfg,TEST_MAPPING,*.bp,*.xml,pyrightconfig.json=file:/OWNERS_build # ChromeOS team owns Linux build files # - build.py is used for Linux build diff --git a/android/pandora/mmi2grpc/pyrightconfig.json b/android/pandora/mmi2grpc/pyrightconfig.json deleted file mode 100644 index fab9f6135dc..00000000000 --- a/android/pandora/mmi2grpc/pyrightconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "typeCheckingMode": "strict", - "useLibraryCodeForTypes": true, - "verboseOutput": false, - "reportMissingTypeStubs": false, - "reportUnknownLambdaType": false, - "reportImportCycles": false, - "reportPrivateUsage": false, - "extraPaths": [ - "../../../pandora/server", - "../../../../../../out/soong/.intermediates/external/pandora/bt-test-interfaces/python/pandora-python-gen-src/gen/", - "../../../../../../out/soong/.intermediates/packages/modules/Bluetooth/pandora/interfaces/python/pandora_experimental-python-gen-src/gen/" - ] -} diff --git a/android/pandora/test/pyrightconfig.json b/android/pandora/test/pyrightconfig.json deleted file mode 100644 index ea458b5c646..00000000000 --- a/android/pandora/test/pyrightconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "typeCheckingMode": "strict", - "useLibraryCodeForTypes": true, - "verboseOutput": false, - "reportMissingTypeStubs": false, - "reportUnknownLambdaType": false, - "reportImportCycles": false, - "reportPrivateUsage": false, - "extraPaths": [ - "../../../pandora/server", - "../../../../../../external/pandora/avatar", - "../../../../../../external/python/bumble", - "../../../../../../external/python/mobly", - "../../../../../../external/python/pyee", - "../../../../../../external/python/portpicker/src", - "../../../../../../out/soong/.intermediates/external/pandora/bt-test-interfaces/python/pandora-python-gen-src/gen/", - "../../../../../../out/soong/.intermediates/packages/modules/Bluetooth/pandora/interfaces/python/pandora_experimental-python-gen-src/gen/" - ] -} \ No newline at end of file diff --git a/pyrightconfig.json b/pyrightconfig.json new file mode 100644 index 00000000000..e2b62afdf1d --- /dev/null +++ b/pyrightconfig.json @@ -0,0 +1,34 @@ +{ + "typeCheckingMode": "strict", + "useLibraryCodeForTypes": true, + "verboseOutput": false, + "reportMissingTypeStubs": false, + "reportUnknownLambdaType": false, + "reportImportCycles": false, + "reportPrivateUsage": false, + "executionEnvironments": [ + { + "root": "android/pandora/test", + "extraPaths": ["pandora/server"] + }, + { + "root": "android/pandora/mmi2grpc" + }, + { + "root": "pandora/server/bumble_experimental" + }, + { + "root": "framework/tests/bumble/src/bumble_server.py", + "extraPaths": ["pandora/server"] + } + ], + "extraPaths": [ + "../../../external/pandora/avatar", + "../../../external/python/bumble", + "../../../external/python/mobly", + "../../../external/python/pyee", + "../../../external/python/portpicker/src", + "../../../out/soong/.intermediates/external/pandora/bt-test-interfaces/python/pandora-python-gen-src/gen/", + "../../../out/soong/.intermediates/packages/modules/Bluetooth/pandora/interfaces/python/pandora_experimental-python-gen-src/gen/" + ] +} -- GitLab From 4cb73b3dfafedd9c8fde94a1db0f9a4a3814588d Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 3 Oct 2024 14:50:40 -0700 Subject: [PATCH 150/875] Add @okamil as project owner Bug: 331817295 Test: NA Flag: EXEMPT, owners change Change-Id: Ic98d0fdd40384b1c11ed58e7f7e443808c77c0e4 --- OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS b/OWNERS index a69eb5a72e7..f3eb92e010d 100644 --- a/OWNERS +++ b/OWNERS @@ -4,6 +4,7 @@ girardier@google.com #{LAST_RESORT_SUGGESTION} muhammadfalam@google.com #{LAST_RESORT_SUGGESTION} siyuanh@google.com #{LAST_RESORT_SUGGESTION} +okamil@google.com #{LAST_RESORT_SUGGESTION} # Per-file ownership -- GitLab From 23d827db636da031fc85f2bd2997b8a548552ca8 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Fri, 20 Sep 2024 22:42:37 +0000 Subject: [PATCH 151/875] [le audio] Resync device to its peer active broadcast source When remote device reconnected and its peer is still syncing to the source, we should assist this device to resync to the same source. Also this CL implements the queuing add source if the BASS state is not ready. With this, stack will handle the case if adding source happened before BASS state is ready. Bug: 364114064 Bug: 363168099 Test: atest BassClientServiceTest BassClientStateMachineTest Change-Id: Ie8876be3fc3393d720239b67671e2f26512ca3c2 --- .../bass_client/BassClientService.java | 59 +++++++++++++++++++ .../bass_client/BassClientStateMachine.java | 23 +++++--- .../bass_client/BassClientServiceTest.java | 54 +++++++++++++++++ .../BassClientStateMachineTest.java | 34 +++++++++++ 4 files changed, 163 insertions(+), 7 deletions(-) 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 05056d68247..4ab11649bea 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -3386,6 +3386,34 @@ public class BassClientService extends ProfileService { } } + /** Handle device newly connected and its peer device still has active source */ + private void checkAndResumeBroadcast(BluetoothDevice sink) { + BluetoothLeBroadcastMetadata metadata = mBroadcastMetadataMap.get(sink); + if (metadata == null) { + Log.d(TAG, "checkAndResumeBroadcast: no metadata available"); + return; + } + for (BluetoothDevice groupDevice : getTargetDeviceList(sink, true)) { + if (groupDevice.equals(sink)) { + continue; + } + // Check peer device + Optional receiver = + getOrCreateStateMachine(groupDevice).getAllSources().stream() + .filter(e -> e.getBroadcastId() == metadata.getBroadcastId()) + .findAny(); + if (receiver.isPresent() + && !getAllSources(sink).stream() + .anyMatch( + rs -> + (rs.getBroadcastId() + == receiver.get().getBroadcastId()))) { + Log.d(TAG, "checkAndResumeBroadcast: restore the source for device: " + sink); + addSource(sink, metadata, false); + } + } + } + private void logPausedBroadcastsAndSinks() { log( "mPausedBroadcastIds: " @@ -3796,6 +3824,7 @@ public class BassClientService extends ProfileService { private static final int MSG_SOURCE_REMOVED_FAILED = 11; private static final int MSG_RECEIVESTATE_CHANGED = 12; private static final int MSG_SOURCE_LOST = 13; + private static final int MSG_BASS_STATE_READY = 14; @GuardedBy("mCallbacksList") private final RemoteCallbackList mCallbacksList = @@ -3848,8 +3877,33 @@ public class BassClientService extends ProfileService { } } + private boolean handleServiceInternalMessage(Message msg) { + boolean isMsgHandled = false; + if (sService == null) { + Log.e(TAG, "Service is null"); + return isMsgHandled; + } + BluetoothDevice sink; + + switch (msg.what) { + case MSG_BASS_STATE_READY: + sink = (BluetoothDevice) msg.obj; + sService.checkAndResumeBroadcast(sink); + isMsgHandled = true; + break; + default: + break; + } + return isMsgHandled; + } + @Override public void handleMessage(Message msg) { + if (handleServiceInternalMessage(msg)) { + log("Handled internal message: " + msg.what); + return; + } + checkForPendingGroupOpRequest(msg); synchronized (mCallbacksList) { @@ -4108,6 +4162,11 @@ public class BassClientService extends ProfileService { sEventLogger.logd(TAG, "notifySourceLost: broadcastId: " + broadcastId); obtainMessage(MSG_SOURCE_LOST, 0, broadcastId).sendToTarget(); } + + void notifyBassStateReady(BluetoothDevice sink) { + sEventLogger.logd(TAG, "notifyBassStateReady: sink: " + sink); + obtainMessage(MSG_BASS_STATE_READY, sink).sendToTarget(); + } } @Override diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index 6ac75f70047..ce4eec02c9c 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState; +import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -968,6 +969,11 @@ public class BassClientStateMachine extends StateMachine { mBroadcastSyncStats.clear(); } + private boolean isSourceAbsent(BluetoothLeBroadcastReceiveState recvState) { + return recvState.getSourceDevice() == null + || recvState.getSourceDevice().getAddress().equals("00:00:00:00:00:00"); + } + private void checkAndUpdateBroadcastCode(BluetoothLeBroadcastReceiveState recvState) { log("checkAndUpdateBroadcastCode"); // Whenever receive state indicated code requested, assistant should set the broadcast code @@ -1149,14 +1155,18 @@ public class BassClientStateMachine extends StateMachine { return; } mBluetoothLeBroadcastReceiveStates.put(characteristic.getInstanceId(), recvState); - checkAndUpdateBroadcastCode(recvState); - processPASyncState(recvState); + if (!isSourceAbsent(recvState)) { + checkAndUpdateBroadcastCode(recvState); + processPASyncState(recvState); + } + if (leaudioBroadcastResyncHelper()) { + // Notify service BASS state ready for operations + mService.getCallbacks().notifyBassStateReady(mDevice); + } } else { log("Updated receiver state: " + recvState); mBluetoothLeBroadcastReceiveStates.replace(characteristic.getInstanceId(), recvState); - String emptyBluetoothDevice = "00:00:00:00:00:00"; - if (oldRecvState.getSourceDevice() == null - || oldRecvState.getSourceDevice().getAddress().equals(emptyBluetoothDevice)) { + if (isSourceAbsent(oldRecvState)) { log("New Source Addition"); removeMessages(CANCEL_PENDING_SOURCE_OPERATION); mService.getCallbacks() @@ -1170,8 +1180,7 @@ public class BassClientStateMachine extends StateMachine { processPASyncState(recvState); processSyncStateChangeStats(recvState); } else { - if (recvState.getSourceDevice() == null - || recvState.getSourceDevice().getAddress().equals(emptyBluetoothDevice)) { + if (isSourceAbsent(recvState)) { BluetoothDevice removedDevice = oldRecvState.getSourceDevice(); log("sourceInfo removal " + removedDevice); int prevSourceId = oldRecvState.getSourceId(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index bb75ed78cd9..d8137df4a1d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -6661,4 +6661,58 @@ public class BassClientServiceTest { .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); } + + /** + * Test add source will be triggered if new device connected and its peer is synced to broadcast + * source + */ + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void sinkBassStateReady_addSourceIfPeerDeviceSynced() { + // Imitate broadcast being active + doReturn(true).when(mLeAudioService).isPlaying(TEST_BROADCAST_ID); + prepareTwoSynchronizedDevicesForLocalBroadcast(); + + mBassClientService.getCallbacks().notifyBassStateReady(mCurrentDevice); + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + + assertThat(mStateMachines.size()).isEqualTo(2); + for (BassClientStateMachine sm : mStateMachines.values()) { + // No adding source if device remain synced + verify(sm, never()).sendMessage(any()); + } + + // Remove source on the mCurrentDevice + for (BassClientStateMachine sm : mStateMachines.values()) { + if (sm.getDevice().equals(mCurrentDevice)) { + injectRemoteSourceStateRemoval(sm, TEST_SOURCE_ID); + } + } + + mBassClientService.getCallbacks().notifyBassStateReady(mCurrentDevice); + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + + for (BassClientStateMachine sm : mStateMachines.values()) { + // Verify mCurrentDevice is resuming the broadcast + if (sm.getDevice().equals(mCurrentDevice1)) { + verify(sm, never()).sendMessage(any()); + } else if (sm.getDevice().equals(mCurrentDevice)) { + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(sm, atLeast(1)).sendMessage(messageCaptor.capture()); + + Message msg = + messageCaptor.getAllValues().stream() + .filter(m -> (m.what == BassClientStateMachine.ADD_BCAST_SOURCE)) + .findFirst() + .orElse(null); + assertThat(msg).isNotNull(); + clearInvocations(sm); + } else { + throw new AssertionError("Unexpected device"); + } + } + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index ebfba1eac8f..53fb242560a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -2519,6 +2519,39 @@ public class BassClientStateMachineTest { eq(0x3)); // STATS_SYNC_AUDIO_SYNC_SUCCESS } + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void sinkConnected_queueAddingSourceForReceiveStateReady() { + mBassClientStateMachine.connectGatt(true); + BluetoothGattCallback cb = mBassClientStateMachine.mGattCallback; + cb.onMtuChanged(null, 23, GATT_SUCCESS); + initToConnectedState(); + + mBassClientStateMachine.mNumOfBroadcastReceiverStates = 1; + BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); + when(mBassClientService.getCallbacks()).thenReturn(callbacks); + + BassClientStateMachine.BluetoothGattTestableWrapper btGatt = + Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class); + mBassClientStateMachine.mBluetoothGatt = btGatt; + BluetoothGattCharacteristic scanControlPoint = + Mockito.mock(BluetoothGattCharacteristic.class); + mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; + + // Initial receive state with empty source device + generateBroadcastReceiveStatesAndVerify( + mEmptyTestDevice, + TEST_SOURCE_ID, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, + BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + 0x0L); + // Verify notifyBassStateReady is called + verify(callbacks).notifyBassStateReady(eq(mTestDevice)); + } + private void initToConnectingState() { allowConnection(true); allowConnectGatt(true); @@ -2627,6 +2660,7 @@ public class BassClientStateMachineTest { private void prepareInitialReceiveStateForGatt() { initToConnectedState(); mBassClientStateMachine.connectGatt(true); + mBassClientStateMachine.mNumOfBroadcastReceiverStates = 2; BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); when(mBassClientService.getCallbacks()).thenReturn(callbacks); -- GitLab From e0198166c171834667d8f9f2196f29aab2f8be7a Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Thu, 12 Sep 2024 17:26:55 +0000 Subject: [PATCH 152/875] Fix OOB writes in gatt_sr.cc At various points in gatt_sr.cc, the output of the gatt_tcb_get_payload_size function is used without checking for a positive length. However, in exceptional cases it is possible for the channel to be closed at the time the function is called, which will lead to a zero length and cause an OOB write in subsequent processing. Fix all of these. Bug: 364026473 Bug: 364027038 Bug: 364027949 Bug: 364025411 Test: m libbluetooth Test: researcher POC Flag: EXEMPT trivial validity checks Tag: #security Ignore-AOSP-First: Security Merged-In: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404 Change-Id: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404 (cherry picked from commit 7de5617f7d5266fe57c990c428621b5d4e92728a) --- system/stack/gatt/gatt_sr.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 9e0c341db8e..81e4eb20733 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -760,6 +760,11 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t msg_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); @@ -795,6 +800,12 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint16_t cid, } uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t buf_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); @@ -935,6 +946,11 @@ static void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint16_t cid, uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t msg_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; @@ -1082,6 +1098,11 @@ static void gatts_process_read_req(tGATT_TCB& tcb, uint16_t cid, uint8_t* p_data) { uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t buf_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; uint16_t offset = 0; -- GitLab From 4eaac642cc47e628593248b1e2c759380674623e Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 3 Oct 2024 15:47:51 -0700 Subject: [PATCH 153/875] HeadsetClient Test: Truth & intent matcher Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: Id2a40f055c6e816ccf8d9fb9e7634d11e803491f --- .../HeadsetClientStateMachineTest.java | 857 ++++++++---------- 1 file changed, 369 insertions(+), 488 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 726dc14fa57..33c0e65e605 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -19,6 +19,9 @@ package com.android.bluetooth.hfpclient; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; import static android.content.pm.PackageManager.FEATURE_WATCH; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; + import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.AT_OK; import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.ENTER_PRIVATE_MODE; import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER; @@ -49,7 +52,6 @@ import android.os.Message; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Pair; -import androidx.test.espresso.intent.matcher.IntentMatchers; import androidx.test.filters.FlakyTest; import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; @@ -62,10 +64,9 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.RemoteDevices; import com.android.bluetooth.hfp.HeadsetService; +import org.hamcrest.Matcher; import org.hamcrest.core.AllOf; -import org.hamcrest.core.IsInstanceOf; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -160,9 +161,8 @@ public class HeadsetClientStateMachineTest { @SmallTest @Test public void testDefaultDisconnectedState() { - Assert.assertEquals( - mHeadsetClientStateMachine.getConnectionState(null), - BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetClientStateMachine.getConnectionState(null)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); } /** Test that an incoming connection with low priority is rejected */ @@ -180,25 +180,14 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that only DISCONNECTED -> DISCONNECTED broadcast is fired - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) - .sendBroadcastMultiplePermissions( - MockitoHamcrest.argThat( - AllOf.allOf( - IntentMatchers.hasAction( - BluetoothHeadsetClient - .ACTION_CONNECTION_STATE_CHANGED), - IntentMatchers.hasExtra( - BluetoothProfile.EXTRA_STATE, - BluetoothProfile.STATE_DISCONNECTED), - IntentMatchers.hasExtra( - BluetoothProfile.EXTRA_PREVIOUS_STATE, - BluetoothProfile.STATE_DISCONNECTED))), - any(String[].class), - any(BroadcastOptions.class)); - // Check we are in disconnected state still. - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class)); + verifySendBroadcastMultiplePermissions( + hasAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED), + hasExtra( + BluetoothProfile.EXTRA_PREVIOUS_STATE, + BluetoothProfile.STATE_DISCONNECTED)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); } /** Test that an incoming connection with high priority is accepted */ @@ -216,20 +205,11 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) - .sendBroadcastMultiplePermissions( - intentArgument1.capture(), - any(String[].class), - any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); - // Check we are in connecting state now. - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connecting.class); // Send a message to trigger SLC connection StackEvent slcEvent = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -242,19 +222,10 @@ public class HeadsetClientStateMachineTest { setUpAndroidAt(false); // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(2)) - .sendBroadcastMultiplePermissions( - intentArgument2.capture(), - any(String[].class), - any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - // Check we are in connecting state now. - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); } @@ -273,38 +244,22 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) - .sendBroadcastMultiplePermissions( - intentArgument1.capture(), - any(String[].class), - any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check we are in connecting state now. - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class)); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connecting.class); // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify( - mHeadsetClientService, - timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2).times(2)) + verify(mHeadsetClientService, timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2)) .sendBroadcastMultiplePermissions( - intentArgument2.capture(), + MockitoHamcrest.argThat( + hasExtra( + BluetoothProfile.EXTRA_STATE, + BluetoothProfile.STATE_DISCONNECTED)), any(String[].class), any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check we are in connecting state now. - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); } @@ -313,39 +268,49 @@ public class HeadsetClientStateMachineTest { initToConnectedState(); // True on correct AT command and BluetothDevice - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY)", mTestDevice)); - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand("+ANDROID: ()", mTestDevice)); - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (,,,)", mTestDevice)); - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE)", mTestDevice)); - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE,1,2,3),(1,2,3)", mTestDevice)); - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand("+ANDROID: 123", mTestDevice)); - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand("+ANDROID: ", mTestDevice)); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID: (SINKAUDIOPOLICY)", mTestDevice)) + .isTrue(); + assertThat(mHeadsetClientStateMachine.processAndroidSlcCommand("+ANDROID: ()", mTestDevice)) + .isTrue(); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID: (,,,)", mTestDevice)) + .isTrue(); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE)", mTestDevice)) + .isTrue(); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE,1,2,3),(1,2,3)", + mTestDevice)) + .isTrue(); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID: 123", mTestDevice)) + .isTrue(); + assertThat(mHeadsetClientStateMachine.processAndroidSlcCommand("+ANDROID: ", mTestDevice)) + .isTrue(); // False on incorrect AT command format - Assert.assertFalse( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID= (SINKAUDIOPOLICY)", mTestDevice)); - Assert.assertFalse( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "RANDOM ^%$# STRING", mTestDevice)); - Assert.assertFalse(mHeadsetClientStateMachine.processAndroidSlcCommand("", mTestDevice)); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID= (SINKAUDIOPOLICY)", mTestDevice)) + .isFalse(); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "RANDOM ^%$# STRING", mTestDevice)) + .isFalse(); + assertThat(mHeadsetClientStateMachine.processAndroidSlcCommand("", mTestDevice)).isFalse(); // False on incorrect BluetoothDevice - Assert.assertFalse( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY)", - mAdapter.getRemoteDevice("05:04:01:02:03:00"))); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID: (SINKAUDIOPOLICY)", + mAdapter.getRemoteDevice("05:04:01:02:03:00"))) + .isFalse(); } @Test @@ -353,28 +318,28 @@ public class HeadsetClientStateMachineTest { initToConnectedState(); mHeadsetClientStateMachine.setAudioPolicyRemoteSupported(false); - Assert.assertFalse( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "RANDOM ^%$# STRING", mTestDevice)); - Assert.assertEquals( - BluetoothStatusCodes.FEATURE_NOT_SUPPORTED, - mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "RANDOM ^%$# STRING", mTestDevice)) + .isFalse(); + assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) + .isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); mHeadsetClientStateMachine.setAudioPolicyRemoteSupported(false); - Assert.assertFalse( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID= (SINKAUDIOPOLICY)", mTestDevice)); - Assert.assertEquals( - BluetoothStatusCodes.FEATURE_NOT_SUPPORTED, - mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID= (SINKAUDIOPOLICY)", mTestDevice)) + .isFalse(); + assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) + .isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); mHeadsetClientStateMachine.setAudioPolicyRemoteSupported(false); - Assert.assertTrue( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY)", mTestDevice)); - Assert.assertEquals( - BluetoothStatusCodes.FEATURE_SUPPORTED, - mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()); + assertThat( + mHeadsetClientStateMachine.processAndroidSlcCommand( + "+ANDROID: (SINKAUDIOPOLICY)", mTestDevice)) + .isTrue(); + assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) + .isEqualTo(BluetoothStatusCodes.FEATURE_SUPPORTED); } /** Test that In Band Ringtone information is relayed from phone. */ @@ -386,7 +351,7 @@ public class HeadsetClientStateMachineTest { when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - Assert.assertEquals(false, mHeadsetClientStateMachine.getInBandRing()); + assertThat(mHeadsetClientStateMachine.getInBandRing()).isFalse(); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -394,20 +359,9 @@ public class HeadsetClientStateMachineTest { connStCh.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); - int expectedBroadcastIndex = 1; - int expectedBroadcastMultiplePermissionsIndex = 1; - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify( - mHeadsetClientService, - timeout(STANDARD_WAIT_MILLIS) - .times(expectedBroadcastMultiplePermissionsIndex++)) - .sendBroadcastMultiplePermissions( - intentArgument.capture(), any(String[].class), any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); // Send a message to trigger SLC connection StackEvent slcEvent = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -419,16 +373,8 @@ public class HeadsetClientStateMachineTest { setUpAndroidAt(false); - verify( - mHeadsetClientService, - timeout(STANDARD_WAIT_MILLIS) - .times(expectedBroadcastMultiplePermissionsIndex++)) - .sendBroadcastMultiplePermissions( - intentArgument.capture(), any(String[].class), any(BroadcastOptions.class)); - - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - intentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED)); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -441,24 +387,16 @@ public class HeadsetClientStateMachineTest { eventInBandRing.valueInt = 1; eventInBandRing.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventInBandRing); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(expectedBroadcastIndex++)) - .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); - Assert.assertEquals( - 1, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadsetClient.EXTRA_IN_BAND_RING, -1)); - Assert.assertEquals(true, mHeadsetClientStateMachine.getInBandRing()); + verifySendBroadcast(hasExtra(BluetoothHeadsetClient.EXTRA_IN_BAND_RING, 1)); + assertThat(mHeadsetClientStateMachine.getInBandRing()).isTrue(); // Simulate a new incoming phone call StackEvent eventCallStatusUpdated = new StackEvent(StackEvent.EVENT_TYPE_CLIP); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventCallStatusUpdated); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - verify( - mHeadsetClientService, - timeout(STANDARD_WAIT_MILLIS).times(expectedBroadcastIndex - 1)) - .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); + verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); // Provide information about the new call StackEvent eventIncomingCall = new StackEvent(StackEvent.EVENT_TYPE_CURRENT_CALLS); @@ -470,41 +408,33 @@ public class HeadsetClientStateMachineTest { eventIncomingCall.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventIncomingCall); - verify( - mHeadsetClientService, - timeout(STANDARD_WAIT_MILLIS).times(expectedBroadcastIndex - 1)) - .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); + verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); // Signal that the complete list of calls was received. StackEvent eventCommandStatus = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); eventCommandStatus.valueInt = AT_OK; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventCommandStatus); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - verify( - mHeadsetClientService, - timeout(QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS) - .times(expectedBroadcastIndex++)) + + ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); + verify(mHeadsetClientService, timeout(QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS).times(2)) .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); // Verify that the new call is being registered with the inBandRing flag set. - Assert.assertEquals( - true, - ((HfpClientCall) - intentArgument - .getValue() - .getParcelableExtra(BluetoothHeadsetClient.EXTRA_CALL)) - .isInBandRing()); + assertThat( + ((HfpClientCall) + intentArgument + .getValue() + .getParcelableExtra( + BluetoothHeadsetClient.EXTRA_CALL)) + .isInBandRing()) + .isTrue(); // Disable In Band Ring and verify state gets propagated. eventInBandRing.valueInt = 0; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventInBandRing); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(expectedBroadcastIndex++)) - .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); - Assert.assertEquals( - 0, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadsetClient.EXTRA_IN_BAND_RING, -1)); - Assert.assertEquals(false, mHeadsetClientStateMachine.getInBandRing()); + verifySendBroadcast(hasExtra(BluetoothHeadsetClient.EXTRA_IN_BAND_RING, 0)); + assertThat(mHeadsetClientStateMachine.getInBandRing()).isFalse(); } /** Test that wearables use {@code BluetoothHeadsetClientCall} in intent. */ @@ -551,43 +481,39 @@ public class HeadsetClientStateMachineTest { // Verify the broadcast ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, times(1)) + verify(mHeadsetClientService) .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); // Verify that the parcelable extra has a legacy {@code BluetoothHeadsetClientCall} type for // wearables. - Assert.assertThat( - intentArgument.getValue().getParcelableExtra(BluetoothHeadsetClient.EXTRA_CALL), - IsInstanceOf.instanceOf(BluetoothHeadsetClientCall.class)); + assertThat( + (Object) + intentArgument + .getValue() + .getParcelableExtra(BluetoothHeadsetClient.EXTRA_CALL)) + .isInstanceOf(BluetoothHeadsetClientCall.class); // To satisfy the @After verification verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); } /* Utility function to simulate HfpClient is connected. */ - private int setUpHfpClientConnection(int startBroadcastIndex) { + private void setUpHfpClientConnection() { // Trigger an incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); - ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(startBroadcastIndex)) - .sendBroadcastMultiplePermissions( - intentArgument.capture(), any(String[].class), any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - startBroadcastIndex++; - return startBroadcastIndex; + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); } /* Utility function to simulate SLC connection. */ - private int setUpServiceLevelConnection(int startBroadcastIndex) { - return setUpServiceLevelConnection(startBroadcastIndex, false); + private void setUpServiceLevelConnection() { + setUpServiceLevelConnection(false); } - private int setUpServiceLevelConnection(int startBroadcastIndex, boolean androidAtSupported) { + private void setUpServiceLevelConnection(boolean androidAtSupported) { // Trigger SLC connection StackEvent slcEvent = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); slcEvent.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED; @@ -599,20 +525,11 @@ public class HeadsetClientStateMachineTest { setUpAndroidAt(androidAtSupported); - ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(startBroadcastIndex)) - .sendBroadcastMultiplePermissions( - intentArgument.capture(), any(String[].class), any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - intentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); - - startBroadcastIndex++; - return startBroadcastIndex; } /** @@ -636,9 +553,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, cmdResEvt); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals( - BluetoothStatusCodes.FEATURE_SUPPORTED, - mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()); + assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) + .isEqualTo(BluetoothStatusCodes.FEATURE_SUPPORTED); } else { // receive CMD_RESULT CME_ERROR due to remote not supporting Android AT StackEvent cmdResEvt = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); @@ -647,9 +563,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, cmdResEvt); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals( - BluetoothStatusCodes.FEATURE_NOT_SUPPORTED, - mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()); + assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) + .isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); } } @@ -659,15 +574,15 @@ public class HeadsetClientStateMachineTest { when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); Message msg = mHeadsetClientStateMachine.obtainMessage( HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, vendorId, 0, atCommand); mHeadsetClientStateMachine.sendMessage(msg); - verify(mNativeInterface, timeout(STANDARD_WAIT_MILLIS).times(1)) + verify(mNativeInterface, timeout(STANDARD_WAIT_MILLIS)) .sendATCmd( mTestDevice, HeadsetClientHalConstants.HANDSFREECLIENT_AT_CMD_VENDOR_SPECIFIC_CMD, @@ -700,8 +615,8 @@ public class HeadsetClientStateMachineTest { when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); Message msg = mHeadsetClientStateMachine.obtainMessage( @@ -738,9 +653,8 @@ public class HeadsetClientStateMachineTest { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - int expectedBroadcastIndex = 1; - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); // Simulate a known event arrive String vendorEvent = vendorEventCode + vendorEventArgument; @@ -750,25 +664,11 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); // Validate broadcast intent - ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(expectedBroadcastIndex)) - .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); - Assert.assertEquals( - BluetoothHeadsetClient.ACTION_VENDOR_SPECIFIC_HEADSETCLIENT_EVENT, - intentArgument.getValue().getAction()); - Assert.assertEquals( - vendorId, - intentArgument.getValue().getIntExtra(BluetoothHeadsetClient.EXTRA_VENDOR_ID, -1)); - Assert.assertEquals( - vendorEventCode, - intentArgument - .getValue() - .getStringExtra(BluetoothHeadsetClient.EXTRA_VENDOR_EVENT_CODE)); - Assert.assertEquals( - vendorEvent, - intentArgument - .getValue() - .getStringExtra(BluetoothHeadsetClient.EXTRA_VENDOR_EVENT_FULL_ARGS)); + verifySendBroadcast( + hasAction(BluetoothHeadsetClient.ACTION_VENDOR_SPECIFIC_HEADSETCLIENT_EVENT), + hasExtra(BluetoothHeadsetClient.EXTRA_VENDOR_ID, vendorId), + hasExtra(BluetoothHeadsetClient.EXTRA_VENDOR_EVENT_CODE, vendorEventCode), + hasExtra(BluetoothHeadsetClient.EXTRA_VENDOR_EVENT_FULL_ARGS, vendorEvent)); } /** Test: supported vendor specific response: response to read command */ @@ -797,8 +697,8 @@ public class HeadsetClientStateMachineTest { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); // Simulate an unknown event arrive String vendorEvent = vendorEventCode + vendorEventArgument; @@ -842,9 +742,8 @@ public class HeadsetClientStateMachineTest { doReturn(true).when(mNativeInterface).startVoiceRecognition(any(BluetoothDevice.class)); doReturn(true).when(mNativeInterface).stopVoiceRecognition(any(BluetoothDevice.class)); - int expectedBroadcastIndex = 1; - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); // Simulate a voice recognition start mHeadsetClientStateMachine.sendMessage(VOICE_RECOGNITION_START); @@ -855,9 +754,11 @@ public class HeadsetClientStateMachineTest { event.valueInt = AT_OK; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); - expectedBroadcastIndex = - verifyVoiceRecognitionBroadcast( - expectedBroadcastIndex, HeadsetClientHalConstants.VR_STATE_STARTED); + verifySendBroadcast( + hasAction(BluetoothHeadsetClient.ACTION_AG_EVENT), + hasExtra( + BluetoothHeadsetClient.EXTRA_VOICE_RECOGNITION, + HeadsetClientHalConstants.VR_STATE_STARTED)); // Simulate a voice recognition stop mHeadsetClientStateMachine.sendMessage(VOICE_RECOGNITION_STOP); @@ -868,23 +769,11 @@ public class HeadsetClientStateMachineTest { event.valueInt = AT_OK; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); - verifyVoiceRecognitionBroadcast( - expectedBroadcastIndex, HeadsetClientHalConstants.VR_STATE_STOPPED); - } - - private int verifyVoiceRecognitionBroadcast(int expectedBroadcastIndex, int expectedState) { - // Validate broadcast intent - ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(expectedBroadcastIndex)) - .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); - Assert.assertEquals( - BluetoothHeadsetClient.ACTION_AG_EVENT, intentArgument.getValue().getAction()); - int state = - intentArgument - .getValue() - .getIntExtra(BluetoothHeadsetClient.EXTRA_VOICE_RECOGNITION, -1); - Assert.assertEquals(expectedState, state); - return expectedBroadcastIndex + 1; + verifySendBroadcast( + hasAction(BluetoothHeadsetClient.ACTION_AG_EVENT), + hasExtra( + BluetoothHeadsetClient.EXTRA_VOICE_RECOGNITION, + HeadsetClientHalConstants.VR_STATE_STOPPED)); } /** Test send BIEV command */ @@ -894,8 +783,8 @@ public class HeadsetClientStateMachineTest { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); int indicator_id = 2; int indicator_value = 50; @@ -906,7 +795,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(msg); - verify(mNativeInterface, timeout(STANDARD_WAIT_MILLIS).times(1)) + verify(mNativeInterface, timeout(STANDARD_WAIT_MILLIS)) .sendATCmd( mTestDevice, HeadsetClientHalConstants.HANDSFREECLIENT_AT_CMD_BIEV, @@ -925,10 +814,10 @@ public class HeadsetClientStateMachineTest { when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS).times(1)).updateBatteryLevel(); + verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)).updateBatteryLevel(); } @Test @@ -948,8 +837,8 @@ public class HeadsetClientStateMachineTest { mTestDevice, 0, HfpClientCall.CALL_STATE_WAITING, "1", false, false, false); mHeadsetClientStateMachine.mCalls.put(0, call); - Assert.assertEquals( - mHeadsetClientStateMachine.callsInState(HfpClientCall.CALL_STATE_WAITING), 1); + assertThat(mHeadsetClientStateMachine.callsInState(HfpClientCall.CALL_STATE_WAITING)) + .isEqualTo(1); } @Test @@ -965,7 +854,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.enterPrivateMode(0); Pair expectedPair = new Pair(ENTER_PRIVATE_MODE, call); - Assert.assertEquals(mHeadsetClientStateMachine.mQueuedActions.peek(), expectedPair); + assertThat(mHeadsetClientStateMachine.mQueuedActions.peek()).isEqualTo(expectedPair); } @Test @@ -985,14 +874,14 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.explicitCallTransfer(); Pair expectedPair = new Pair(EXPLICIT_CALL_TRANSFER, 0); - Assert.assertEquals(mHeadsetClientStateMachine.mQueuedActions.peek(), expectedPair); + assertThat(mHeadsetClientStateMachine.mQueuedActions.peek()).isEqualTo(expectedPair); } @Test public void testSetAudioRouteAllowed() { mHeadsetClientStateMachine.setAudioRouteAllowed(true); - Assert.assertTrue(mHeadsetClientStateMachine.getAudioRouteAllowed()); + assertThat(mHeadsetClientStateMachine.getAudioRouteAllowed()).isTrue(); // Case 1: if remote is not supported // Expect: Should not send +ANDROID to remote @@ -1020,11 +909,10 @@ public class HeadsetClientStateMachineTest { @Test public void testGetAudioState_withCurrentDeviceNull() { - Assert.assertNull(mHeadsetClientStateMachine.mCurrentDevice); + assertThat(mHeadsetClientStateMachine.mCurrentDevice).isNull(); - Assert.assertEquals( - mHeadsetClientStateMachine.getAudioState(mTestDevice), - BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED); + assertThat(mHeadsetClientStateMachine.getAudioState(mTestDevice)) + .isEqualTo(BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED); } @Test @@ -1033,7 +921,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.mAudioState = audioState; mHeadsetClientStateMachine.mCurrentDevice = mTestDevice; - Assert.assertEquals(mHeadsetClientStateMachine.getAudioState(mTestDevice), audioState); + assertThat(mHeadsetClientStateMachine.getAudioState(mTestDevice)).isEqualTo(audioState); } @Test @@ -1045,7 +933,7 @@ public class HeadsetClientStateMachineTest { int[] states = new int[1]; states[0] = HfpClientCall.CALL_STATE_ACTIVE; - Assert.assertEquals(mHeadsetClientStateMachine.getCall(states), call); + assertThat(mHeadsetClientStateMachine.getCall(states)).isEqualTo(call); } @Test @@ -1057,52 +945,48 @@ public class HeadsetClientStateMachineTest { int[] states = new int[1]; states[0] = HfpClientCall.CALL_STATE_ACTIVE; - Assert.assertNull(mHeadsetClientStateMachine.getCall(states)); + assertThat(mHeadsetClientStateMachine.getCall(states)).isNull(); } @Test public void testGetConnectionState_withNullDevice() { - Assert.assertEquals( - mHeadsetClientStateMachine.getConnectionState(null), - BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetClientStateMachine.getConnectionState(null)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); } @Test public void testGetConnectionState_withNonNullDevice() { mHeadsetClientStateMachine.mCurrentDevice = mTestDevice; - Assert.assertEquals( - mHeadsetClientStateMachine.getConnectionState(mTestDevice), - BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetClientStateMachine.getConnectionState(mTestDevice)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); } @Test public void testGetConnectionStateFromAudioState() { - Assert.assertEquals( - HeadsetClientStateMachine.getConnectionStateFromAudioState( - BluetoothHeadsetClient.STATE_AUDIO_CONNECTED), - BluetoothAdapter.STATE_CONNECTED); - Assert.assertEquals( - HeadsetClientStateMachine.getConnectionStateFromAudioState( - BluetoothHeadsetClient.STATE_AUDIO_CONNECTING), - BluetoothAdapter.STATE_CONNECTING); - Assert.assertEquals( - HeadsetClientStateMachine.getConnectionStateFromAudioState( - BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED), - BluetoothAdapter.STATE_DISCONNECTED); + assertThat( + HeadsetClientStateMachine.getConnectionStateFromAudioState( + BluetoothHeadsetClient.STATE_AUDIO_CONNECTED)) + .isEqualTo(BluetoothAdapter.STATE_CONNECTED); + assertThat( + HeadsetClientStateMachine.getConnectionStateFromAudioState( + BluetoothHeadsetClient.STATE_AUDIO_CONNECTING)) + .isEqualTo(BluetoothAdapter.STATE_CONNECTING); + assertThat( + HeadsetClientStateMachine.getConnectionStateFromAudioState( + BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED)) + .isEqualTo(BluetoothAdapter.STATE_DISCONNECTED); int invalidAudioState = 3; - Assert.assertEquals( - HeadsetClientStateMachine.getConnectionStateFromAudioState(invalidAudioState), - BluetoothAdapter.STATE_DISCONNECTED); + assertThat(HeadsetClientStateMachine.getConnectionStateFromAudioState(invalidAudioState)) + .isEqualTo(BluetoothAdapter.STATE_DISCONNECTED); } @Test public void testGetCurrentAgEvents() { Bundle bundle = mHeadsetClientStateMachine.getCurrentAgEvents(); - Assert.assertEquals( - bundle.getString(BluetoothHeadsetClient.EXTRA_SUBSCRIBER_INFO), - mHeadsetClientStateMachine.mSubscriberInfo); + assertThat(bundle.getString(BluetoothHeadsetClient.EXTRA_SUBSCRIBER_INFO)) + .isEqualTo(mHeadsetClientStateMachine.mSubscriberInfo); } @Test @@ -1110,30 +994,30 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_3WAY; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC; Set features = mHeadsetClientStateMachine.getCurrentAgFeatures(); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_3WAY)); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC)); + assertThat(features.contains(HeadsetClientHalConstants.PEER_FEAT_3WAY)).isTrue(); + assertThat(features.contains(HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC)).isTrue(); mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_VREC; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL; features = mHeadsetClientStateMachine.getCurrentAgFeatures(); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_VREC)); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_REL)); + assertThat(features.contains(HeadsetClientHalConstants.PEER_FEAT_VREC)).isTrue(); + assertThat(features.contains(HeadsetClientHalConstants.CHLD_FEAT_REL)).isTrue(); mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_REJECT; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL_ACC; features = mHeadsetClientStateMachine.getCurrentAgFeatures(); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_REJECT)); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_REL_ACC)); + assertThat(features.contains(HeadsetClientHalConstants.PEER_FEAT_REJECT)).isTrue(); + assertThat(features.contains(HeadsetClientHalConstants.CHLD_FEAT_REL_ACC)).isTrue(); mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_ECC; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE; features = mHeadsetClientStateMachine.getCurrentAgFeatures(); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.PEER_FEAT_ECC)); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_MERGE)); + assertThat(features.contains(HeadsetClientHalConstants.PEER_FEAT_ECC)).isTrue(); + assertThat(features.contains(HeadsetClientHalConstants.CHLD_FEAT_MERGE)).isTrue(); mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH; features = mHeadsetClientStateMachine.getCurrentAgFeatures(); - Assert.assertTrue(features.contains(HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH)); + assertThat(features.contains(HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH)).isTrue(); } @Test @@ -1141,37 +1025,42 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_3WAY; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC; Bundle bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle(); - Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_3WAY_CALLING)); - Assert.assertTrue( - bundle.getBoolean( - BluetoothHeadsetClient.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL)); + assertThat(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_3WAY_CALLING)) + .isTrue(); + assertThat( + bundle.getBoolean( + BluetoothHeadsetClient + .EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL)) + .isTrue(); mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_VREC; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL; bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle(); - Assert.assertTrue( - bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_VOICE_RECOGNITION)); - Assert.assertTrue( - bundle.getBoolean( - BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL)); + assertThat(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_VOICE_RECOGNITION)) + .isTrue(); + assertThat( + bundle.getBoolean( + BluetoothHeadsetClient + .EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL)) + .isTrue(); mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_REJECT; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_REL_ACC; bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle(); - Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_REJECT_CALL)); - Assert.assertTrue( - bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT)); + assertThat(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_REJECT_CALL)).isTrue(); + assertThat(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT)) + .isTrue(); mHeadsetClientStateMachine.mPeerFeatures = HeadsetClientHalConstants.PEER_FEAT_ECC; mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE; bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle(); - Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ECC)); - Assert.assertTrue(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE)); + assertThat(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ECC)).isTrue(); + assertThat(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE)).isTrue(); mHeadsetClientStateMachine.mChldFeatures = HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH; bundle = mHeadsetClientStateMachine.getCurrentAgFeaturesBundle(); - Assert.assertTrue( - bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE_AND_DETACH)); + assertThat(bundle.getBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE_AND_DETACH)) + .isTrue(); } @Test @@ -1183,91 +1072,82 @@ public class HeadsetClientStateMachineTest { List currentCalls = mHeadsetClientStateMachine.getCurrentCalls(); - Assert.assertEquals(currentCalls.get(0), call); + assertThat(currentCalls.get(0)).isEqualTo(call); } @Test public void testGetMessageName() { - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(StackEvent.STACK_EVENT), "STACK_EVENT"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.CONNECT), - "CONNECT"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISCONNECT), - "DISCONNECT"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.CONNECT_AUDIO), - "CONNECT_AUDIO"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.DISCONNECT_AUDIO), - "DISCONNECT_AUDIO"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_START), - "VOICE_RECOGNITION_START"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_STOP), - "VOICE_RECOGNITION_STOP"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SET_MIC_VOLUME), - "SET_MIC_VOLUME"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.SET_SPEAKER_VOLUME), - "SET_SPEAKER_VOLUME"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DIAL_NUMBER), - "DIAL_NUMBER"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.ACCEPT_CALL), - "ACCEPT_CALL"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.REJECT_CALL), - "REJECT_CALL"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.HOLD_CALL), - "HOLD_CALL"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.TERMINATE_CALL), - "TERMINATE_CALL"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(ENTER_PRIVATE_MODE), "ENTER_PRIVATE_MODE"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_DTMF), - "SEND_DTMF"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(EXPLICIT_CALL_TRANSFER), - "EXPLICIT_CALL_TRANSFER"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISABLE_NREC), - "DISABLE_NREC"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND), - "SEND_VENDOR_AT_COMMAND"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_BIEV), - "SEND_BIEV"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.QUERY_CURRENT_CALLS), - "QUERY_CURRENT_CALLS"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.QUERY_OPERATOR_NAME), - "QUERY_OPERATOR_NAME"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SUBSCRIBER_INFO), - "SUBSCRIBER_INFO"); - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.CONNECTING_TIMEOUT), - "CONNECTING_TIMEOUT"); + assertThat(HeadsetClientStateMachine.getMessageName(StackEvent.STACK_EVENT)) + .isEqualTo("STACK_EVENT"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.CONNECT)) + .isEqualTo("CONNECT"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISCONNECT)) + .isEqualTo("DISCONNECT"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.CONNECT_AUDIO)) + .isEqualTo("CONNECT_AUDIO"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.DISCONNECT_AUDIO)) + .isEqualTo("DISCONNECT_AUDIO"); + assertThat(HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_START)) + .isEqualTo("VOICE_RECOGNITION_START"); + assertThat(HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_STOP)) + .isEqualTo("VOICE_RECOGNITION_STOP"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.SET_MIC_VOLUME)) + .isEqualTo("SET_MIC_VOLUME"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.SET_SPEAKER_VOLUME)) + .isEqualTo("SET_SPEAKER_VOLUME"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DIAL_NUMBER)) + .isEqualTo("DIAL_NUMBER"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.ACCEPT_CALL)) + .isEqualTo("ACCEPT_CALL"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.REJECT_CALL)) + .isEqualTo("REJECT_CALL"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.HOLD_CALL)) + .isEqualTo("HOLD_CALL"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.TERMINATE_CALL)) + .isEqualTo("TERMINATE_CALL"); + assertThat(HeadsetClientStateMachine.getMessageName(ENTER_PRIVATE_MODE)) + .isEqualTo("ENTER_PRIVATE_MODE"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_DTMF)) + .isEqualTo("SEND_DTMF"); + assertThat(HeadsetClientStateMachine.getMessageName(EXPLICIT_CALL_TRANSFER)) + .isEqualTo("EXPLICIT_CALL_TRANSFER"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISABLE_NREC)) + .isEqualTo("DISABLE_NREC"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND)) + .isEqualTo("SEND_VENDOR_AT_COMMAND"); + assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_BIEV)) + .isEqualTo("SEND_BIEV"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.QUERY_CURRENT_CALLS)) + .isEqualTo("QUERY_CURRENT_CALLS"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.QUERY_OPERATOR_NAME)) + .isEqualTo("QUERY_OPERATOR_NAME"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.SUBSCRIBER_INFO)) + .isEqualTo("SUBSCRIBER_INFO"); + assertThat( + HeadsetClientStateMachine.getMessageName( + HeadsetClientStateMachine.CONNECTING_TIMEOUT)) + .isEqualTo("CONNECTING_TIMEOUT"); int unknownMessageInt = 54; - Assert.assertEquals( - HeadsetClientStateMachine.getMessageName(unknownMessageInt), - "UNKNOWN(" + unknownMessageInt + ")"); + assertThat(HeadsetClientStateMachine.getMessageName(unknownMessageInt)) + .isEqualTo("UNKNOWN(" + unknownMessageInt + ")"); } /** @@ -1280,8 +1160,8 @@ public class HeadsetClientStateMachineTest { when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2); + setUpHfpClientConnection(); + setUpServiceLevelConnection(); BluetoothSinkAudioPolicy dummyAudioPolicy = new BluetoothSinkAudioPolicy.Builder().build(); mHeadsetClientStateMachine.setAudioPolicy(dummyAudioPolicy); @@ -1296,8 +1176,8 @@ public class HeadsetClientStateMachineTest { when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(1); - setUpServiceLevelConnection(2, true); + setUpHfpClientConnection(); + setUpServiceLevelConnection(true); BluetoothSinkAudioPolicy dummyAudioPolicy = new BluetoothSinkAudioPolicy.Builder() @@ -1312,19 +1192,19 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.setAudioPolicy(dummyAudioPolicy); verify(mNativeInterface, never()) .sendAndroidAt(mTestDevice, "+ANDROID=SINKAUDIOPOLICY,1,2,1"); - Assert.assertEquals(0, mHeadsetClientStateMachine.mQueuedActions.size()); + assertThat(mHeadsetClientStateMachine.mQueuedActions).isEmpty(); // Test setAudioPolicy mHeadsetClientStateMachine.setAudioPolicyRemoteSupported(true); mHeadsetClientStateMachine.setAudioPolicy(dummyAudioPolicy); verify(mNativeInterface).sendAndroidAt(mTestDevice, "+ANDROID=SINKAUDIOPOLICY,1,2,1"); - Assert.assertEquals(1, mHeadsetClientStateMachine.mQueuedActions.size()); + assertThat(mHeadsetClientStateMachine.mQueuedActions.size()).isEqualTo(1); mHeadsetClientStateMachine.mQueuedActions.clear(); // Test if fail to sendAndroidAt doReturn(false).when(mNativeInterface).sendAndroidAt(anyObject(), anyString()); mHeadsetClientStateMachine.setAudioPolicy(dummyAudioPolicy); - Assert.assertEquals(0, mHeadsetClientStateMachine.mQueuedActions.size()); + assertThat(mHeadsetClientStateMachine.mQueuedActions).isEmpty(); } @Test @@ -1335,8 +1215,7 @@ public class HeadsetClientStateMachineTest { // Check if set default policy when Connecting -> Connected // The testing sys prop is 0. It is ok to check if set audio policy while leaving connecting // state. - verify(mNativeInterface, times(1)) - .sendAndroidAt(mTestDevice, "+ANDROID=SINKAUDIOPOLICY,0,0,0"); + verify(mNativeInterface).sendAndroidAt(mTestDevice, "+ANDROID=SINKAUDIOPOLICY,0,0,0"); // Check if won't set default policy when AudioOn -> Connected // Transit to AudioOn @@ -1347,9 +1226,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.AudioOn.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); // Back to Connected event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); @@ -1358,12 +1236,10 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); - verify(mNativeInterface, times(1)) - .sendAndroidAt(mTestDevice, "+ANDROID=SINKAUDIOPOLICY,0,0,0"); + verify(mNativeInterface).sendAndroidAt(mTestDevice, "+ANDROID=SINKAUDIOPOLICY,0,0,0"); } @Test @@ -1375,8 +1251,8 @@ public class HeadsetClientStateMachineTest { public void testProcessDisconnectMessage_onDisconnectedState() { mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals( - STATE_DISCONNECTED, mHeadsetClientStateMachine.getConnectionState(mTestDevice)); + assertThat(mHeadsetClientStateMachine.getConnectionState(mTestDevice)) + .isEqualTo(STATE_DISCONNECTED); } @Test @@ -1419,9 +1295,10 @@ public class HeadsetClientStateMachineTest { .isFalse(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertTrue( - mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( - HeadsetClientStateMachine.CONNECT)); + assertThat( + mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( + HeadsetClientStateMachine.CONNECT)) + .isTrue(); } @Test @@ -1444,9 +1321,8 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connecting.class); } @Test @@ -1457,9 +1333,8 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connecting.class); } @Test @@ -1473,8 +1348,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertTrue( - mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)); + assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)) + .isTrue(); } @Test @@ -1485,9 +1360,8 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connecting.class); } @Test @@ -1501,9 +1375,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); } @@ -1537,9 +1410,8 @@ public class HeadsetClientStateMachineTest { initToConnectedState(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); } @Test @@ -1583,9 +1455,10 @@ public class HeadsetClientStateMachineTest { .isFalse(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertTrue( - mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( - HeadsetClientStateMachine.DISCONNECT)); + assertThat( + mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( + HeadsetClientStateMachine.DISCONNECT)) + .isTrue(); } @Test @@ -1614,44 +1487,39 @@ public class HeadsetClientStateMachineTest { @Test public void testProcessStackEvent_ConnectionStateChanged_onAudioOnState() { initToAudioOnState(); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.AudioOn.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED; event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); } @Test public void testProcessStackEvent_AudioStateChanged_onAudioOnState() { initToAudioOnState(); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.AudioOn.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED; event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); } @Test public void testProcessStackEvent_CodecSelection_onConnectedState() { initToConnectedState(); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); // Trigger a MSBC codec stack event. Expect to mAudioWbs = true. mHeadsetClientStateMachine.mAudioWbs = false; @@ -1662,8 +1530,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertTrue(mHeadsetClientStateMachine.mAudioWbs); - Assert.assertFalse(mHeadsetClientStateMachine.mAudioSWB); + assertThat(mHeadsetClientStateMachine.mAudioWbs).isTrue(); + assertThat(mHeadsetClientStateMachine.mAudioSWB).isFalse(); // Trigger a LC3 codec stack event. Expect to mAudioSWB = true. mHeadsetClientStateMachine.mAudioWbs = false; @@ -1674,8 +1542,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertFalse(mHeadsetClientStateMachine.mAudioWbs); - Assert.assertTrue(mHeadsetClientStateMachine.mAudioSWB); + assertThat(mHeadsetClientStateMachine.mAudioWbs).isFalse(); + assertThat(mHeadsetClientStateMachine.mAudioSWB).isTrue(); } /** @@ -1704,9 +1572,8 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); } @@ -1719,9 +1586,24 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetClientStateMachine.AudioOn.class)); + assertThat(mHeadsetClientStateMachine.getCurrentState()) + .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); + } + + private void verifySendBroadcastMultiplePermissions(Matcher... matchers) { + verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + .sendBroadcastMultiplePermissions( + MockitoHamcrest.argThat(AllOf.allOf(matchers)), + any(String[].class), + any(BroadcastOptions.class)); + } + + private void verifySendBroadcast(Matcher... matchers) { + verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + .sendBroadcast( + MockitoHamcrest.argThat(AllOf.allOf(matchers)), + anyString(), + any(Bundle.class)); } private void sendMessageAndVerifyTransition(Message msg, Class type) { @@ -1731,8 +1613,7 @@ public class HeadsetClientStateMachineTest { verify(mHeadsetClientService, timeout(TIMEOUT_MS)) .sendBroadcastMultiplePermissions( any(Intent.class), any(String[].class), any(BroadcastOptions.class)); - Assert.assertThat( - mHeadsetClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); + assertThat(mHeadsetClientStateMachine.getCurrentState()).isInstanceOf(type); } public static class TestHeadsetClientStateMachine extends HeadsetClientStateMachine { -- GitLab From c9164e9e07e40066dc60d2539f88700282a8f225 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Fri, 4 Oct 2024 00:07:55 +0000 Subject: [PATCH 154/875] Add UnicastGameGatewayCharacteristicUuid Bug: 350102910 Bug: 353978074 Change-Id: Ia6cb57b08182cf314d01dc69110bcefdf7f65c32 Test: atest --host bluetooth_le_audio_client_test Flag: com.android.bluetooth.flags.leaudio_gmap_client --- system/bta/le_audio/le_audio_types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/bta/le_audio/le_audio_types.h b/system/bta/le_audio/le_audio_types.h index c42c30150a1..54e3898cb1a 100644 --- a/system/bta/le_audio/le_audio_types.h +++ b/system/bta/le_audio/le_audio_types.h @@ -103,6 +103,8 @@ static const bluetooth::Uuid kTelephonyMediaAudioProfileRoleCharacteristicUuid = /* Gaming Audio Service Characteristics */ static const bluetooth::Uuid kRoleCharacteristicUuid = bluetooth::Uuid::From16Bit(0x2C00); +static const bluetooth::Uuid kUnicastGameGatewayCharacteristicUuid = + bluetooth::Uuid::From16Bit(0x2C01); static const bluetooth::Uuid kUnicastGameTerminalCharacteristicUuid = bluetooth::Uuid::From16Bit(0x2C02); } // namespace uuid -- GitLab From 3e5d1e5111f267074933af98fc2226b62169f1a2 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 3 Oct 2024 16:52:45 -0700 Subject: [PATCH 155/875] HeadsetClient Test: remove clearInvocation Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I6be817121ebe336743777e1df5429d2dc5e647bd --- .../HeadsetClientStateMachineTest.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 33c0e65e605..0ec87000ef4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -73,7 +73,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -107,7 +106,6 @@ public class HeadsetClientStateMachineTest { private static final int QUERY_CURRENT_CALLS_WAIT_MILLIS = 2000; private static final int QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS = QUERY_CURRENT_CALLS_WAIT_MILLIS * 3 / 2; - private static final int TIMEOUT_MS = 1000; @Before public void setUp() throws Exception { @@ -1383,10 +1381,10 @@ public class HeadsetClientStateMachineTest { @Test public void testProcessConnectTimeoutMessage_onConnectingState() { initToConnectingState(); - Message msg = + sendMessageAndVerifyTransition( mHeadsetClientStateMachine.obtainMessage( - HeadsetClientStateMachine.CONNECTING_TIMEOUT); - sendMessageAndVerifyTransition(msg, HeadsetClientStateMachine.Disconnected.class); + HeadsetClientStateMachine.CONNECTING_TIMEOUT), + HeadsetClientStateMachine.Disconnected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); } @@ -1607,12 +1605,16 @@ public class HeadsetClientStateMachineTest { } private void sendMessageAndVerifyTransition(Message msg, Class type) { - Mockito.clearInvocations(mHeadsetClientService); + int previousState = mHeadsetClientStateMachine.getConnectionState(mTestDevice); + mHeadsetClientStateMachine.sendMessage(msg); - // Verify that one connection state broadcast is executed - verify(mHeadsetClientService, timeout(TIMEOUT_MS)) - .sendBroadcastMultiplePermissions( - any(Intent.class), any(String[].class), any(BroadcastOptions.class)); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + + int newState = mHeadsetClientStateMachine.getConnectionState(mTestDevice); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, previousState), + hasExtra(BluetoothProfile.EXTRA_STATE, newState)); + assertThat(mHeadsetClientStateMachine.getCurrentState()).isInstanceOf(type); } -- GitLab From d4f7a4e89f7915202754ecda197d4476049eaf13 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 3 Oct 2024 16:52:45 -0700 Subject: [PATCH 156/875] HeadsetClient Test: force intent order Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I6060f226d88d250eb46654acafd157ead57daa9f --- .../HeadsetClientStateMachineTest.java | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 0ec87000ef4..7416a53a040 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -72,6 +72,7 @@ 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.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; @@ -87,6 +88,7 @@ public class HeadsetClientStateMachineTest { private BluetoothAdapter mAdapter; private HandlerThread mHandlerThread; private TestHeadsetClientStateMachine mHeadsetClientStateMachine; + private InOrder mInOrder; private BluetoothDevice mTestDevice; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -109,6 +111,7 @@ public class HeadsetClientStateMachineTest { @Before public void setUp() throws Exception { + mInOrder = inOrder(mHeadsetClientService); // Setup mocks and test assets // Set a valid volume when(mAudioManager.getStreamVolume(anyInt())).thenReturn(2); @@ -248,7 +251,9 @@ public class HeadsetClientStateMachineTest { .isInstanceOf(HeadsetClientStateMachine.Connecting.class); // Verify that one connection state broadcast is executed - verify(mHeadsetClientService, timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2)) + mInOrder.verify( + mHeadsetClientService, + timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2)) .sendBroadcastMultiplePermissions( MockitoHamcrest.argThat( hasExtra( @@ -393,7 +398,7 @@ public class HeadsetClientStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventCallStatusUpdated); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + mInOrder.verify(mHeadsetClientService, never()) .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); // Provide information about the new call @@ -406,7 +411,8 @@ public class HeadsetClientStateMachineTest { eventIncomingCall.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventIncomingCall); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mInOrder.verify(mHeadsetClientService, never()) .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); // Signal that the complete list of calls was received. @@ -416,17 +422,15 @@ public class HeadsetClientStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService, timeout(QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS).times(2)) + mInOrder.verify(mHeadsetClientService, timeout(QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS)) .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); // Verify that the new call is being registered with the inBandRing flag set. - assertThat( - ((HfpClientCall) - intentArgument - .getValue() - .getParcelableExtra( - BluetoothHeadsetClient.EXTRA_CALL)) - .isInBandRing()) - .isTrue(); + HfpClientCall clientCall = + (HfpClientCall) + intentArgument + .getValue() + .getParcelableExtra(BluetoothHeadsetClient.EXTRA_CALL); + assertThat(clientCall.isInBandRing()).isTrue(); // Disable In Band Ring and verify state gets propagated. eventInBandRing.valueInt = 0; @@ -479,17 +483,17 @@ public class HeadsetClientStateMachineTest { // Verify the broadcast ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - verify(mHeadsetClientService) + mInOrder.verify(mHeadsetClientService) .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); // Verify that the parcelable extra has a legacy {@code BluetoothHeadsetClientCall} type for // wearables. - assertThat( - (Object) - intentArgument - .getValue() - .getParcelableExtra(BluetoothHeadsetClient.EXTRA_CALL)) - .isInstanceOf(BluetoothHeadsetClientCall.class); + Object clientCall = + (Object) + intentArgument + .getValue() + .getParcelableExtra(BluetoothHeadsetClient.EXTRA_CALL); + assertThat(clientCall).isInstanceOf(BluetoothHeadsetClientCall.class); // To satisfy the @After verification verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -825,7 +829,7 @@ public class HeadsetClientStateMachineTest { BluetoothHeadsetClient.STATE_AUDIO_CONNECTED, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING); - verify(mHeadsetClientService).sendBroadcast(any(), any(), any()); + mInOrder.verify(mHeadsetClientService).sendBroadcast(any(), any(), any()); } @Test @@ -1589,7 +1593,7 @@ public class HeadsetClientStateMachineTest { } private void verifySendBroadcastMultiplePermissions(Matcher... matchers) { - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + mInOrder.verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) .sendBroadcastMultiplePermissions( MockitoHamcrest.argThat(AllOf.allOf(matchers)), any(String[].class), @@ -1597,7 +1601,7 @@ public class HeadsetClientStateMachineTest { } private void verifySendBroadcast(Matcher... matchers) { - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + mInOrder.verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) .sendBroadcast( MockitoHamcrest.argThat(AllOf.allOf(matchers)), anyString(), -- GitLab From 649e521c14a76fe37e9df66fde8c82a66455f9e9 Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Fri, 4 Oct 2024 11:54:49 +0800 Subject: [PATCH 157/875] floss: Re-enable ReadFailedContactCounter The issue has been fixed in FW, thus removing this Bug: 249876976 Tag: #floss Test: mmm packages/modules/Bluetooth Test: Play audio on Brya (AX211), move the headset far to trigger buffer overflow, Floss doesn't crash Flag: EXEMPT, Floss-only change Change-Id: I955d55d49e48a757ca7d002ff74947acef13048c --- system/btif/src/btif_a2dp_source.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 38c45cc78e0..b9004718dc1 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -1013,18 +1013,10 @@ static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n, log::warn("Cannot read RSSI: status {}", status); } - // Intel controllers don't handle ReadFailedContactCounter very well, it - // sends back Hardware Error event which will crash the daemon. So - // temporarily disable this for Floss. - // TODO(b/249876976): Intel controllers to handle this command correctly. - // And if the need for disabling metrics-related HCI call grows, consider - // creating a framework to avoid ifdefs. -#ifndef TARGET_FLOSS status = BTM_ReadFailedContactCounter(peer_bda, btm_read_failed_contact_counter_cb); if (status != tBTM_STATUS::BTM_CMD_STARTED) { log::warn("Cannot read Failed Contact Counter: status {}", status); } -#endif status = BTM_ReadTxPower(peer_bda, BT_TRANSPORT_BR_EDR, btm_read_tx_power_cb); if (status != tBTM_STATUS::BTM_CMD_STARTED) { -- GitLab From 2be3cadac958f5d9d373b52d836127d448979ae3 Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Wed, 11 Sep 2024 18:15:14 +0000 Subject: [PATCH 158/875] BassClientService: Sort scan results for source sync by fails counter Until now, it was sorted by priority flag and by RSSI. That solution had the disadvantage that if two broadcasters with the best range, fails all the time, then any other broadcaster will not be sync. This change add sorting by sync failure counter between priority flag and RSSI. Each time when sync fails or lost, counter in increased. It is cleared when new searching is started. Bug: 365613358 Bug: 370639684 Test: atest BassClientServiceTest Change-Id: I8350482009f7a77a5ca02ff981c85b2afb6bcc0b --- .../bass_client/BassClientService.java | 87 +++-- .../bass_client/BassClientServiceTest.java | 297 +++++++++++++++--- 2 files changed, 309 insertions(+), 75 deletions(-) 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 63d6bb23cfc..2f95d067039 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -27,6 +27,7 @@ import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeriphe import static com.android.bluetooth.flags.Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine; import static com.android.bluetooth.flags.Flags.leaudioBroadcastMonitorSourceSyncStatus; import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper; +import static com.android.bluetooth.flags.Flags.leaudioSortScansToSyncByFails; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; @@ -158,6 +159,7 @@ public class BassClientService extends ProfileService { new HashMap<>(); private final PriorityQueue mSourceSyncRequestsQueue = new PriorityQueue<>(sSourceSyncRequestComparator); + private final Map mSyncFailureCounter = new HashMap<>(); private final Map mBisDiscoveryCounterMap = new HashMap<>(); private final List mPendingSourcesToAdd = new ArrayList<>(); @@ -280,12 +282,14 @@ public class BassClientService extends ProfileService { } private static class SourceSyncRequest { - private ScanResult mScanResult; - private boolean mHasPriority; + private final ScanResult mScanResult; + private final boolean mHasPriority; + private final int mSyncFailureCounter; - SourceSyncRequest(ScanResult scanResult, boolean hasPriority) { + SourceSyncRequest(ScanResult scanResult, boolean hasPriority, int syncFailureCounter) { this.mScanResult = scanResult; this.mHasPriority = hasPriority; + this.mSyncFailureCounter = syncFailureCounter; } public ScanResult getScanResult() { @@ -300,6 +304,10 @@ public class BassClientService extends ProfileService { return mHasPriority; } + public int getFailsCounter() { + return mSyncFailureCounter; + } + @Override public String toString() { return "SourceSyncRequest{" @@ -307,6 +315,8 @@ public class BassClientService extends ProfileService { + mScanResult + ", mHasPriority=" + mHasPriority + + ", mSyncFailureCounter=" + + mSyncFailureCounter + '}'; } } @@ -319,6 +329,9 @@ public class BassClientService extends ProfileService { return -1; } else if (!ssr1.hasPriority() && ssr2.hasPriority()) { return 1; + } else if (leaudioSortScansToSyncByFails() + && (ssr1.getFailsCounter() != ssr2.getFailsCounter())) { + return Integer.compare(ssr1.getFailsCounter(), ssr2.getFailsCounter()); } else { return Integer.compare(ssr2.getRssi(), ssr1.getRssi()); } @@ -1046,9 +1059,8 @@ public class BassClientService extends ProfileService { if (isPlaying) { stopBigMonitoring(broadcastId, false); } else if (!mPausedBroadcastIds.containsKey(broadcastId)) { - ScanResult scanRes = getCachedBroadcast(broadcastId); - if (scanRes != null) { - addSelectSourceRequest(scanRes, true); + if (mCachedBroadcasts.containsKey(broadcastId)) { + addSelectSourceRequest(broadcastId, true); mPausedBroadcastIds.put(broadcastId, PauseType.SINK_UNKNOWN); logPausedBroadcastsAndSinks(); mHandler.removeMessages(MESSAGE_BIG_CHECK_START); @@ -1842,11 +1854,11 @@ public class BassClientService extends ProfileService { "Broadcast Source Found: Broadcast ID: " + broadcastId); if (broadcastId != BassConstants.INVALID_BROADCAST_ID - && mCachedBroadcasts.get(broadcastId) == null) { + && !mCachedBroadcasts.containsKey(broadcastId)) { log("selectBroadcastSource: broadcastId " + broadcastId); mCachedBroadcasts.put(broadcastId, result); if (leaudioBroadcastExtractPeriodicScannerFromStateMachine()) { - addSelectSourceRequest(result, false); + addSelectSourceRequest(broadcastId, false); } else { synchronized (mStateMachines) { for (BassClientStateMachine sm : @@ -1866,15 +1878,13 @@ public class BassClientService extends ProfileService { informConnectedDeviceAboutScanOffloadStop(); } }; + mSyncFailureCounter.clear(); mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT); if (leaudioBroadcastResyncHelper()) { // Sync to the broadcasts already synced with sinks Set syncedBroadcasts = getExternalBroadcastsActiveOnSinks(); for (int syncedBroadcast : syncedBroadcasts) { - ScanResult scanRes = getCachedBroadcast(syncedBroadcast); - if (scanRes != null) { - addSelectSourceRequest(scanRes, true); - } + addSelectSourceRequest(syncedBroadcast, true); } } // when starting scan, clear the previously cached broadcast scan results @@ -1972,10 +1982,7 @@ public class BassClientService extends ProfileService { Integer broadcastId = entry.getKey(); PauseType pauseType = entry.getValue(); if (pauseType != PauseType.HOST_INTENTIONAL) { - ScanResult scanRes = getCachedBroadcast(broadcastId); - if (scanRes != null) { - addSelectSourceRequest(scanRes, true); - } + addSelectSourceRequest(broadcastId, true); } } } @@ -1985,6 +1992,7 @@ public class BassClientService extends ProfileService { private void clearAllSyncData() { log("clearAllSyncData"); mSourceSyncRequestsQueue.clear(); + mSyncFailureCounter.clear(); mPendingSourcesToAdd.clear(); cancelActiveSync(null); @@ -2106,6 +2114,10 @@ public class BassClientService extends ProfileService { } } stopBigMonitoring(broadcastId, false); + synchronized (mSourceSyncRequestsQueue) { + int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1; + mSyncFailureCounter.put(broadcastId, failsCounter); + } synchronized (mSearchScanCallbackLock) { // Clear from cache to make possible sync again (only during active searching) if (mSearchScanCallback != null) { @@ -2180,6 +2192,10 @@ public class BassClientService extends ProfileService { mCallbacks.notifySourceLost(broadcastId); } stopBigMonitoring(broadcastId, false); + synchronized (mSourceSyncRequestsQueue) { + int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1; + mSyncFailureCounter.put(broadcastId, failsCounter); + } } clearAllDataForSyncHandle(syncHandle); // Clear from cache to make possible sync again (only during active searching) @@ -2464,30 +2480,35 @@ public class BassClientService extends ProfileService { return broadcastName; } - void addSelectSourceRequest(ScanResult scanRes, boolean hasPriority) { + void addSelectSourceRequest(int broadcastId, boolean hasPriority) { sEventLogger.logd( TAG, - "Add Select Broadcast Source, result: " - + scanRes + "Add Select Broadcast Source, broadcastId: " + + broadcastId + ", hasPriority: " + hasPriority); - if (scanRes == null) { - Log.e(TAG, "addSelectSourceRequest: Error bad parameters: scanRes cannot be null"); - return; - } + ScanResult scanRes = getCachedBroadcast(broadcastId); + if (scanRes != null) { + ScanRecord scanRecord = scanRes.getScanRecord(); + if (scanRecord == null) { + log("addSelectSourceRequest: ScanRecord empty"); + return; + } - ScanRecord scanRecord = scanRes.getScanRecord(); - if (scanRecord == null) { - log("addSelectSourceRequest: ScanRecord empty"); - return; - } + synchronized (mSourceSyncRequestsQueue) { + if (!mSyncFailureCounter.containsKey(broadcastId)) { + mSyncFailureCounter.put(broadcastId, 0); + } + mSourceSyncRequestsQueue.add( + new SourceSyncRequest( + scanRes, hasPriority, mSyncFailureCounter.get(broadcastId))); + } - synchronized (mSourceSyncRequestsQueue) { - mSourceSyncRequestsQueue.add(new SourceSyncRequest(scanRes, hasPriority)); + handleSelectSourceRequest(); + } else { + log("addSelectSourceRequest: ScanResult empty"); } - - handleSelectSourceRequest(); } @SuppressLint("AndroidFrameworkRequiresPermission") // TODO: b/350563786 - Fix BASS annotation @@ -2732,7 +2753,7 @@ public class BassClientService extends ProfileService { mPendingSourcesToAdd.add( new AddSourceData(sink, sourceMetadata, isGroupOp)); if (!alreadyAdded) { - addSelectSourceRequest(getCachedBroadcast(broadcastId), true); + addSelectSourceRequest(broadcastId, true); } } } else { diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index b48c278e57b..3ba383a656c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -2377,35 +2377,11 @@ public class BassClientServiceTest { @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void testSelectSource_withSameBroadcastId() { - byte[] scanRecord = getScanRecord(TEST_BROADCAST_ID); - - ScanResult scanResult1 = - new ScanResult( - mSourceDevice, - 0, - 0, - 0, - 0, - 0, - TEST_RSSI, - 0, - ScanRecord.parseFromBytes(scanRecord), - 0); - ScanResult scanResult2 = - new ScanResult( - mSourceDevice2, - 0, - 0, - 0, - 0, - 0, - TEST_RSSI, - 0, - ScanRecord.parseFromBytes(scanRecord), - 0); + prepareConnectedDeviceGroup(); + startSearchingForSources(); // First selectSource - mBassClientService.addSelectSourceRequest(scanResult1, false); + onScanResult(mSourceDevice, TEST_BROADCAST_ID); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( @@ -2414,7 +2390,7 @@ public class BassClientServiceTest { onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); // Second selectSource with the same broadcast id - mBassClientService.addSelectSourceRequest(scanResult2, false); + onScanResult(mSourceDevice2, TEST_BROADCAST_ID); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerRegisterSync( @@ -2491,7 +2467,9 @@ public class BassClientServiceTest { ScanRecord.parseFromBytes(scanRecord), 0); - mBassClientService.addSelectSourceRequest(scanResult, false); + prepareConnectedDeviceGroup(); + startSearchingForSources(); + mCallbackCaptor.getValue().onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult); verify(mMethodProxy, never()) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); @@ -2591,7 +2569,9 @@ public class BassClientServiceTest { ScanRecord.parseFromBytes(scanRecord), 0); - mBassClientService.addSelectSourceRequest(scanResult, false); + prepareConnectedDeviceGroup(); + startSearchingForSources(); + mCallbackCaptor.getValue().onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult); verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); @@ -2667,7 +2647,9 @@ public class BassClientServiceTest { ScanRecord.parseFromBytes(scanRecord), 0); - mBassClientService.addSelectSourceRequest(scanResult, false); + prepareConnectedDeviceGroup(); + startSearchingForSources(); + mCallbackCaptor.getValue().onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult); verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); @@ -3318,7 +3300,7 @@ public class BassClientServiceTest { @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) - public void testSelectSource_orderOfSyncRegistering() { + public void testSelectSource_orderOfSyncRegisteringByPriorityAndRssi() { final BluetoothDevice device1 = mBluetoothAdapter.getRemoteLeDevice( "00:11:22:33:44:11", BluetoothDevice.ADDRESS_TYPE_RANDOM); @@ -3441,20 +3423,42 @@ public class BassClientServiceTest { ScanRecord.parseFromBytes(scanRecord7), 0); + prepareConnectedDeviceGroup(); + startSearchingForSources(); + // Added and executed immidiatelly as no other in queue - mBassClientService.addSelectSourceRequest(scanResult1, false); + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); // Added to queue with worst rssi - mBassClientService.addSelectSourceRequest(scanResult2, false); + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult2); // Added to queue with best rssi - mBassClientService.addSelectSourceRequest(scanResult3, false); + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult3); // Added to queue with medium rssi - mBassClientService.addSelectSourceRequest(scanResult4, false); - // Added to queue with priority and worst rssi - mBassClientService.addSelectSourceRequest(scanResult5, true); - // Added to queue with priority and best rssi - mBassClientService.addSelectSourceRequest(scanResult6, true); - // Added to queue with priority and medium rssi - mBassClientService.addSelectSourceRequest(scanResult7, true); + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult4); + // Added to queue with worst rssi (increase priority after all) + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult5); + // Added to queue with best rssi (increase priority after all) + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult6); + // Added to queue with medium rssi (increase priority after all) + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult7); + + // Increase priority of last 3 of them + mBassClientService.addSelectSourceRequest(broadcastId5, true); + mBassClientService.addSelectSourceRequest(broadcastId6, true); + mBassClientService.addSelectSourceRequest(broadcastId7, true); ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(ScanResult.class); mInOrderMethodProxy @@ -3555,6 +3559,215 @@ public class BassClientServiceTest { .isEqualTo(broadcastId2); } + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_SORT_SCANS_TO_SYNC_BY_FAILS, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void testSelectSource_orderOfSyncRegisteringByRssiAndFailsCounter() { + final BluetoothDevice device1 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:11", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final BluetoothDevice device2 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:22", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final BluetoothDevice device3 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:33", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final int broadcastId1 = 1111; + final int broadcastId2 = 2222; + final int broadcastId3 = 3333; + + byte[] scanRecord1 = getScanRecord(broadcastId1); + byte[] scanRecord2 = getScanRecord(broadcastId2); + byte[] scanRecord3 = getScanRecord(broadcastId3); + + ScanResult scanResult1 = + new ScanResult( + device1, + 0, + 0, + 0, + 0, + 0, + TEST_RSSI + 10, + 0, + ScanRecord.parseFromBytes(scanRecord1), + 0); + ScanResult scanResult2 = + new ScanResult( + device2, + 0, + 0, + 0, + 0, + 0, + TEST_RSSI + 9, + 0, + ScanRecord.parseFromBytes(scanRecord2), + 0); + ScanResult scanResult3 = + new ScanResult( + device3, + 0, + 0, + 0, + 0, + 0, + TEST_RSSI, + 0, + ScanRecord.parseFromBytes(scanRecord3), + 0); + + prepareConnectedDeviceGroup(); + startSearchingForSources(); + + // Test using onSyncEstablishedFailed + + // Added and executed immidiatelly as no other in queue, high rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); + // Added to queue, medium rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult2); + // Added to queue, low rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult3); + + ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(ScanResult.class); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), resultCaptor.capture(), anyInt(), anyInt(), any(), any()); + assertThat( + BassUtils.parseBroadcastId( + resultCaptor + .getValue() + .getScanRecord() + .getServiceData() + .get(BassConstants.BAAS_UUID))) + .isEqualTo(broadcastId1); + + onSyncEstablishedFailed(device1, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), resultCaptor.capture(), anyInt(), anyInt(), any(), any()); + assertThat( + BassUtils.parseBroadcastId( + resultCaptor + .getValue() + .getScanRecord() + .getServiceData() + .get(BassConstants.BAAS_UUID))) + .isEqualTo(broadcastId2); + + // Added to queue again, high rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); + + onSyncEstablishedFailed(device2, TEST_SYNC_HANDLE + 1); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), resultCaptor.capture(), anyInt(), anyInt(), any(), any()); + assertThat( + BassUtils.parseBroadcastId( + resultCaptor + .getValue() + .getScanRecord() + .getServiceData() + .get(BassConstants.BAAS_UUID))) + .isEqualTo(broadcastId3); + + onSyncEstablished(device3, TEST_SYNC_HANDLE + 2); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), resultCaptor.capture(), anyInt(), anyInt(), any(), any()); + assertThat( + BassUtils.parseBroadcastId( + resultCaptor + .getValue() + .getScanRecord() + .getServiceData() + .get(BassConstants.BAAS_UUID))) + .isEqualTo(broadcastId1); + + // Restart searching clears the mSyncFailureCounter + mBassClientService.stopSearchingForSources(); + mInOrderMethodProxy + .verify(mMethodProxy, times(2)) + .periodicAdvertisingManagerUnregisterSync(any(), any()); + startSearchingForSources(); + + // Test using onSyncLost + + // Added and executed immidiatelly as no other in queue, high rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); + // Added to queue, medium rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult2); + // Added to queue, low rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult3); + + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), resultCaptor.capture(), anyInt(), anyInt(), any(), any()); + assertThat( + BassUtils.parseBroadcastId( + resultCaptor + .getValue() + .getScanRecord() + .getServiceData() + .get(BassConstants.BAAS_UUID))) + .isEqualTo(broadcastId1); + + onSyncEstablished(device1, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), resultCaptor.capture(), anyInt(), anyInt(), any(), any()); + assertThat( + BassUtils.parseBroadcastId( + resultCaptor + .getValue() + .getScanRecord() + .getServiceData() + .get(BassConstants.BAAS_UUID))) + .isEqualTo(broadcastId2); + onSyncLost(); + + // Added to queue again, high rssi + mCallbackCaptor + .getValue() + .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); + + onSyncEstablished(device2, TEST_SYNC_HANDLE + 1); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), resultCaptor.capture(), anyInt(), anyInt(), any(), any()); + assertThat( + BassUtils.parseBroadcastId( + resultCaptor + .getValue() + .getScanRecord() + .getServiceData() + .get(BassConstants.BAAS_UUID))) + .isEqualTo(broadcastId3); + } + @Test @DisableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void testSelectSource_invalidActiveSource() { -- GitLab From 489fd5097145d30d146f2d61c539e8310192c86f Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Fri, 4 Oct 2024 20:53:00 +0800 Subject: [PATCH 159/875] floss: dbus_projection: Allow other attributes on top of dbus_method The current logic in dbus_projection is very strict when checking for the dbus_method attribute, specifically it doesn't allow other attributes at all. This might come as surprising because even an unsuspecting function comment actually counts as an attribute. When parsing failure occurs, the macro treats as if it's not a dbus function so no error is reported. Change the logic to allow multiple attributes. For now those attributes are ignored - if more support is required one needs to add their own implementation still. Bug: 371534263 Test: m -j Test: btclient advertise on, verify doesn't crash Flag: EXEMPT, floss-only change Change-Id: I26d2595b0c536a2dbd0ae505f6234f881e2199f7 --- .../dbus_projection/dbus_macros/src/lib.rs | 69 +++++++++++-------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/system/gd/rust/linux/dbus_projection/dbus_macros/src/lib.rs b/system/gd/rust/linux/dbus_projection/dbus_macros/src/lib.rs index 430454d2165..3cc3c91cf25 100644 --- a/system/gd/rust/linux/dbus_projection/dbus_macros/src/lib.rs +++ b/system/gd/rust/linux/dbus_projection/dbus_macros/src/lib.rs @@ -125,16 +125,21 @@ pub fn generate_dbus_exporter(attr: TokenStream, item: TokenStream) -> TokenStre for item in ast.items { if let ImplItem::Method(method) = item { - if method.attrs.len() != 1 { - continue; + // Find the #[dbus_method] attribute + let mut dbus_method_attr = None; + for attr in &method.attrs { + if attr.path.get_ident().unwrap().to_string().eq("dbus_method") { + dbus_method_attr = Some(attr); + break; + } } - let attr = &method.attrs[0]; - if !attr.path.get_ident().unwrap().to_string().eq("dbus_method") { + // Skip the method is not marked with #[dbus_method]. + if dbus_method_attr.is_none() { continue; } - let meta_list = match attr.parse_meta().unwrap() { + let meta_list = match dbus_method_attr.unwrap().parse_meta().unwrap() { Meta::List(meta_list) => meta_list, _ => continue, }; @@ -333,9 +338,17 @@ pub fn generate_dbus_interface_client(attr: TokenStream, item: TokenStream) -> T // Iterate on every methods of a trait impl for item in ast.items { if let ImplItem::Method(method) = item { - // If the method is not marked with #[dbus_method], just copy the - // original method body. - if method.attrs.len() != 1 { + // Find the #[dbus_method] attribute + let mut dbus_method_attr = None; + for attr in &method.attrs { + if attr.path.get_ident().unwrap().to_string().eq("dbus_method") { + dbus_method_attr = Some(attr); + break; + } + } + + // If the method is not marked with #[dbus_method], just copy the original method body. + if dbus_method_attr.is_none() { methods = quote! { #methods @@ -344,15 +357,9 @@ pub fn generate_dbus_interface_client(attr: TokenStream, item: TokenStream) -> T continue; } - let attr = &method.attrs[0]; - if !attr.path.get_ident().unwrap().to_string().eq("dbus_method") { - continue; - } - - let sig = &method.sig; - // For RPC-friendly method, copy the original signature but add public, async, and wrap // the return with Result. + let sig = &method.sig; let mut rpc_sig = sig.clone(); rpc_sig.asyncness = Some(::default()); rpc_sig.output = match rpc_sig.output { @@ -367,11 +374,12 @@ pub fn generate_dbus_interface_client(attr: TokenStream, item: TokenStream) -> T pub #rpc_sig }; - let dbus_method_name = if let Meta::List(meta_list) = attr.parse_meta().unwrap() { - Some(meta_list.nested[0].clone()) - } else { - None - }; + let dbus_method_name = + if let Meta::List(meta_list) = dbus_method_attr.unwrap().parse_meta().unwrap() { + Some(meta_list.nested[0].clone()) + } else { + None + }; if dbus_method_name.is_none() { continue; @@ -769,9 +777,17 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream { for item in ast.items { if let ImplItem::Method(method) = item { - // If the method is not marked with #[dbus_method], just copy the - // original method body. - if method.attrs.len() != 1 { + // Find the #[dbus_method] attribute + let mut dbus_method_attr = None; + for attr in &method.attrs { + if attr.path.get_ident().unwrap().to_string().eq("dbus_method") { + dbus_method_attr = Some(attr); + break; + } + } + + // If the method is not marked with #[dbus_method], just copy the original method body. + if dbus_method_attr.is_none() { method_impls = quote! { #method_impls #method @@ -779,12 +795,7 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream { continue; } - let attr = &method.attrs[0]; - if !attr.path.get_ident().unwrap().to_string().eq("dbus_method") { - continue; - } - - let meta_list = match attr.parse_meta().unwrap() { + let meta_list = match dbus_method_attr.unwrap().parse_meta().unwrap() { Meta::List(meta_list) => meta_list, _ => continue, }; -- GitLab From 88853e0038fa51aebbd750dd04fe3be8a6d26005 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 3 Oct 2024 17:43:37 -0700 Subject: [PATCH 160/875] Remove unused parameters from bt_interface_t::init Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: Icbb7f2c942452577e79b41726e81e3f41d8573cb --- .../com_android_bluetooth_btservice_AdapterService.cpp | 10 +++------- .../bluetooth/btservice/AdapterNativeInterface.java | 9 +++------ .../android/bluetooth/btservice/AdapterService.java | 3 +-- system/btif/src/bluetooth.cc | 4 +--- system/gd/rust/topshim/src/btif.rs | 4 +--- system/include/hardware/bluetooth.h | 3 +-- system/test/headless/headless.cc | 2 +- system/test/suite/adapter/adapter_unittest.cc | 2 +- system/test/suite/adapter/bluetooth_test.cc | 2 +- 9 files changed, 13 insertions(+), 26 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index b4cf5eb3262..050fc7b1a53 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -1020,7 +1020,7 @@ int hal_util_load_bt_library(const bt_interface_t** interface) { } static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest, jboolean isCommonCriteriaMode, - int configCompareResult, jboolean isAtvDevice, jstring userDataDirectory) { + int configCompareResult, jboolean isAtvDevice) { std::unique_lock lock(jniObjMutex); log::verbose(""); @@ -1035,14 +1035,10 @@ static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest, jboolean isCo return JNI_FALSE; } - const char* user_data_directory = env->GetStringUTFChars(userDataDirectory, NULL); - int ret = sBluetoothInterface->init(&sBluetoothCallbacks, isGuest == JNI_TRUE ? 1 : 0, isCommonCriteriaMode == JNI_TRUE ? 1 : 0, configCompareResult, - nullptr, isAtvDevice == JNI_TRUE ? 1 : 0, user_data_directory); - - env->ReleaseStringUTFChars(userDataDirectory, user_data_directory); + isAtvDevice == JNI_TRUE ? 1 : 0); if (ret != BT_STATUS_SUCCESS) { log::error("Error while setting the callbacks: {}", ret); @@ -2225,7 +2221,7 @@ static jboolean restoreFilterAcceptListNative(JNIEnv* /* env */, jobject /* obj int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) { const JNINativeMethod methods[] = { - {"initNative", "(ZZIZLjava/lang/String;)Z", reinterpret_cast(initNative)}, + {"initNative", "(ZZIZ)Z", reinterpret_cast(initNative)}, {"cleanupNative", "()V", reinterpret_cast(cleanupNative)}, {"enableNative", "()Z", reinterpret_cast(enableNative)}, {"disableNative", "()Z", reinterpret_cast(disableNative)}, diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java index 87cd3536a4e..4a5bb81267d 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java @@ -64,15 +64,13 @@ public class AdapterNativeInterface { boolean startRestricted, boolean isCommonCriteriaMode, int configCompareResult, - boolean isAtvDevice, - String userDataDirectory) { + boolean isAtvDevice) { mJniCallbacks = new JniCallbacks(service, adapterProperties); return initNative( startRestricted, isCommonCriteriaMode, configCompareResult, - isAtvDevice, - userDataDirectory); + isAtvDevice); } void cleanup() { @@ -295,8 +293,7 @@ public class AdapterNativeInterface { boolean startRestricted, boolean isCommonCriteriaMode, int configCompareResult, - boolean isAtvDevice, - String userDataDirectory); + boolean isAtvDevice); private native void cleanupNative(); diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 19c8aee207c..563950078df 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -700,8 +700,7 @@ public class AdapterService extends Service { mUserManager.isGuestUser(), isCommonCriteriaMode, configCompareResult, - isAtvDevice, - getApplicationInfo().dataDir); + isAtvDevice); mNativeAvailable = true; // Load the name and address mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDADDR); diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index aeeb450a21c..8438dee7601 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -435,9 +435,7 @@ int GetAdapterIndex() { return 0; } // Unsupported outside of FLOSS #endif static int init(bt_callbacks_t* callbacks, bool start_restricted, bool is_common_criteria_mode, - int config_compare_result, const char** /* init_flags */, bool is_atv, - const char* user_data_directory) { - (void)user_data_directory; + int config_compare_result, bool is_atv) { log::info( "start restricted = {} ; common criteria mode = {}, config compare " "result = {}", diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index 5a6d76b7705..e3bd8480c36 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -1262,9 +1262,7 @@ impl BluetoothInterface { guest_mode, is_common_criteria_mode, config_compare_result, - std::ptr::null_mut(), - is_atv, - std::ptr::null() + is_atv ); self.is_init = init == 0; diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index 7e891573b9e..77ff10a9995 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -691,8 +691,7 @@ typedef struct { * the local device is an Android TV */ int (*init)(bt_callbacks_t* callbacks, bool guest_mode, bool is_common_criteria_mode, - int config_compare_result, const char** init_flags, bool is_atv, - const char* user_data_directory); + int config_compare_result, bool is_atv); /** Enable Bluetooth. */ int (*enable)(); diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc index dd15c2a557a..ebfcb041ecd 100644 --- a/system/test/headless/headless.cc +++ b/system/test/headless/headless.cc @@ -258,7 +258,7 @@ void HeadlessStack::SetUp() { const bool is_atv = false; int status = bluetoothInterface.init(&bt_callbacks, start_restricted, is_common_criteria_mode, - config_compare_result, nullptr, is_atv, nullptr); + config_compare_result, is_atv); if (status == BT_STATUS_SUCCESS) { log::info("Initialized bluetooth callbacks"); diff --git a/system/test/suite/adapter/adapter_unittest.cc b/system/test/suite/adapter/adapter_unittest.cc index 65de637a7cb..8e2769ea105 100644 --- a/system/test/suite/adapter/adapter_unittest.cc +++ b/system/test/suite/adapter/adapter_unittest.cc @@ -160,7 +160,7 @@ TEST_F(BluetoothTest, AdapterCleanupDuringDiscovery) { ASSERT_TRUE(callbacks != nullptr); for (int i = 0; i < kTestRepeatCount; ++i) { - bt_interface()->init(callbacks, false, false, 0, nullptr, false, nullptr); + bt_interface()->init(callbacks, false, false, 0, false); EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on."; diff --git a/system/test/suite/adapter/bluetooth_test.cc b/system/test/suite/adapter/bluetooth_test.cc index ce7f0c4479b..ebed3288492 100644 --- a/system/test/suite/adapter/bluetooth_test.cc +++ b/system/test/suite/adapter/bluetooth_test.cc @@ -86,7 +86,7 @@ void BluetoothTest::SetUp() { remove("/data/misc/bluedroid/bt_config.conf.encrypted-checksum"); instance = this; - int status = bluetoothInterface.init(&callbacks, false, false, 0, nullptr, false, nullptr); + int status = bluetoothInterface.init(&callbacks, false, false, 0, false); ASSERT_EQ(status, BT_STATUS_SUCCESS); } -- GitLab From 2fc3087b9ac3019518c6ceb8a64d181d6bb04907 Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Fri, 4 Oct 2024 18:23:45 +0000 Subject: [PATCH 161/875] Fix OOB writes in gatt_sr.cc At various points in gatt_sr.cc, the output of the gatt_tcb_get_payload_size function is used without checking for a positive length. However, in exceptional cases it is possible for the channel to be closed at the time the function is called, which will lead to a zero length and cause an OOB write in subsequent processing. Fix all of these. Bug: 364026473 Bug: 364027038 Bug: 364027949 Bug: 364025411 Test: m libbluetooth Test: researcher POC Flag: EXEMPT trivial validity checks Tag: #security Ignore-AOSP-First: Security Merged-In: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404 Change-Id: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404 --- system/stack/gatt/gatt_sr.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 6f81b905141..c61df52bc84 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -734,6 +734,11 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t msg_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); @@ -769,6 +774,12 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint16_t cid, } uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t buf_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); @@ -902,6 +913,11 @@ static void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint16_t cid, uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t msg_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; @@ -1049,6 +1065,11 @@ static void gatts_process_read_req(tGATT_TCB& tcb, uint16_t cid, uint8_t* p_data) { uint16_t payload_size = gatt_tcb_get_payload_size_tx(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t buf_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; uint16_t offset = 0; -- GitLab From 6f58417c6542c0cac1412c67ce2cd622103ced0c Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Thu, 26 Sep 2024 00:32:02 +0000 Subject: [PATCH 162/875] Skip PbapServiceTest if feature is not supported TelephonyManager#getLine1Number requires the feature. Flag: EXEMPT, test only change Bug: 367395001 Test: atest BluetoothPbapServiceTest Change-Id: Ifb85d713643394c85ca3b26ae48140fbb63689b2 --- .../android/bluetooth/pbap/BluetoothPbapServiceTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java index dbbb53e9d88..b5d098695a6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java @@ -18,6 +18,8 @@ package com.android.bluetooth.pbap; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import static org.junit.Assume.assumeNotNull; +import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -31,6 +33,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.os.Message; import android.os.UserManager; import android.os.test.TestLooper; @@ -97,6 +100,10 @@ public class BluetoothPbapServiceTest { mService = new BluetoothPbapService(mAdapterService, mNotificationManager); mService.start(); mService.setAvailable(true); + + PackageManager pm = mTargetContext.getPackageManager(); + assumeNotNull(pm); + assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)); } @After -- GitLab From 108aa4d79ef071d38fc2e762b49b54a2c531bd63 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 4 Oct 2024 22:47:09 +0000 Subject: [PATCH 163/875] Match package prefix instead of complete package name Tesla app may have different package names for internal testing and service centers Test: mmm packages/modules/Bluetooth Flag: EXEMPT IOP fix Bug: 369329192 Change-Id: I560beee7947b699e3a63df998f5733ce558041d6 --- .../android/bluetooth/gatt/GattService.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 9015774554c..1f7593fa2c7 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -145,7 +145,7 @@ public class GattService extends ProfileService { private static final Integer GATT_MTU_MAX = 517; private static final Map EARLY_MTU_EXCHANGE_PACKAGES = - Map.of("com.teslamotors.tesla", GATT_MTU_MAX); + Map.of("com.teslamotors", GATT_MTU_MAX); @VisibleForTesting static final int GATT_CLIENT_LIMIT_PER_APP = 32; @@ -2161,14 +2161,19 @@ public class GattService extends ProfileService { // Some applications expect MTU to be exchanged immediately on connections String packageName = attributionSource.getPackageName(); - if (packageName != null && EARLY_MTU_EXCHANGE_PACKAGES.containsKey(packageName)) { - preferredMtu = EARLY_MTU_EXCHANGE_PACKAGES.get(packageName); - Log.i( - TAG, - "Early MTU exchange preference (" - + preferredMtu - + ") requested for " - + packageName); + if (packageName != null) { + for (Map.Entry entry : EARLY_MTU_EXCHANGE_PACKAGES.entrySet()) { + if (packageName.contains(entry.getKey())) { + preferredMtu = entry.getValue(); + Log.i( + TAG, + "Early MTU exchange preference (" + + preferredMtu + + ") requested for " + + packageName); + break; + } + } } mNativeInterface.gattClientConnect( -- GitLab From 2ba6d51203aab193a5fbbb7e67da5a6a7988c8c9 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 17:14:37 -0700 Subject: [PATCH 164/875] Hap: set available on unknow preset no crash Bug: 362424892 Test: atest avatar:HapTest#test__set_non_existing_preset_as_available__verify_no_crash_and_no_update Flag: Exempt feature is not shipped yet, fix has end-to-end test Change-Id: Id218fccf6bc78586953f8f82255b77b2abe15d55 --- system/bta/has/has_client.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 8b4ebbe7ccf..b8b2aa327a0 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -1394,6 +1394,12 @@ private: break; } + if (!device.has_presets.contains(nt.index)) { + log::error("Unknown preset. Notification is discarded: {}", nt); + device.has_journal_.Append(HasJournalRecord(nt)); + device.ctp_notifications_.pop_front(); + continue; + } auto preset = device.has_presets.extract(nt.index).value(); auto new_props = preset.GetProperties(); -- GitLab From 99527fc62ec1f891cd53afe909bc48c5a3d710bb Mon Sep 17 00:00:00 2001 From: Omair Kamil Date: Fri, 4 Oct 2024 12:17:54 -0700 Subject: [PATCH 165/875] Interop fix to not read PPCP for devices that report incompatible values. Bug: 360314855 Fix: 360314855 Flag: EXEMPT, targeted IOP fix Test: m Bluetooth, manual testing Change-Id: I69b13f959351075b45603a514f06a967101cccf4 --- system/bta/dm/bta_dm_disc.cc | 13 ++++++++++++- system/conf/interop_database.conf | 3 +++ system/device/test/interop_test.cc | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc index f22870f9009..455309e60a9 100644 --- a/system/bta/dm/bta_dm_disc.cc +++ b/system/bta/dm/bta_dm_disc.cc @@ -31,8 +31,10 @@ #include "bta/dm/bta_dm_disc_int.h" #include "bta/include/bta_gatt_api.h" +#include "btif/include/btif_storage.h" #include "common/circular_buffer.h" #include "common/strings.h" +#include "device/include/interop.h" #include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" #include "os/logging/log_adapter.h" @@ -276,8 +278,17 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { bta_dm_discovery_cb.service_search_cbacks.on_service_discovery_results(r.bd_addr, r.uuids, r.result); } else { + char remote_name[BD_NAME_LEN] = ""; bta_dm_discovery_cb.transports &= ~BT_TRANSPORT_LE; - GAP_BleReadPeerPrefConnParams(bta_dm_discovery_cb.peer_bdaddr); + if (btif_storage_get_stored_remote_name(bta_dm_discovery_cb.peer_bdaddr, remote_name) && + interop_match_name(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS, remote_name)) { + // Some devices provide PPCP values that are incompatible with the device-side firmware. + log::info("disable PPCP read: interop matched name {} address {}", remote_name, + bta_dm_discovery_cb.peer_bdaddr); + } else { + log::info("reading PPCP"); + GAP_BleReadPeerPrefConnParams(bta_dm_discovery_cb.peer_bdaddr); + } bta_dm_discovery_cb.service_search_cbacks.on_gatt_results(bta_dm_discovery_cb.peer_bdaddr, disc_result.gatt_uuids, diff --git a/system/conf/interop_database.conf b/system/conf/interop_database.conf index ba5c679b22d..c7827c41af4 100644 --- a/system/conf/interop_database.conf +++ b/system/conf/interop_database.conf @@ -194,6 +194,9 @@ Motorola Keyboard KZ500 v122 = Name_Based [INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS] BSMBB09DS = Name_Based ELECOM = Name_Based +Dexcom = Name_Based +DXCM = Name_Based +DX0 = Name_Based # Disable role switch for headsets/car-kits # Some car kits allow role switch but when DUT initiates role switch diff --git a/system/device/test/interop_test.cc b/system/device/test/interop_test.cc index e0c44b1cb71..c27801f2084 100644 --- a/system/device/test/interop_test.cc +++ b/system/device/test/interop_test.cc @@ -365,6 +365,9 @@ TEST_F(InteropTest, test_name_hit) { "Targus BT Laser Notebook Mouse")); EXPECT_TRUE(interop_match_name(INTEROP_REMOVE_HID_DIG_DESCRIPTOR, "Motorola Keyboard KZ500")); EXPECT_TRUE(interop_match_name(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS, "BSMBB09DS")); + EXPECT_TRUE(interop_match_name(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS, "DXCMog")); + EXPECT_TRUE(interop_match_name(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS, "Dexcom 123")); + EXPECT_TRUE(interop_match_name(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS, "DX01ab")); EXPECT_TRUE(interop_match_name(INTEROP_DISABLE_AAC_CODEC, "abramtek M1")); EXPECT_TRUE(interop_match_name(INTEROP_DISABLE_AAC_VBR_CODEC, "Audi_MMI_2781")); EXPECT_TRUE(interop_match_name(INTEROP_DISABLE_AVDTP_RECONFIGURE, "KMM-BT51*HD")); -- GitLab From 8ca8a52f7913f7af14ed260b852d42dcd6c5ff95 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 19:22:36 -0700 Subject: [PATCH 166/875] HeadsetClient Test: use test looper Faster, more deterministic Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I732d42126634f48bc5f683ffefa3aab6e6b1c15a --- .../HeadsetClientStateMachineTest.java | 142 +++++++----------- 1 file changed, 56 insertions(+), 86 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 7416a53a040..2fa381eaf1c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -46,20 +46,17 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.media.AudioManager; import android.os.Bundle; -import android.os.HandlerThread; import android.os.Looper; import android.os.Message; +import android.os.test.TestLooper; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Pair; import androidx.test.filters.FlakyTest; -import androidx.test.filters.LargeTest; -import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; -import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.RemoteDevices; import com.android.bluetooth.hfp.HeadsetService; @@ -81,15 +78,14 @@ import org.mockito.junit.MockitoRule; import java.util.List; import java.util.Set; -/** Test cases for {@link HeadsetClientStateMachine}. */ -@LargeTest +@SmallTest @RunWith(AndroidJUnit4.class) public class HeadsetClientStateMachineTest { private BluetoothAdapter mAdapter; - private HandlerThread mHandlerThread; private TestHeadsetClientStateMachine mHeadsetClientStateMachine; private InOrder mInOrder; private BluetoothDevice mTestDevice; + private TestLooper mTestLooper; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -104,11 +100,6 @@ public class HeadsetClientStateMachineTest { @Mock private PackageManager mPackageManager; @Mock private NativeInterface mNativeInterface; - private static final int STANDARD_WAIT_MILLIS = 1000; - private static final int QUERY_CURRENT_CALLS_WAIT_MILLIS = 2000; - private static final int QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS = - QUERY_CURRENT_CALLS_WAIT_MILLIS * 3 / 2; - @Before public void setUp() throws Exception { mInOrder = inOrder(mHeadsetClientService); @@ -134,27 +125,25 @@ public class HeadsetClientStateMachineTest { mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); // Setup thread and looper - mHandlerThread = new HandlerThread("HeadsetClientStateMachineTestHandlerThread"); - mHandlerThread.start(); + mTestLooper = new TestLooper(); // Manage looper execution in main test thread explicitly to guarantee timing consistency mHeadsetClientStateMachine = new TestHeadsetClientStateMachine( mAdapterService, mHeadsetClientService, mHeadsetService, - mHandlerThread.getLooper(), + mTestLooper.getLooper(), mNativeInterface); mHeadsetClientStateMachine.start(); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); } @After public void tearDown() throws Exception { - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); mHeadsetClientStateMachine.allowConnect = null; mHeadsetClientStateMachine.doQuit(); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - mHandlerThread.quit(); + mTestLooper.dispatchAll(); verifyNoMoreInteractions(mHeadsetService); } @@ -167,7 +156,6 @@ public class HeadsetClientStateMachineTest { } /** Test that an incoming connection with low priority is rejected */ - @MediumTest @Test public void testIncomingPriorityReject() { // Return false for priority. @@ -192,7 +180,6 @@ public class HeadsetClientStateMachineTest { } /** Test that an incoming connection with high priority is accepted */ - @MediumTest @Test public void testIncomingPriorityAccept() { // Return true for priority. @@ -218,7 +205,7 @@ public class HeadsetClientStateMachineTest { slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; slcEvent.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, slcEvent); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); setUpAndroidAt(false); @@ -231,7 +218,6 @@ public class HeadsetClientStateMachineTest { } /** Test that an incoming connection that times out */ - @MediumTest @Test public void testIncomingTimeout() { // Return true for priority. @@ -250,17 +236,11 @@ public class HeadsetClientStateMachineTest { assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connecting.class); - // Verify that one connection state broadcast is executed - mInOrder.verify( - mHeadsetClientService, - timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2)) - .sendBroadcastMultiplePermissions( - MockitoHamcrest.argThat( - hasExtra( - BluetoothProfile.EXTRA_STATE, - BluetoothProfile.STATE_DISCONNECTED)), - any(String[].class), - any(BroadcastOptions.class)); + // Trigger timeout + mTestLooper.moveTimeForward(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS); + mTestLooper.dispatchAll(); + verifySendBroadcastMultiplePermissions( + hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED)); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); @@ -346,7 +326,6 @@ public class HeadsetClientStateMachineTest { } /** Test that In Band Ringtone information is relayed from phone. */ - @LargeTest @Test @FlakyTest public void testInBandRingtone() { @@ -372,7 +351,7 @@ public class HeadsetClientStateMachineTest { slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; slcEvent.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, slcEvent); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); setUpAndroidAt(false); @@ -395,9 +374,9 @@ public class HeadsetClientStateMachineTest { // Simulate a new incoming phone call StackEvent eventCallStatusUpdated = new StackEvent(StackEvent.EVENT_TYPE_CLIP); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventCallStatusUpdated); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); mInOrder.verify(mHeadsetClientService, never()) .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); @@ -411,7 +390,7 @@ public class HeadsetClientStateMachineTest { eventIncomingCall.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventIncomingCall); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); mInOrder.verify(mHeadsetClientService, never()) .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); @@ -419,10 +398,10 @@ public class HeadsetClientStateMachineTest { StackEvent eventCommandStatus = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); eventCommandStatus.valueInt = AT_OK; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventCommandStatus); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); - mInOrder.verify(mHeadsetClientService, timeout(QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS)) + mInOrder.verify(mHeadsetClientService) .sendBroadcast(intentArgument.capture(), anyString(), any(Bundle.class)); // Verify that the new call is being registered with the inBandRing flag set. HfpClientCall clientCall = @@ -479,7 +458,7 @@ public class HeadsetClientStateMachineTest { false)); // Wait for processing - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); // Verify the broadcast ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); @@ -523,7 +502,7 @@ public class HeadsetClientStateMachineTest { slcEvent.valueInt2 |= HeadsetClientHalConstants.PEER_FEAT_HF_IND; slcEvent.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, slcEvent); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); setUpAndroidAt(androidAtSupported); @@ -546,14 +525,14 @@ public class HeadsetClientStateMachineTest { unknownEvt.valueString = "+ANDROID: (SINKAUDIOPOLICY)"; unknownEvt.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, unknownEvt); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); // receive CMD_RESULT OK after the Android AT command from remote StackEvent cmdResEvt = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); cmdResEvt.valueInt = StackEvent.CMD_RESULT_TYPE_OK; cmdResEvt.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, cmdResEvt); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) .isEqualTo(BluetoothStatusCodes.FEATURE_SUPPORTED); @@ -563,7 +542,7 @@ public class HeadsetClientStateMachineTest { cmdResEvt.valueInt = StackEvent.CMD_RESULT_TYPE_CME_ERROR; cmdResEvt.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, cmdResEvt); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) .isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); @@ -583,8 +562,9 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.obtainMessage( HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, vendorId, 0, atCommand); mHeadsetClientStateMachine.sendMessage(msg); + mTestLooper.dispatchAll(); - verify(mNativeInterface, timeout(STANDARD_WAIT_MILLIS)) + verify(mNativeInterface) .sendATCmd( mTestDevice, HeadsetClientHalConstants.HANDSFREECLIENT_AT_CMD_VENDOR_SPECIFIC_CMD, @@ -594,7 +574,6 @@ public class HeadsetClientStateMachineTest { } /** Test: supported vendor specific command: set operation */ - @LargeTest @Test public void testSupportedVendorAtCommandSet() { int vendorId = BluetoothAssignedNumbers.APPLE; @@ -603,7 +582,6 @@ public class HeadsetClientStateMachineTest { } /** Test: supported vendor specific command: read operation */ - @LargeTest @Test public void testSupportedVendorAtCommandRead() { int vendorId = BluetoothAssignedNumbers.APPLE; @@ -624,13 +602,12 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.obtainMessage( HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, vendorId, 0, atCommand); mHeadsetClientStateMachine.sendMessage(msg); + mTestLooper.dispatchAll(); - verify(mNativeInterface, timeout(STANDARD_WAIT_MILLIS).times(0)) - .sendATCmd(any(), anyInt(), anyInt(), anyInt(), any()); + verify(mNativeInterface, never()).sendATCmd(any(), anyInt(), anyInt(), anyInt(), any()); } /** Test: unsupported vendor specific command shall be filtered: bad command code */ - @LargeTest @Test public void testUnsupportedVendorAtCommandBadCode() { String atCommand = "+XAAPL=ABCD-1234-0100,100"; @@ -639,7 +616,6 @@ public class HeadsetClientStateMachineTest { } /** Test: unsupported vendor specific command shall be filtered: no back to back command */ - @LargeTest @Test public void testUnsupportedVendorAtCommandBackToBack() { String atCommand = "+XAPL=ABCD-1234-0100,100; +XAPL=ab"; @@ -674,7 +650,6 @@ public class HeadsetClientStateMachineTest { } /** Test: supported vendor specific response: response to read command */ - @LargeTest @Test public void testSupportedVendorEventReadResponse() { final int vendorId = BluetoothAssignedNumbers.APPLE; @@ -684,7 +659,6 @@ public class HeadsetClientStateMachineTest { } /** Test: supported vendor specific response: response to test command */ - @LargeTest @Test public void testSupportedVendorEventTestResponse() { final int vendorId = BluetoothAssignedNumbers.APPLE; @@ -715,7 +689,6 @@ public class HeadsetClientStateMachineTest { } /** Test unsupported vendor response: bad read response */ - @LargeTest @Test public void testUnsupportedVendorEventBadReadResponse() { final int vendorId = BluetoothAssignedNumbers.APPLE; @@ -725,7 +698,6 @@ public class HeadsetClientStateMachineTest { } /** Test unsupported vendor response: bad test response */ - @LargeTest @Test public void testUnsupportedVendorEventBadTestResponse() { final int vendorId = BluetoothAssignedNumbers.APPLE; @@ -735,7 +707,6 @@ public class HeadsetClientStateMachineTest { } /** Test voice recognition state change broadcast. */ - @MediumTest @Test public void testVoiceRecognitionStateChange() { // Setup connection state machine to be in connected state @@ -779,7 +750,6 @@ public class HeadsetClientStateMachineTest { } /** Test send BIEV command */ - @MediumTest @Test public void testSendBIEVCommand() { // Setup connection state machine to be in connected state @@ -796,8 +766,9 @@ public class HeadsetClientStateMachineTest { msg.arg2 = indicator_value; mHeadsetClientStateMachine.sendMessage(msg); + mTestLooper.dispatchAll(); - verify(mNativeInterface, timeout(STANDARD_WAIT_MILLIS)) + verify(mNativeInterface) .sendATCmd( mTestDevice, HeadsetClientHalConstants.HANDSFREECLIENT_AT_CMD_BIEV, @@ -809,7 +780,6 @@ public class HeadsetClientStateMachineTest { /** * Test state machine shall try to send AT+BIEV command to AG to update an init battery level. */ - @MediumTest @Test public void testSendBatteryUpdateIndicatorWhenConnect() { // Setup connection state machine to be in connected state @@ -819,7 +789,7 @@ public class HeadsetClientStateMachineTest { setUpHfpClientConnection(); setUpServiceLevelConnection(); - verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)).updateBatteryLevel(); + verify(mHeadsetClientService).updateBatteryLevel(); } @Test @@ -1227,7 +1197,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); @@ -1237,7 +1207,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); @@ -1252,7 +1222,7 @@ public class HeadsetClientStateMachineTest { @Test public void testProcessDisconnectMessage_onDisconnectedState() { mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getConnectionState(mTestDevice)) .isEqualTo(STATE_DISCONNECTED); } @@ -1296,7 +1266,7 @@ public class HeadsetClientStateMachineTest { HeadsetClientStateMachine.CONNECT)) .isFalse(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat( mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( HeadsetClientStateMachine.CONNECT)) @@ -1349,7 +1319,7 @@ public class HeadsetClientStateMachineTest { .isFalse(); mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)) .isTrue(); } @@ -1376,7 +1346,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -1402,7 +1372,7 @@ public class HeadsetClientStateMachineTest { .isFalse(); mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)) .isTrue(); } @@ -1411,7 +1381,7 @@ public class HeadsetClientStateMachineTest { public void testProcessConnectMessage_onConnectedState() { initToConnectedState(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); } @@ -1420,7 +1390,7 @@ public class HeadsetClientStateMachineTest { public void testProcessDisconnectMessage_onConnectedState() { initToConnectedState(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); verify(mNativeInterface).disconnect(any(BluetoothDevice.class)); } @@ -1428,7 +1398,7 @@ public class HeadsetClientStateMachineTest { public void testProcessConnectAudioMessage_onConnectedState() { initToConnectedState(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); verify(mNativeInterface).connectAudio(any(BluetoothDevice.class)); } @@ -1436,7 +1406,7 @@ public class HeadsetClientStateMachineTest { public void testProcessDisconnectAudioMessage_onConnectedState() { initToConnectedState(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); verify(mNativeInterface).disconnectAudio(any(BluetoothDevice.class)); } @@ -1444,7 +1414,7 @@ public class HeadsetClientStateMachineTest { public void testProcessVoiceRecognitionStartMessage_onConnectedState() { initToConnectedState(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); verify(mNativeInterface).startVoiceRecognition(any(BluetoothDevice.class)); } @@ -1456,7 +1426,7 @@ public class HeadsetClientStateMachineTest { HeadsetClientStateMachine.DISCONNECT)) .isFalse(); mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat( mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( HeadsetClientStateMachine.DISCONNECT)) @@ -1468,7 +1438,7 @@ public class HeadsetClientStateMachineTest { initToAudioOnState(); mHeadsetClientStateMachine.sendMessage( HeadsetClientStateMachine.DISCONNECT_AUDIO, mTestDevice); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); verify(mNativeInterface).disconnectAudio(any(BluetoothDevice.class)); } @@ -1482,7 +1452,7 @@ public class HeadsetClientStateMachineTest { int[] states = new int[1]; states[0] = HfpClientCall.CALL_STATE_ACTIVE; mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.HOLD_CALL, mTestDevice); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); verify(mNativeInterface).handleCallAction(any(BluetoothDevice.class), anyInt(), eq(0)); } @@ -1496,7 +1466,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); @@ -1512,7 +1482,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); } @@ -1531,7 +1501,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.mAudioWbs).isTrue(); assertThat(mHeadsetClientStateMachine.mAudioSWB).isFalse(); @@ -1543,7 +1513,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.mAudioWbs).isFalse(); assertThat(mHeadsetClientStateMachine.mAudioSWB).isTrue(); } @@ -1573,7 +1543,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -1587,13 +1557,13 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; mHeadsetClientStateMachine.sendMessage( mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); } private void verifySendBroadcastMultiplePermissions(Matcher... matchers) { - mInOrder.verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + mInOrder.verify(mHeadsetClientService) .sendBroadcastMultiplePermissions( MockitoHamcrest.argThat(AllOf.allOf(matchers)), any(String[].class), @@ -1601,7 +1571,7 @@ public class HeadsetClientStateMachineTest { } private void verifySendBroadcast(Matcher... matchers) { - mInOrder.verify(mHeadsetClientService, timeout(STANDARD_WAIT_MILLIS)) + mInOrder.verify(mHeadsetClientService) .sendBroadcast( MockitoHamcrest.argThat(AllOf.allOf(matchers)), anyString(), @@ -1612,7 +1582,7 @@ public class HeadsetClientStateMachineTest { int previousState = mHeadsetClientStateMachine.getConnectionState(mTestDevice); mHeadsetClientStateMachine.sendMessage(msg); - TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + mTestLooper.dispatchAll(); int newState = mHeadsetClientStateMachine.getConnectionState(mTestDevice); verifySendBroadcastMultiplePermissions( -- GitLab From 5dd4ce74bc413f26609ff8921c996139c539b6e3 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 19:25:38 -0700 Subject: [PATCH 167/875] HeadsetClient Test: import BluetoothProfile Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I41bdd08641f9f8c0520c1aefb9727f02782f3116 --- .../HeadsetClientStateMachineTest.java | 74 +++++++++---------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 2fa381eaf1c..96bc956a1e5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -16,6 +16,12 @@ package com.android.bluetooth.hfpclient; +import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; +import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; +import static android.bluetooth.BluetoothProfile.EXTRA_PREVIOUS_STATE; +import static android.bluetooth.BluetoothProfile.EXTRA_STATE; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; import static android.content.pm.PackageManager.FEATURE_WATCH; @@ -38,7 +44,6 @@ import android.bluetooth.BluetoothAssignedNumbers; 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.content.Intent; @@ -152,7 +157,7 @@ public class HeadsetClientStateMachineTest { @Test public void testDefaultDisconnectedState() { assertThat(mHeadsetClientStateMachine.getConnectionState(null)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + .isEqualTo(STATE_DISCONNECTED); } /** Test that an incoming connection with low priority is rejected */ @@ -160,7 +165,7 @@ public class HeadsetClientStateMachineTest { public void testIncomingPriorityReject() { // Return false for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + .thenReturn(CONNECTION_POLICY_FORBIDDEN); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -171,10 +176,8 @@ public class HeadsetClientStateMachineTest { // Verify that only DISCONNECTED -> DISCONNECTED broadcast is fired verifySendBroadcastMultiplePermissions( hasAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED), - hasExtra( - BluetoothProfile.EXTRA_PREVIOUS_STATE, - BluetoothProfile.STATE_DISCONNECTED)); + hasExtra(EXTRA_STATE, STATE_DISCONNECTED), + hasExtra(EXTRA_PREVIOUS_STATE, STATE_DISCONNECTED)); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); } @@ -184,7 +187,7 @@ public class HeadsetClientStateMachineTest { public void testIncomingPriorityAccept() { // Return true for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -193,8 +196,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connecting.class); @@ -210,8 +212,7 @@ public class HeadsetClientStateMachineTest { setUpAndroidAt(false); // Verify that one connection state broadcast is executed - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTED)); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -222,7 +223,7 @@ public class HeadsetClientStateMachineTest { public void testIncomingTimeout() { // Return true for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -231,16 +232,14 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connecting.class); // Trigger timeout mTestLooper.moveTimeForward(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS); mTestLooper.dispatchAll(); - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_DISCONNECTED)); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); @@ -331,7 +330,7 @@ public class HeadsetClientStateMachineTest { public void testInBandRingtone() { // Return true for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); assertThat(mHeadsetClientStateMachine.getInBandRing()).isFalse(); @@ -342,8 +341,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); // Send a message to trigger SLC connection StackEvent slcEvent = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -355,8 +353,7 @@ public class HeadsetClientStateMachineTest { setUpAndroidAt(false); - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTED)); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -429,7 +426,7 @@ public class HeadsetClientStateMachineTest { // Return true for connection policy to allow connections when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); // Send an incoming connection event StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -485,8 +482,7 @@ public class HeadsetClientStateMachineTest { connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.device = mTestDevice; mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTING)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); } /* Utility function to simulate SLC connection. */ @@ -506,8 +502,7 @@ public class HeadsetClientStateMachineTest { setUpAndroidAt(androidAtSupported); - verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED)); + verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTED)); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -553,7 +548,7 @@ public class HeadsetClientStateMachineTest { private void runSupportedVendorAtCommand(String atCommand, int vendorId) { // Return true for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -593,7 +588,7 @@ public class HeadsetClientStateMachineTest { public void runUnsupportedVendorAtCommand(String atCommand, int vendorId) { // Return true for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -630,7 +625,7 @@ public class HeadsetClientStateMachineTest { int vendorId, String vendorEventCode, String vendorEventArgument) { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -672,7 +667,7 @@ public class HeadsetClientStateMachineTest { int vendorId, String vendorEventCode, String vendorEventArgument) { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -711,7 +706,7 @@ public class HeadsetClientStateMachineTest { public void testVoiceRecognitionStateChange() { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); doReturn(true).when(mNativeInterface).startVoiceRecognition(any(BluetoothDevice.class)); doReturn(true).when(mNativeInterface).stopVoiceRecognition(any(BluetoothDevice.class)); @@ -754,7 +749,7 @@ public class HeadsetClientStateMachineTest { public void testSendBIEVCommand() { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -784,7 +779,7 @@ public class HeadsetClientStateMachineTest { public void testSendBatteryUpdateIndicatorWhenConnect() { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -923,7 +918,7 @@ public class HeadsetClientStateMachineTest { @Test public void testGetConnectionState_withNullDevice() { assertThat(mHeadsetClientStateMachine.getConnectionState(null)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + .isEqualTo(STATE_DISCONNECTED); } @Test @@ -931,7 +926,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.mCurrentDevice = mTestDevice; assertThat(mHeadsetClientStateMachine.getConnectionState(mTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + .isEqualTo(STATE_DISCONNECTED); } @Test @@ -1130,7 +1125,7 @@ public class HeadsetClientStateMachineTest { public void testAndroidAtRemoteNotSupported_StateTransition_setAudioPolicy() { // Setup connection state machine to be in connected state when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -1146,7 +1141,7 @@ public class HeadsetClientStateMachineTest { public void testSetGetCallAudioPolicy() { // Return true for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(true); @@ -1586,8 +1581,7 @@ public class HeadsetClientStateMachineTest { int newState = mHeadsetClientStateMachine.getConnectionState(mTestDevice); verifySendBroadcastMultiplePermissions( - hasExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, previousState), - hasExtra(BluetoothProfile.EXTRA_STATE, newState)); + hasExtra(EXTRA_PREVIOUS_STATE, previousState), hasExtra(EXTRA_STATE, newState)); assertThat(mHeadsetClientStateMachine.getCurrentState()).isInstanceOf(type); } -- GitLab From ae5728ce8785f1a1a383b26015df76875d9525cd Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 20:12:41 -0700 Subject: [PATCH 168/875] HeadsetClient Test: remove flaky test Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I72f59b30873707d628e27c1701f138d21b76ef1e --- .../bluetooth/hfpclient/HeadsetClientStateMachineTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 96bc956a1e5..7dfd999f926 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -57,7 +57,6 @@ import android.os.test.TestLooper; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Pair; -import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -326,7 +325,6 @@ public class HeadsetClientStateMachineTest { /** Test that In Band Ringtone information is relayed from phone. */ @Test - @FlakyTest public void testInBandRingtone() { // Return true for priority. when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) -- GitLab From f1331c6514108ed9ca39cf83b9fc206e8891da83 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 20:12:50 -0700 Subject: [PATCH 169/875] HeadsetClient Test: uniform mocking with doReturn Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I0fac4a9ee453160874292995e0e0dde978727be8 --- .../HeadsetClientStateMachineTest.java | 96 +++++-------------- 1 file changed, 26 insertions(+), 70 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 7dfd999f926..30e961c2304 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -44,8 +44,10 @@ import android.bluetooth.BluetoothAssignedNumbers; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadsetClient; import android.bluetooth.BluetoothHeadsetClientCall; +import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothSinkAudioPolicy; import android.bluetooth.BluetoothStatusCodes; +import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -57,10 +59,12 @@ import android.os.test.TestLooper; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Pair; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; +import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.RemoteDevices; import com.android.bluetooth.hfp.HeadsetService; @@ -85,10 +89,13 @@ import java.util.Set; @SmallTest @RunWith(AndroidJUnit4.class) public class HeadsetClientStateMachineTest { - private BluetoothAdapter mAdapter; + private final Context mTargetContext = InstrumentationRegistry.getTargetContext(); + private final BluetoothAdapter mAdapter = + mTargetContext.getSystemService(BluetoothManager.class).getAdapter(); + private final BluetoothDevice mTestDevice = TestUtils.getTestDevice(mAdapter, 42); + private TestHeadsetClientStateMachine mHeadsetClientStateMachine; private InOrder mInOrder; - private BluetoothDevice mTestDevice; private TestLooper mTestLooper; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -109,25 +116,23 @@ public class HeadsetClientStateMachineTest { mInOrder = inOrder(mHeadsetClientService); // Setup mocks and test assets // Set a valid volume - when(mAudioManager.getStreamVolume(anyInt())).thenReturn(2); - when(mAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10); - when(mAudioManager.getStreamMinVolume(anyInt())).thenReturn(1); - when(mHeadsetClientService.getAudioManager()).thenReturn(mAudioManager); - when(mHeadsetClientService.getResources()).thenReturn(mMockHfpResources); - when(mHeadsetClientService.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.hasSystemFeature(FEATURE_WATCH)).thenReturn(false); - when(mMockHfpResources.getBoolean(R.bool.hfp_clcc_poll_during_call)).thenReturn(true); - when(mMockHfpResources.getInteger(R.integer.hfp_clcc_poll_interval_during_call)) - .thenReturn(2000); + doReturn(2).when(mAudioManager).getStreamVolume(anyInt()); + doReturn(10).when(mAudioManager).getStreamMaxVolume(anyInt()); + doReturn(1).when(mAudioManager).getStreamMinVolume(anyInt()); + + doReturn(mAudioManager).when(mHeadsetClientService).getAudioManager(); + doReturn(mMockHfpResources).when(mHeadsetClientService).getResources(); + doReturn(mPackageManager).when(mHeadsetClientService).getPackageManager(); + doReturn(CONNECTION_POLICY_ALLOWED).when(mHeadsetClientService).getConnectionPolicy(any()); + + doReturn(true).when(mMockHfpResources).getBoolean(eq(R.bool.hfp_clcc_poll_during_call)); + doReturn(2000) + .when(mMockHfpResources) + .getInteger(eq(R.integer.hfp_clcc_poll_interval_during_call)); doReturn(mRemoteDevices).when(mAdapterService).getRemoteDevices(); doReturn(true).when(mNativeInterface).sendAndroidAt(anyObject(), anyString()); - // This line must be called to make sure relevant objects are initialized properly - mAdapter = BluetoothAdapter.getDefaultAdapter(); - // Get a device for testing - mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); - // Setup thread and looper mTestLooper = new TestLooper(); // Manage looper execution in main test thread explicitly to guarantee timing consistency @@ -152,7 +157,6 @@ public class HeadsetClientStateMachineTest { } /** Test that default state is disconnected */ - @SmallTest @Test public void testDefaultDisconnectedState() { assertThat(mHeadsetClientStateMachine.getConnectionState(null)) @@ -162,9 +166,9 @@ public class HeadsetClientStateMachineTest { /** Test that an incoming connection with low priority is rejected */ @Test public void testIncomingPriorityReject() { - // Return false for priority. - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_FORBIDDEN); + doReturn(CONNECTION_POLICY_FORBIDDEN) + .when(mHeadsetClientService) + .getConnectionPolicy(any()); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -184,10 +188,6 @@ public class HeadsetClientStateMachineTest { /** Test that an incoming connection with high priority is accepted */ @Test public void testIncomingPriorityAccept() { - // Return true for priority. - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; @@ -220,10 +220,6 @@ public class HeadsetClientStateMachineTest { /** Test that an incoming connection that times out */ @Test public void testIncomingTimeout() { - // Return true for priority. - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; @@ -326,10 +322,6 @@ public class HeadsetClientStateMachineTest { /** Test that In Band Ringtone information is relayed from phone. */ @Test public void testInBandRingtone() { - // Return true for priority. - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - assertThat(mHeadsetClientStateMachine.getInBandRing()).isFalse(); // Inject an event for when incoming connection is requested @@ -417,15 +409,11 @@ public class HeadsetClientStateMachineTest { @Test public void testWearablesUseBluetoothHeadsetClientCallInIntent() { // Specify the watch form factor when package manager is asked - when(mPackageManager.hasSystemFeature(FEATURE_WATCH)).thenReturn(true); + doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_WATCH); // Skip over the Android AT commands to test this code path doReturn(false).when(mNativeInterface).sendAndroidAt(anyObject(), anyString()); - // Return true for connection policy to allow connections - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - // Send an incoming connection event StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.device = mTestDevice; @@ -544,10 +532,6 @@ public class HeadsetClientStateMachineTest { /* Utility function: supported AT command should lead to native call */ private void runSupportedVendorAtCommand(String atCommand, int vendorId) { - // Return true for priority. - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -584,10 +568,6 @@ public class HeadsetClientStateMachineTest { /* utility function: unsupported vendor specific command shall be filtered. */ public void runUnsupportedVendorAtCommand(String atCommand, int vendorId) { - // Return true for priority. - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -621,9 +601,6 @@ public class HeadsetClientStateMachineTest { */ private void runSupportedVendorEvent( int vendorId, String vendorEventCode, String vendorEventArgument) { - // Setup connection state machine to be in connected state - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -663,9 +640,6 @@ public class HeadsetClientStateMachineTest { /* Utility test function: unsupported vendor specific response shall be filtered out*/ public void runUnsupportedVendorEvent( int vendorId, String vendorEventCode, String vendorEventArgument) { - // Setup connection state machine to be in connected state - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -702,9 +676,6 @@ public class HeadsetClientStateMachineTest { /** Test voice recognition state change broadcast. */ @Test public void testVoiceRecognitionStateChange() { - // Setup connection state machine to be in connected state - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); doReturn(true).when(mNativeInterface).startVoiceRecognition(any(BluetoothDevice.class)); doReturn(true).when(mNativeInterface).stopVoiceRecognition(any(BluetoothDevice.class)); @@ -745,9 +716,6 @@ public class HeadsetClientStateMachineTest { /** Test send BIEV command */ @Test public void testSendBIEVCommand() { - // Setup connection state machine to be in connected state - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -775,10 +743,6 @@ public class HeadsetClientStateMachineTest { */ @Test public void testSendBatteryUpdateIndicatorWhenConnect() { - // Setup connection state machine to be in connected state - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -1121,10 +1085,6 @@ public class HeadsetClientStateMachineTest { */ @Test public void testAndroidAtRemoteNotSupported_StateTransition_setAudioPolicy() { - // Setup connection state machine to be in connected state - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); - setUpHfpClientConnection(); setUpServiceLevelConnection(); @@ -1134,12 +1094,8 @@ public class HeadsetClientStateMachineTest { .sendAndroidAt(mTestDevice, "+ANDROID=SINKAUDIOPOLICY,0,0,0"); } - @SmallTest @Test public void testSetGetCallAudioPolicy() { - // Return true for priority. - when(mHeadsetClientService.getConnectionPolicy(any(BluetoothDevice.class))) - .thenReturn(CONNECTION_POLICY_ALLOWED); setUpHfpClientConnection(); setUpServiceLevelConnection(true); -- GitLab From cabed1be6df5dad6a86c8a1292375149c550524c Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 20:12:57 -0700 Subject: [PATCH 170/875] HeadsetClient Test: sendMessage process it Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I5c9515fa7e9130241ad725e7ead9391ee7953119 --- .../HeadsetClientStateMachineTest.java | 194 +++++++----------- 1 file changed, 75 insertions(+), 119 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index 30e961c2304..ecaaff3734f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -114,7 +114,7 @@ public class HeadsetClientStateMachineTest { @Before public void setUp() throws Exception { mInOrder = inOrder(mHeadsetClientService); - // Setup mocks and test assets + // Set a valid volume doReturn(2).when(mAudioManager).getStreamVolume(anyInt()); doReturn(10).when(mAudioManager).getStreamMaxVolume(anyInt()); @@ -133,9 +133,7 @@ public class HeadsetClientStateMachineTest { doReturn(mRemoteDevices).when(mAdapterService).getRemoteDevices(); doReturn(true).when(mNativeInterface).sendAndroidAt(anyObject(), anyString()); - // Setup thread and looper mTestLooper = new TestLooper(); - // Manage looper execution in main test thread explicitly to guarantee timing consistency mHeadsetClientStateMachine = new TestHeadsetClientStateMachine( mAdapterService, @@ -174,7 +172,7 @@ public class HeadsetClientStateMachineTest { StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); + sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that only DISCONNECTED -> DISCONNECTED broadcast is fired verifySendBroadcastMultiplePermissions( @@ -192,7 +190,7 @@ public class HeadsetClientStateMachineTest { StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); + sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); @@ -205,8 +203,7 @@ public class HeadsetClientStateMachineTest { slcEvent.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED; slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; slcEvent.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, slcEvent); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, slcEvent); setUpAndroidAt(false); @@ -224,7 +221,7 @@ public class HeadsetClientStateMachineTest { StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); + sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); @@ -328,7 +325,7 @@ public class HeadsetClientStateMachineTest { StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); + sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); @@ -338,8 +335,7 @@ public class HeadsetClientStateMachineTest { slcEvent.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED; slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; slcEvent.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, slcEvent); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, slcEvent); setUpAndroidAt(false); @@ -355,15 +351,13 @@ public class HeadsetClientStateMachineTest { StackEvent eventInBandRing = new StackEvent(StackEvent.EVENT_TYPE_IN_BAND_RINGTONE); eventInBandRing.valueInt = 1; eventInBandRing.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventInBandRing); + sendMessage(StackEvent.STACK_EVENT, eventInBandRing); verifySendBroadcast(hasExtra(BluetoothHeadsetClient.EXTRA_IN_BAND_RING, 1)); assertThat(mHeadsetClientStateMachine.getInBandRing()).isTrue(); // Simulate a new incoming phone call StackEvent eventCallStatusUpdated = new StackEvent(StackEvent.EVENT_TYPE_CLIP); - mTestLooper.dispatchAll(); - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventCallStatusUpdated); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, eventCallStatusUpdated); mInOrder.verify(mHeadsetClientService, never()) .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); @@ -376,16 +370,14 @@ public class HeadsetClientStateMachineTest { eventIncomingCall.valueString = "5551212"; // phone number eventIncomingCall.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventIncomingCall); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, eventIncomingCall); mInOrder.verify(mHeadsetClientService, never()) .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); // Signal that the complete list of calls was received. StackEvent eventCommandStatus = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); eventCommandStatus.valueInt = AT_OK; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventCommandStatus); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, eventCommandStatus); ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); mInOrder.verify(mHeadsetClientService) @@ -400,7 +392,7 @@ public class HeadsetClientStateMachineTest { // Disable In Band Ring and verify state gets propagated. eventInBandRing.valueInt = 0; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, eventInBandRing); + sendMessage(StackEvent.STACK_EVENT, eventInBandRing); verifySendBroadcast(hasExtra(BluetoothHeadsetClient.EXTRA_IN_BAND_RING, 0)); assertThat(mHeadsetClientStateMachine.getInBandRing()).isFalse(); } @@ -418,18 +410,18 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.device = mTestDevice; event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); + sendMessage(StackEvent.STACK_EVENT, event); // Send a message to trigger service level connection using the required ECS feature event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.device = mTestDevice; event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED; event.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); + sendMessage(StackEvent.STACK_EVENT, event); // Dial a phone call, which will fail as @{code dial} method is not specified in @{code // mNativeInterface} mock and trigger a call state changed broadcast - mHeadsetClientStateMachine.sendMessage( + sendMessage( HeadsetClientStateMachine.DIAL_NUMBER, new HfpClientCall( mTestDevice, @@ -440,9 +432,6 @@ public class HeadsetClientStateMachineTest { false, false)); - // Wait for processing - mTestLooper.dispatchAll(); - // Verify the broadcast ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); mInOrder.verify(mHeadsetClientService) @@ -467,7 +456,7 @@ public class HeadsetClientStateMachineTest { StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh); + sendMessage(StackEvent.STACK_EVENT, connStCh); verifySendBroadcastMultiplePermissions(hasExtra(EXTRA_STATE, STATE_CONNECTING)); } @@ -483,8 +472,7 @@ public class HeadsetClientStateMachineTest { slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; slcEvent.valueInt2 |= HeadsetClientHalConstants.PEER_FEAT_HF_IND; slcEvent.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, slcEvent); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, slcEvent); setUpAndroidAt(androidAtSupported); @@ -505,15 +493,13 @@ public class HeadsetClientStateMachineTest { StackEvent unknownEvt = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT); unknownEvt.valueString = "+ANDROID: (SINKAUDIOPOLICY)"; unknownEvt.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, unknownEvt); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, unknownEvt); // receive CMD_RESULT OK after the Android AT command from remote StackEvent cmdResEvt = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); cmdResEvt.valueInt = StackEvent.CMD_RESULT_TYPE_OK; cmdResEvt.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, cmdResEvt); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, cmdResEvt); assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) .isEqualTo(BluetoothStatusCodes.FEATURE_SUPPORTED); @@ -522,8 +508,7 @@ public class HeadsetClientStateMachineTest { StackEvent cmdResEvt = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); cmdResEvt.valueInt = StackEvent.CMD_RESULT_TYPE_CME_ERROR; cmdResEvt.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, cmdResEvt); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, cmdResEvt); assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) .isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); @@ -535,11 +520,7 @@ public class HeadsetClientStateMachineTest { setUpHfpClientConnection(); setUpServiceLevelConnection(); - Message msg = - mHeadsetClientStateMachine.obtainMessage( - HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, vendorId, 0, atCommand); - mHeadsetClientStateMachine.sendMessage(msg); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, vendorId, 0, atCommand); verify(mNativeInterface) .sendATCmd( @@ -571,11 +552,7 @@ public class HeadsetClientStateMachineTest { setUpHfpClientConnection(); setUpServiceLevelConnection(); - Message msg = - mHeadsetClientStateMachine.obtainMessage( - HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, vendorId, 0, atCommand); - mHeadsetClientStateMachine.sendMessage(msg); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, vendorId, 0, atCommand); verify(mNativeInterface, never()).sendATCmd(any(), anyInt(), anyInt(), anyInt(), any()); } @@ -609,7 +586,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT); event.device = mTestDevice; event.valueString = vendorEvent; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); + sendMessage(StackEvent.STACK_EVENT, event); // Validate broadcast intent verifySendBroadcast( @@ -648,7 +625,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT); event.device = mTestDevice; event.valueString = vendorEvent; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); + sendMessage(StackEvent.STACK_EVENT, event); // Validate no broadcast intent verify(mHeadsetClientService, atMost(2)) @@ -683,13 +660,13 @@ public class HeadsetClientStateMachineTest { setUpServiceLevelConnection(); // Simulate a voice recognition start - mHeadsetClientStateMachine.sendMessage(VOICE_RECOGNITION_START); + sendMessage(VOICE_RECOGNITION_START); // Signal that the complete list of actions was received. StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); event.device = mTestDevice; event.valueInt = AT_OK; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); + sendMessage(StackEvent.STACK_EVENT, event); verifySendBroadcast( hasAction(BluetoothHeadsetClient.ACTION_AG_EVENT), @@ -698,13 +675,13 @@ public class HeadsetClientStateMachineTest { HeadsetClientHalConstants.VR_STATE_STARTED)); // Simulate a voice recognition stop - mHeadsetClientStateMachine.sendMessage(VOICE_RECOGNITION_STOP); + sendMessage(VOICE_RECOGNITION_STOP); // Signal that the complete list of actions was received. event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); event.device = mTestDevice; event.valueInt = AT_OK; - mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, event); + sendMessage(StackEvent.STACK_EVENT, event); verifySendBroadcast( hasAction(BluetoothHeadsetClient.ACTION_AG_EVENT), @@ -722,12 +699,7 @@ public class HeadsetClientStateMachineTest { int indicator_id = 2; int indicator_value = 50; - Message msg = mHeadsetClientStateMachine.obtainMessage(HeadsetClientStateMachine.SEND_BIEV); - msg.arg1 = indicator_id; - msg.arg2 = indicator_value; - - mHeadsetClientStateMachine.sendMessage(msg); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.SEND_BIEV, indicator_id, indicator_value); verify(mNativeInterface) .sendATCmd( @@ -1144,9 +1116,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_CONNECTED; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); @@ -1154,9 +1124,7 @@ public class HeadsetClientStateMachineTest { event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); @@ -1170,8 +1138,7 @@ public class HeadsetClientStateMachineTest { @Test public void testProcessDisconnectMessage_onDisconnectedState() { - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.DISCONNECT); assertThat(mHeadsetClientStateMachine.getConnectionState(mTestDevice)) .isEqualTo(STATE_DISCONNECTED); } @@ -1214,8 +1181,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( HeadsetClientStateMachine.CONNECT)) .isFalse(); - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.CONNECT); assertThat( mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( HeadsetClientStateMachine.CONNECT)) @@ -1240,8 +1206,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connecting.class); } @@ -1252,8 +1217,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTING; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connecting.class); } @@ -1266,9 +1230,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)) .isFalse(); - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)) .isTrue(); } @@ -1279,8 +1241,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); event.valueInt = StackEvent.CMD_RESULT_TYPE_OK; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connecting.class); } @@ -1293,9 +1254,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT); event.valueString = atCommand; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -1319,9 +1278,7 @@ public class HeadsetClientStateMachineTest { event.device = mTestDevice; assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)) .isFalse(); - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(StackEvent.STACK_EVENT)) .isTrue(); } @@ -1329,8 +1286,7 @@ public class HeadsetClientStateMachineTest { @Test public void testProcessConnectMessage_onConnectedState() { initToConnectedState(); - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.CONNECT); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); } @@ -1338,32 +1294,28 @@ public class HeadsetClientStateMachineTest { @Test public void testProcessDisconnectMessage_onConnectedState() { initToConnectedState(); - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice); verify(mNativeInterface).disconnect(any(BluetoothDevice.class)); } @Test public void testProcessConnectAudioMessage_onConnectedState() { initToConnectedState(); - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO); verify(mNativeInterface).connectAudio(any(BluetoothDevice.class)); } @Test public void testProcessDisconnectAudioMessage_onConnectedState() { initToConnectedState(); - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO); verify(mNativeInterface).disconnectAudio(any(BluetoothDevice.class)); } @Test public void testProcessVoiceRecognitionStartMessage_onConnectedState() { initToConnectedState(); - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START); verify(mNativeInterface).startVoiceRecognition(any(BluetoothDevice.class)); } @@ -1374,8 +1326,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( HeadsetClientStateMachine.DISCONNECT)) .isFalse(); - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice); assertThat( mHeadsetClientStateMachine.doesSuperHaveDeferredMessages( HeadsetClientStateMachine.DISCONNECT)) @@ -1385,9 +1336,7 @@ public class HeadsetClientStateMachineTest { @Test public void testProcessDisconnectAudioMessage_onAudioOnState() { initToAudioOnState(); - mHeadsetClientStateMachine.sendMessage( - HeadsetClientStateMachine.DISCONNECT_AUDIO, mTestDevice); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO, mTestDevice); verify(mNativeInterface).disconnectAudio(any(BluetoothDevice.class)); } @@ -1400,8 +1349,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.mCalls.put(0, call); int[] states = new int[1]; states[0] = HfpClientCall.CALL_STATE_ACTIVE; - mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.HOLD_CALL, mTestDevice); - mTestLooper.dispatchAll(); + sendMessage(HeadsetClientStateMachine.HOLD_CALL, mTestDevice); verify(mNativeInterface).handleCallAction(any(BluetoothDevice.class), anyInt(), eq(0)); } @@ -1413,9 +1361,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Disconnected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); @@ -1429,9 +1375,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); } @@ -1448,9 +1392,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_CONNECTED_MSBC; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.mAudioWbs).isTrue(); assertThat(mHeadsetClientStateMachine.mAudioSWB).isFalse(); @@ -1460,9 +1402,7 @@ public class HeadsetClientStateMachineTest { event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_CONNECTED_LC3; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.mAudioWbs).isFalse(); assertThat(mHeadsetClientStateMachine.mAudioSWB).isTrue(); } @@ -1490,9 +1430,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT); event.valueString = atCommand; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.Connected.class); verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(true)); @@ -1504,9 +1442,7 @@ public class HeadsetClientStateMachineTest { StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_CONNECTED; event.device = mTestDevice; - mHeadsetClientStateMachine.sendMessage( - mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event)); - mTestLooper.dispatchAll(); + sendMessage(StackEvent.STACK_EVENT, event); assertThat(mHeadsetClientStateMachine.getCurrentState()) .isInstanceOf(HeadsetClientStateMachine.AudioOn.class); } @@ -1527,11 +1463,31 @@ public class HeadsetClientStateMachineTest { any(Bundle.class)); } + private void sendMessage(Message msg) { + mHeadsetClientStateMachine.sendMessage(msg); + mTestLooper.dispatchAll(); + } + + private void sendMessage(int what) { + sendMessage(mHeadsetClientStateMachine.obtainMessage(what)); + } + + private void sendMessage(int what, Object obj) { + sendMessage(mHeadsetClientStateMachine.obtainMessage(what, obj)); + } + + private void sendMessage(int what, int arg1, int arg2) { + sendMessage(mHeadsetClientStateMachine.obtainMessage(what, arg1, arg2)); + } + + private void sendMessage(int what, int arg1, int arg2, Object obj) { + sendMessage(mHeadsetClientStateMachine.obtainMessage(what, arg1, arg2, obj)); + } + private void sendMessageAndVerifyTransition(Message msg, Class type) { int previousState = mHeadsetClientStateMachine.getConnectionState(mTestDevice); - mHeadsetClientStateMachine.sendMessage(msg); - mTestLooper.dispatchAll(); + sendMessage(msg); int newState = mHeadsetClientStateMachine.getConnectionState(mTestDevice); verifySendBroadcastMultiplePermissions( -- GitLab From 04f93fc909d22d8602055240de5d15612d6e9b9e Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 20:26:15 -0700 Subject: [PATCH 171/875] HeadsetClient Test: help formatter to be pretty Bug: 311772251 Test: atest HeadsetClientStateMachineTest Flag: TEST_ONLY Change-Id: I4544a7219ffb801f308c9c03e03033cd140060ed --- .../HeadsetClientStateMachineTest.java | 161 +++++------------- 1 file changed, 47 insertions(+), 114 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index ecaaff3734f..1ca22bec3c5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -237,47 +237,30 @@ public class HeadsetClientStateMachineTest { verify(mHeadsetService).updateInbandRinging(eq(mTestDevice), eq(false)); } + private boolean processAndroidSlcCommand(String command) { + return mHeadsetClientStateMachine.processAndroidSlcCommand(command, mTestDevice); + } + @Test public void testProcessAndroidSlcCommand() { initToConnectedState(); // True on correct AT command and BluetothDevice + assertThat(processAndroidSlcCommand("+ANDROID: (SINKAUDIOPOLICY)")).isTrue(); + assertThat(processAndroidSlcCommand("+ANDROID: ()")).isTrue(); + assertThat(processAndroidSlcCommand("+ANDROID: (,,,)")).isTrue(); + assertThat(processAndroidSlcCommand("+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE)")).isTrue(); assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY)", mTestDevice)) - .isTrue(); - assertThat(mHeadsetClientStateMachine.processAndroidSlcCommand("+ANDROID: ()", mTestDevice)) - .isTrue(); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (,,,)", mTestDevice)) - .isTrue(); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE)", mTestDevice)) - .isTrue(); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE,1,2,3),(1,2,3)", - mTestDevice)) - .isTrue(); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: 123", mTestDevice)) - .isTrue(); - assertThat(mHeadsetClientStateMachine.processAndroidSlcCommand("+ANDROID: ", mTestDevice)) + processAndroidSlcCommand( + "+ANDROID: (SINKAUDIOPOLICY),(OTHERFEATURE,1,2,3),(1,2,3)")) .isTrue(); + assertThat(processAndroidSlcCommand("+ANDROID: 123")).isTrue(); + assertThat(processAndroidSlcCommand("+ANDROID: ")).isTrue(); // False on incorrect AT command format - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID= (SINKAUDIOPOLICY)", mTestDevice)) - .isFalse(); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "RANDOM ^%$# STRING", mTestDevice)) - .isFalse(); - assertThat(mHeadsetClientStateMachine.processAndroidSlcCommand("", mTestDevice)).isFalse(); + assertThat(processAndroidSlcCommand("+ANDROID= (SINKAUDIOPOLICY)")).isFalse(); + assertThat(processAndroidSlcCommand("RANDOM ^%$# STRING")).isFalse(); + assertThat(processAndroidSlcCommand("")).isFalse(); // False on incorrect BluetoothDevice assertThat( @@ -292,26 +275,17 @@ public class HeadsetClientStateMachineTest { initToConnectedState(); mHeadsetClientStateMachine.setAudioPolicyRemoteSupported(false); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "RANDOM ^%$# STRING", mTestDevice)) - .isFalse(); + assertThat(processAndroidSlcCommand("RANDOM ^%$# STRING")).isFalse(); assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) .isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); mHeadsetClientStateMachine.setAudioPolicyRemoteSupported(false); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID= (SINKAUDIOPOLICY)", mTestDevice)) - .isFalse(); + assertThat(processAndroidSlcCommand("+ANDROID= (SINKAUDIOPOLICY)")).isFalse(); assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) .isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); mHeadsetClientStateMachine.setAudioPolicyRemoteSupported(false); - assertThat( - mHeadsetClientStateMachine.processAndroidSlcCommand( - "+ANDROID: (SINKAUDIOPOLICY)", mTestDevice)) - .isTrue(); + assertThat(processAndroidSlcCommand("+ANDROID: (SINKAUDIOPOLICY)")).isTrue(); assertThat(mHeadsetClientStateMachine.getAudioPolicyRemoteSupported()) .isEqualTo(BluetoothStatusCodes.FEATURE_SUPPORTED); } @@ -976,79 +950,38 @@ public class HeadsetClientStateMachineTest { assertThat(currentCalls.get(0)).isEqualTo(call); } + private void assertName(int message, String message_name) { + assertThat(HeadsetClientStateMachine.getMessageName(message)).isEqualTo(message_name); + } + @Test public void testGetMessageName() { - assertThat(HeadsetClientStateMachine.getMessageName(StackEvent.STACK_EVENT)) - .isEqualTo("STACK_EVENT"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.CONNECT)) - .isEqualTo("CONNECT"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISCONNECT)) - .isEqualTo("DISCONNECT"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.CONNECT_AUDIO)) - .isEqualTo("CONNECT_AUDIO"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.DISCONNECT_AUDIO)) - .isEqualTo("DISCONNECT_AUDIO"); - assertThat(HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_START)) - .isEqualTo("VOICE_RECOGNITION_START"); - assertThat(HeadsetClientStateMachine.getMessageName(VOICE_RECOGNITION_STOP)) - .isEqualTo("VOICE_RECOGNITION_STOP"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.SET_MIC_VOLUME)) - .isEqualTo("SET_MIC_VOLUME"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.SET_SPEAKER_VOLUME)) - .isEqualTo("SET_SPEAKER_VOLUME"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DIAL_NUMBER)) - .isEqualTo("DIAL_NUMBER"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.ACCEPT_CALL)) - .isEqualTo("ACCEPT_CALL"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.REJECT_CALL)) - .isEqualTo("REJECT_CALL"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.HOLD_CALL)) - .isEqualTo("HOLD_CALL"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.TERMINATE_CALL)) - .isEqualTo("TERMINATE_CALL"); - assertThat(HeadsetClientStateMachine.getMessageName(ENTER_PRIVATE_MODE)) - .isEqualTo("ENTER_PRIVATE_MODE"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_DTMF)) - .isEqualTo("SEND_DTMF"); - assertThat(HeadsetClientStateMachine.getMessageName(EXPLICIT_CALL_TRANSFER)) - .isEqualTo("EXPLICIT_CALL_TRANSFER"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.DISABLE_NREC)) - .isEqualTo("DISABLE_NREC"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND)) - .isEqualTo("SEND_VENDOR_AT_COMMAND"); - assertThat(HeadsetClientStateMachine.getMessageName(HeadsetClientStateMachine.SEND_BIEV)) - .isEqualTo("SEND_BIEV"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.QUERY_CURRENT_CALLS)) - .isEqualTo("QUERY_CURRENT_CALLS"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.QUERY_OPERATOR_NAME)) - .isEqualTo("QUERY_OPERATOR_NAME"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.SUBSCRIBER_INFO)) - .isEqualTo("SUBSCRIBER_INFO"); - assertThat( - HeadsetClientStateMachine.getMessageName( - HeadsetClientStateMachine.CONNECTING_TIMEOUT)) - .isEqualTo("CONNECTING_TIMEOUT"); + assertName(StackEvent.STACK_EVENT, "STACK_EVENT"); + assertName(HeadsetClientStateMachine.CONNECT, "CONNECT"); + assertName(HeadsetClientStateMachine.DISCONNECT, "DISCONNECT"); + assertName(HeadsetClientStateMachine.CONNECT_AUDIO, "CONNECT_AUDIO"); + assertName(HeadsetClientStateMachine.DISCONNECT_AUDIO, "DISCONNECT_AUDIO"); + assertName(VOICE_RECOGNITION_START, "VOICE_RECOGNITION_START"); + assertName(VOICE_RECOGNITION_STOP, "VOICE_RECOGNITION_STOP"); + assertName(HeadsetClientStateMachine.SET_MIC_VOLUME, "SET_MIC_VOLUME"); + assertName(HeadsetClientStateMachine.SET_SPEAKER_VOLUME, "SET_SPEAKER_VOLUME"); + assertName(HeadsetClientStateMachine.DIAL_NUMBER, "DIAL_NUMBER"); + assertName(HeadsetClientStateMachine.ACCEPT_CALL, "ACCEPT_CALL"); + assertName(HeadsetClientStateMachine.REJECT_CALL, "REJECT_CALL"); + assertName(HeadsetClientStateMachine.HOLD_CALL, "HOLD_CALL"); + assertName(HeadsetClientStateMachine.TERMINATE_CALL, "TERMINATE_CALL"); + assertName(ENTER_PRIVATE_MODE, "ENTER_PRIVATE_MODE"); + assertName(HeadsetClientStateMachine.SEND_DTMF, "SEND_DTMF"); + assertName(EXPLICIT_CALL_TRANSFER, "EXPLICIT_CALL_TRANSFER"); + assertName(HeadsetClientStateMachine.DISABLE_NREC, "DISABLE_NREC"); + assertName(HeadsetClientStateMachine.SEND_VENDOR_AT_COMMAND, "SEND_VENDOR_AT_COMMAND"); + assertName(HeadsetClientStateMachine.SEND_BIEV, "SEND_BIEV"); + assertName(HeadsetClientStateMachine.QUERY_CURRENT_CALLS, "QUERY_CURRENT_CALLS"); + assertName(HeadsetClientStateMachine.QUERY_OPERATOR_NAME, "QUERY_OPERATOR_NAME"); + assertName(HeadsetClientStateMachine.SUBSCRIBER_INFO, "SUBSCRIBER_INFO"); + assertName(HeadsetClientStateMachine.CONNECTING_TIMEOUT, "CONNECTING_TIMEOUT"); int unknownMessageInt = 54; - assertThat(HeadsetClientStateMachine.getMessageName(unknownMessageInt)) - .isEqualTo("UNKNOWN(" + unknownMessageInt + ")"); + assertName(unknownMessageInt, "UNKNOWN(" + unknownMessageInt + ")"); } /** -- GitLab From c34c81ace1d59bea19cb0e067282bfeca865cace Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Fri, 4 Oct 2024 15:31:05 +0900 Subject: [PATCH 172/875] BluetoothPbapActivityTest: Ignore exception from ActivityScenario.close Bug: 324551391 Test: atest BluetoothInstrumentationTests:BluetoothPbapActivityTest \ --rerun-until-failure 100 Flag: EXEMPT, test-only change Change-Id: Ic3cdc4ad6295c7387d716065e8ee95a39ff9af11 --- .../android/bluetooth/pbap/BluetoothPbapActivityTest.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapActivityTest.java index 54674b1d14c..1e837f3d9af 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapActivityTest.java @@ -84,7 +84,12 @@ public class BluetoothPbapActivityTest { if (mActivityScenario != null) { // Workaround for b/159805732. Without this, test hangs for 45 seconds. Thread.sleep(1_000); - mActivityScenario.close(); + try { + mActivityScenario.close(); + } catch (Exception e) { + // Ignore exception: Sometimes the state does not reach "DESTROYED", + // however this should not affect our test. + } } enableActivity(false); BluetoothMethodProxy.setInstanceForTesting(null); -- GitLab From dc54e0c5d23c7467e09504245f4cea3b7384af9a Mon Sep 17 00:00:00 2001 From: WhaleChang Date: Tue, 1 Oct 2024 16:44:31 +0800 Subject: [PATCH 173/875] Enable hfp offload if hfp software path is not enabled Bug: 349136324 Test: atest bluetooth_test_gd Test: offload_enabled=true if bluetooth.hfp.software_datapath.enabled=false Flag: EXEMPT desktop only Change-Id: Idb8593338551450d22d2670529b88703e0772950 --- system/stack/btm/btm_sco_hfp_hal_linux.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/stack/btm/btm_sco_hfp_hal_linux.cc b/system/stack/btm/btm_sco_hfp_hal_linux.cc index 1488b6899eb..018ba1fd652 100644 --- a/system/stack/btm/btm_sco_hfp_hal_linux.cc +++ b/system/stack/btm/btm_sco_hfp_hal_linux.cc @@ -294,6 +294,13 @@ void init() { bluetooth::log::info("Successfully queried SCO codec capabilities."); } +#ifndef TARGET_FLOSS + // If hfp software path is not enabled, fallback to offload path. + if (!osi_property_get_bool("bluetooth.hfp.software_datapath.enabled", false)) { + enable_offload(true); + } +#endif + close(fd); } -- GitLab From 8189e07cc0c3331e6f47ffe26f4c1ec2818a70e4 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 7 Oct 2024 16:11:59 +0000 Subject: [PATCH 174/875] Update PDL for the CS HCI according to the released BT core 6.0 Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 372000684 Test: m com.android.btservices Change-Id: If23855d2d18491076f3cd6dcea759de424d95b2a --- system/gd/hci/distance_measurement_manager.cc | 2 +- system/pdl/hci/hci_packets.pdl | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 6949069a0b1..6f31e98331c 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -538,7 +538,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { kMaxMainModeSteps, kMainModeRepetition, kMode0Steps, CsRole::INITIATOR, CsConfigRttType::RTT_WITH_128_BIT_RANDOM_SEQUENCE, CsSyncPhy::LE_1M_PHY, channel_map, kChannelMapRepetition, CsChannelSelectionType::TYPE_3B, - CsCh3cShape::HAT_SHAPE, kCh3cJump, Enable::DISABLED), + CsCh3cShape::HAT_SHAPE, kCh3cJump), handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); } diff --git a/system/pdl/hci/hci_packets.pdl b/system/pdl/hci/hci_packets.pdl index 9225204045c..df7c47db2a2 100644 --- a/system/pdl/hci/hci_packets.pdl +++ b/system/pdl/hci/hci_packets.pdl @@ -5012,6 +5012,7 @@ packet LeCsReadLocalSupportedCapabilitiesComplete : CommandComplete (command_op_ optional_t_fcs_times_supported : CsOptionalTFcsTimesSupported, optional_t_pm_times_supported : CsOptionalTPmTimesSupported, t_sw_time_supported : 8, + optional_tx_snr_capability : 8, } packet LeCsReadRemoteSupportedCapabilities : DistanceMeasurementCommand (op_code = LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES) { @@ -5044,6 +5045,7 @@ packet LeCsWriteCachedRemoteSupportedCapabilities : DistanceMeasurementCommand ( optional_t_fcs_times_supported : CsOptionalTFcsTimesSupported, optional_t_pm_times_supported : CsOptionalTPmTimesSupported, t_sw_time_supported : 8, + optional_tx_snr_capability: 8, } packet LeCsWriteCachedRemoteSupportedCapabilitiesComplete : CommandComplete (command_op_code = LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES) { @@ -5173,7 +5175,7 @@ packet LeCsCreateConfig : DistanceMeasurementCommand (op_code = LE_CS_CREATE_CON channel_selection_type : CsChannelSelectionType, ch3c_shape : CsCh3cShape, ch3c_jump : 8, - companion_signal_enable : Enable, + _reserved_ : 8, } packet LeCsCreateConfigStatus : CommandStatus (command_op_code = LE_CS_CREATE_CONFIG) { @@ -6801,6 +6803,7 @@ packet LeCsReadRemoteSupportedCapabilitiesComplete : LeMetaEvent (subevent_code optional_t_fcs_times_supported : CsOptionalTFcsTimesSupported, optional_t_pm_times_supported : CsOptionalTPmTimesSupported, t_sw_time_supported : 8, + optional_tx_snr_capability : 8, } packet LeCsReadRemoteFaeTableComplete : LeMetaEvent (subevent_code = LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE) { @@ -6854,7 +6857,7 @@ packet LeCsConfigComplete : LeMetaEvent (subevent_code = LE_CS_CONFIG_COMPLETE) channel_selection_type : CsChannelSelectionType, ch3c_shape : CsCh3cShape, ch3c_jump : 8, - companion_signal_enable : Enable, + _reserved_ : 8, t_ip1_time : 8, t_ip2_time : 8, t_fcs_time : 8, -- GitLab From 0841307823b0bdc4bd8840e1b80302f0839bb99c Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 7 Oct 2024 16:46:26 +0000 Subject: [PATCH 175/875] fix code error for sending ras data Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 372007410 Test: m com.android.btservices Change-Id: I32fa4139e99e648c577bb76ca5d045819fe67a63 --- system/gd/hci/distance_measurement_manager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 6949069a0b1..e73852cb75b 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -906,8 +906,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (procedure_data->local_status != CsProcedureDoneStatus::PARTIAL_RESULTS && unsent_data_size <= kMtuForRasData) { procedure_data->segmentation_header_.last_segment_ = 1; - } else if (procedure_data->ras_raw_data_.size() < kMtuForRasData) { - log::verbose("waiting for more data, current size {}", procedure_data->ras_raw_data_.size()); + } else if (unsent_data_size < kMtuForRasData) { + log::verbose("waiting for more data, current unsent data size {}", unsent_data_size); return; } -- GitLab From 5145e1af3dcc03442690262674c473a0de46666a Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 17:17:41 -0700 Subject: [PATCH 176/875] Hap: prevent setactive on unknow preset Bug: 371636624 Fix: 371636624 Test: atest avatar:HapTest#test__set_non_existing_preset_as_active__verify_no_crash_and_no_update Flag: Exempt feature is not shipped yet, fix has end-to-end test Change-Id: Ifd0ca9e3c262153e4bcff4d5ff321048c8d18e61 --- system/bta/has/has_client.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index b8b2aa327a0..2701fc47316 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -1566,7 +1566,15 @@ private: /* Get the active preset value */ auto* pp = value; - STREAM_TO_UINT8(device->currently_active_preset, pp); + uint8_t active_preset_index; + STREAM_TO_UINT8(active_preset_index, pp); + if (active_preset_index != 0 && device->isGattServiceValid() && + !device->has_presets.contains(active_preset_index)) { + log::error("Unknown preset {}. Active preset change is discarded", active_preset_index); + device->has_journal_.Append(HasJournalRecord(active_preset_index, false)); + return; + } + device->currently_active_preset = active_preset_index; if (device->isGattServiceValid()) { btif_storage_set_leaudio_has_active_preset(device->addr, device->currently_active_preset); @@ -1579,7 +1587,9 @@ private: MarkDeviceValidIfInInitialDiscovery(*device); if (device->isGattServiceValid()) { - if (!pending_group_operation_timeouts_.empty()) { + if (pending_group_operation_timeouts_.empty()) { + callbacks_->OnActivePresetSelected(device->addr, device->currently_active_preset); + } else { for (auto it = pending_group_operation_timeouts_.rbegin(); it != pending_group_operation_timeouts_.rend(); ++it) { auto& group_op_coordinator = it->second; @@ -1615,9 +1625,6 @@ private: break; } } - - } else { - callbacks_->OnActivePresetSelected(device->addr, device->currently_active_preset); } } } -- GitLab From 4aab5e40816314812a63e326e854bd8fc107a017 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 17:30:59 -0700 Subject: [PATCH 177/875] Hap: various cleanup in avatar Test: atest avatar:HapTest Bug: 311772251 Flag: TEST_ONLY Change-Id: I8f73b215af6592328c739d49b0676ab663c2b13a --- android/pandora/server/src/Hap.kt | 15 +++++---------- android/pandora/test/hap_test.py | 5 +++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/android/pandora/server/src/Hap.kt b/android/pandora/server/src/Hap.kt index 92fb7bbab6e..c4a6f84805d 100644 --- a/android/pandora/server/src/Hap.kt +++ b/android/pandora/server/src/Hap.kt @@ -156,8 +156,7 @@ class Hap(val context: Context) : HAPImplBase(), Closeable { ) { grpcUnary(scope, responseObserver) { val device = request.connection.toBluetoothDevice(bluetoothAdapter) - - Log.i(TAG, "getPresetRecord device=${device.address} index=${request.index}") + Log.i(TAG, "getPresetRecord($device, ${request.index})") val presetInfo: BluetoothHapPresetInfo? = bluetoothHapClient.getPresetInfo(device, request.index) @@ -211,8 +210,7 @@ class Hap(val context: Context) : HAPImplBase(), Closeable { ) { grpcUnary(scope, responseObserver) { val device = request.connection.toBluetoothDevice(bluetoothAdapter) - - Log.i(TAG, "writePresetName index=${request.index} name=${request.name}") + Log.i(TAG, "writePresetName($device, ${request.index}, ${request.name})") bluetoothHapClient.setPresetName(device, request.index, request.name) @@ -226,8 +224,7 @@ class Hap(val context: Context) : HAPImplBase(), Closeable { ) { grpcUnary(scope, responseObserver) { val device = request.connection.toBluetoothDevice(bluetoothAdapter) - - Log.i(TAG, "SetActivePreset") + Log.i(TAG, "SetActivePreset($device, ${request.index})") bluetoothHapClient.selectPreset(device, request.index) @@ -241,8 +238,7 @@ class Hap(val context: Context) : HAPImplBase(), Closeable { ) { grpcUnary(scope, responseObserver) { val device = request.connection.toBluetoothDevice(bluetoothAdapter) - - Log.i(TAG, "setNextPreset") + Log.i(TAG, "setNextPreset($device)") bluetoothHapClient.switchToNextPreset(device) @@ -256,8 +252,7 @@ class Hap(val context: Context) : HAPImplBase(), Closeable { ) { grpcUnary(scope, responseObserver) { val device = request.connection.toBluetoothDevice(bluetoothAdapter) - - Log.i(TAG, "setPreviousPreset") + Log.i(TAG, "setPreviousPreset($device)") bluetoothHapClient.switchToPreviousPreset(device) diff --git a/android/pandora/test/hap_test.py b/android/pandora/test/hap_test.py index f382cd86017..ec1fd40f89d 100644 --- a/android/pandora/test/hap_test.py +++ b/android/pandora/test/hap_test.py @@ -18,6 +18,7 @@ from bumble.gatt import GATT_HEARING_ACCESS_SERVICE, GATT_AUDIO_STREAM_CONTROL_S from bumble.profiles import hap from bumble.profiles.hap import DynamicPresets, HearingAccessService, HearingAidFeatures, HearingAidType, IndependentPresets, PresetRecord, PresetSynchronizationSupport, WritablePresetsSupport +from pandora_experimental.os_grpc_aio import Os as OsAio from pandora_experimental.gatt_grpc_aio import GATT from pandora_experimental.hap_grpc_aio import HAP from pandora_experimental.hap_pb2 import PresetRecord as grpcPresetRecord # type: ignore @@ -84,6 +85,8 @@ class HapTest(base_test.BaseTestClass): @asynchronous async def setup_test(self) -> None: await asyncio.gather(self.dut.reset(), self.ref_left.reset()) + self.logcat = OsAio(channel=self.dut.aio.channel) + await self.logcat.Log("setup test") self.hap_grpc = HAP(channel=self.dut.aio.channel) device_features = HearingAidFeatures(HearingAidType.MONAURAL_HEARING_AID, PresetSynchronizationSupport.PRESET_SYNCHRONIZATION_IS_NOT_SUPPORTED, @@ -162,6 +165,7 @@ class HapTest(base_test.BaseTestClass): @asynchronous async def test_get_features(self) -> None: + await self.logcat.Log("test_get_features") dut_connection_to_ref = await self.setupHapConnection() features = hap.HearingAidFeatures_from_bytes( @@ -170,6 +174,7 @@ class HapTest(base_test.BaseTestClass): @asynchronous async def test_get_preset(self) -> None: + await self.logcat.Log("test_get_preset") dut_connection_to_ref = await self.setupHapConnection() await self.assertIdentiqPresetInDutAndRef(dut_connection_to_ref) -- GitLab From cc7d9dd01b0b56117cf2687d2f787d689f80c465 Mon Sep 17 00:00:00 2001 From: Sarvesh Kalwit Date: Thu, 26 Sep 2024 16:19:49 +0000 Subject: [PATCH 178/875] Revert "Msft: Remove dead code from android target" This reverts commit 8e0be6a705323866b62934df8eaddd1f79f328bb. Bug: 360384729 Bug: 365787977 Test: m -j Change-Id: I66318d1a7e0b64e451f65a17e580e5d22c1de3aa --- system/gd/hci/Android.bp | 1 + system/gd/hci/msft.cc | 2 -- system/gd/hci/msft.h | 2 -- .../gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc | 13 ------------- system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h | 2 -- system/include/hardware/ble_scanner.h | 4 ---- system/main/shim/ble_scanner_interface_impl.h | 6 ------ system/main/shim/entry.cc | 4 ---- system/main/shim/entry.h | 4 ---- system/main/shim/le_scanning_manager.cc | 6 ------ system/main/shim/stack.cc | 4 ---- system/test/mock/mock_main_shim_entry.cc | 2 -- 12 files changed, 1 insertion(+), 49 deletions(-) diff --git a/system/gd/hci/Android.bp b/system/gd/hci/Android.bp index 9ebf5108635..d0fc019dd5e 100644 --- a/system/gd/hci/Android.bp +++ b/system/gd/hci/Android.bp @@ -26,6 +26,7 @@ filegroup { "le_scanning_manager.cc", "le_scanning_reassembler.cc", "link_key.cc", + "msft.cc", "remote_name_request.cc", "uuid.cc", ], diff --git a/system/gd/hci/msft.cc b/system/gd/hci/msft.cc index e663438952e..b27bcf23d5a 100644 --- a/system/gd/hci/msft.cc +++ b/system/gd/hci/msft.cc @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#if TARGET_FLOSS #include "hci/msft.h" #include @@ -358,4 +357,3 @@ void MsftExtensionManager::SetScanningCallback(ScanningCallback* callbacks) { } // namespace hci } // namespace bluetooth -#endif diff --git a/system/gd/hci/msft.h b/system/gd/hci/msft.h index 5e31a6b345a..70b41ee8ce1 100644 --- a/system/gd/hci/msft.h +++ b/system/gd/hci/msft.h @@ -14,7 +14,6 @@ * limitations under the License. */ #pragma once -#if TARGET_FLOSS #include "hci/hci_packets.h" #include "hci/le_scanning_callback.h" @@ -61,4 +60,3 @@ private: } // namespace hci } // namespace bluetooth -#endif diff --git a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc index 6573b024579..2bfa893d808 100644 --- a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc +++ b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc @@ -225,8 +225,6 @@ void BleScannerIntf::ScanFilterEnable(bool enable) { enable, base::Bind(&BleScannerIntf::OnEnableCallback, base::Unretained(this))); } -#if TARGET_FLOSS - bool BleScannerIntf::IsMsftSupported() { return scanner_intf_->IsMsftSupported(); } void BleScannerIntf::MsftAdvMonitorAdd(const RustMsftAdvMonitor& monitor) { @@ -247,15 +245,6 @@ void BleScannerIntf::MsftAdvMonitorEnable(bool enable) { base::Bind(&BleScannerIntf::OnMsftAdvMonitorEnableCallback, base::Unretained(this))); } -#else - -bool BleScannerIntf::IsMsftSupported() { return false; } -void BleScannerIntf::MsftAdvMonitorAdd(const RustMsftAdvMonitor&) {} -void BleScannerIntf::MsftAdvMonitorRemove(uint8_t) {} -void BleScannerIntf::MsftAdvMonitorEnable(bool) {} - -#endif - void BleScannerIntf::SetScanParameters(uint8_t scanner_id, uint8_t scan_type, uint16_t scan_interval, uint16_t scan_window, uint8_t scan_phy) { @@ -335,7 +324,6 @@ void BleScannerIntf::OnFilterConfigCallback(uint8_t filter_index, uint8_t filt_t rusty::gdscan_filter_config_callback(filter_index, filt_type, avbl_space, action, btm_status); } -#if TARGET_FLOSS void BleScannerIntf::OnMsftAdvMonitorAddCallback(uint8_t monitor_handle, uint8_t status) { rusty::gdscan_msft_adv_monitor_add_callback(monitor_handle, status); } @@ -347,7 +335,6 @@ void BleScannerIntf::OnMsftAdvMonitorRemoveCallback(uint8_t status) { void BleScannerIntf::OnMsftAdvMonitorEnableCallback(uint8_t status) { rusty::gdscan_msft_adv_monitor_enable_callback(status); } -#endif void BleScannerIntf::OnPeriodicSyncStarted(int, uint8_t status, uint16_t sync_handle, uint8_t advertising_sid, uint8_t address_type, diff --git a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h index 318a54ccf4e..0f1ee7dcf6f 100644 --- a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h +++ b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h @@ -160,11 +160,9 @@ private: uint8_t btm_status); void OnFilterConfigCallback(uint8_t filt_index, uint8_t filt_type, uint8_t avbl_space, uint8_t action, uint8_t btm_status); -#if TARGET_FLOSS void OnMsftAdvMonitorAddCallback(uint8_t monitor_handle, uint8_t status); void OnMsftAdvMonitorRemoveCallback(uint8_t status); void OnMsftAdvMonitorEnableCallback(uint8_t status); -#endif BleScannerInterface* scanner_intf_; }; diff --git a/system/include/hardware/ble_scanner.h b/system/include/hardware/ble_scanner.h index 4e42d68fc5f..ebe4654dba2 100644 --- a/system/include/hardware/ble_scanner.h +++ b/system/include/hardware/ble_scanner.h @@ -116,7 +116,6 @@ public: base::Callback; -#if TARGET_FLOSS using MsftAdvMonitorAddCallback = base::Callback; @@ -124,7 +123,6 @@ public: using MsftAdvMonitorEnableCallback = base::Callback; -#endif /** Registers a scanner with the stack */ virtual void RegisterScanner(const bluetooth::Uuid& app_uuid, RegisterCallback) = 0; @@ -149,7 +147,6 @@ public: /** Enable / disable scan filter feature*/ virtual void ScanFilterEnable(bool enable, EnableCallback cb) = 0; -#if TARGET_FLOSS /** Is MSFT Extension supported? */ virtual bool IsMsftSupported() = 0; @@ -161,7 +158,6 @@ public: /** Enable / disable MSFT scan filter feature */ virtual void MsftAdvMonitorEnable(bool enable, MsftAdvMonitorEnableCallback cb) = 0; -#endif /** Sets the LE scan interval and window in units of N*0.625 msec */ virtual void SetScanParameters(int scanner_id, uint8_t scan_type, int scan_interval, diff --git a/system/main/shim/ble_scanner_interface_impl.h b/system/main/shim/ble_scanner_interface_impl.h index 3310381eb7d..53c5f0df94a 100644 --- a/system/main/shim/ble_scanner_interface_impl.h +++ b/system/main/shim/ble_scanner_interface_impl.h @@ -34,7 +34,6 @@ namespace shim { extern ::ScanningCallbacks* default_scanning_callback; -#if TARGET_FLOSS class MsftCallbacks { public: using MsftAdvMonitorAddCallback = @@ -46,7 +45,6 @@ public: MsftAdvMonitorRemoveCallback Remove; MsftAdvMonitorEnableCallback Enable; }; -#endif class BleScannerInterfaceImpl : public ::BleScannerInterface, public bluetooth::hci::ScanningCallback { @@ -66,12 +64,10 @@ public: FilterConfigCallback cb) override; void ScanFilterClear(int filter_index, FilterConfigCallback cb) override; void ScanFilterEnable(bool enable, EnableCallback cb) override; -#if TARGET_FLOSS bool IsMsftSupported() override; void MsftAdvMonitorAdd(MsftAdvMonitor monitor, MsftAdvMonitorAddCallback cb) override; void MsftAdvMonitorRemove(uint8_t monitor_handle, MsftAdvMonitorRemoveCallback cb) override; void MsftAdvMonitorEnable(bool enable, MsftAdvMonitorEnableCallback cb) override; -#endif void SetScanParameters(int scanner_id, uint8_t scan_type, int scan_interval, int scan_window, int scan_phy, Callback cb) override; void BatchscanConfigStorage(int client_if, int batch_scan_full_max, int batch_scan_trunc_max, @@ -124,12 +120,10 @@ public: void OnBigInfoReport(uint16_t sync_handle, bool encrypted) override; ::ScanningCallbacks* scanning_callbacks_ = default_scanning_callback; -#if TARGET_FLOSS void OnMsftAdvMonitorAdd(uint8_t monitor_handle, bluetooth::hci::ErrorCode status); void OnMsftAdvMonitorRemove(bluetooth::hci::ErrorCode status); void OnMsftAdvMonitorEnable(bool enable, bluetooth::hci::ErrorCode status); MsftCallbacks msft_callbacks_; -#endif private: bool parse_filter_command(bluetooth::hci::AdvertisingPacketContentFilterCommand& diff --git a/system/main/shim/entry.cc b/system/main/shim/entry.cc index d09b570745c..a1c61b7ab0b 100644 --- a/system/main/shim/entry.cc +++ b/system/main/shim/entry.cc @@ -24,9 +24,7 @@ #include "hci/hci_layer.h" #include "hci/le_advertising_manager.h" #include "hci/le_scanning_manager.h" -#if TARGET_FLOSS #include "hci/msft.h" -#endif #include "hci/remote_name_request.h" #include "main/shim/stack.h" #include "metrics/counter_metrics.h" @@ -81,11 +79,9 @@ metrics::CounterMetrics* GetCounterMetrics() { return Stack::GetInstance()->GetStackManager()->GetInstance(); } -#if TARGET_FLOSS hci::MsftExtensionManager* GetMsftExtensionManager() { return Stack::GetInstance()->GetStackManager()->GetInstance(); } -#endif } // namespace shim } // namespace bluetooth diff --git a/system/main/shim/entry.h b/system/main/shim/entry.h index ff23bfb1cdd..e50cbc4d910 100644 --- a/system/main/shim/entry.h +++ b/system/main/shim/entry.h @@ -45,9 +45,7 @@ class RemoteNameRequestModule; class DistanceMeasurementManager; class LeAdvertisingManager; class LeScanningManager; -#if TARGET_FLOSS class MsftExtensionManager; -#endif } // namespace hci namespace metrics { @@ -75,9 +73,7 @@ hal::SnoopLogger* GetSnoopLogger(); storage::StorageModule* GetStorage(); hci::AclManager* GetAclManager(); metrics::CounterMetrics* GetCounterMetrics(); -#if TARGET_FLOSS hci::MsftExtensionManager* GetMsftExtensionManager(); -#endif } // namespace shim } // namespace bluetooth diff --git a/system/main/shim/le_scanning_manager.cc b/system/main/shim/le_scanning_manager.cc index 09c82fca0ab..beaa585d16f 100644 --- a/system/main/shim/le_scanning_manager.cc +++ b/system/main/shim/le_scanning_manager.cc @@ -26,9 +26,7 @@ #include "btif/include/btif_common.h" #include "hci/address.h" #include "hci/le_scanning_manager.h" -#if TARGET_FLOSS #include "hci/msft.h" -#endif #include "include/hardware/ble_scanner.h" #include "main/shim/ble_scanner_interface_impl.h" #include "main/shim/entry.h" @@ -133,11 +131,9 @@ void BleScannerInterfaceImpl::Init() { log::info("init BleScannerInterfaceImpl"); bluetooth::shim::GetScanning()->RegisterScanningCallback(this); -#if TARGET_FLOSS if (bluetooth::shim::GetMsftExtensionManager()) { bluetooth::shim::GetMsftExtensionManager()->SetScanningCallback(this); } -#endif } /** Registers a scanner with the stack */ @@ -251,7 +247,6 @@ void BleScannerInterfaceImpl::ScanFilterEnable(bool enable, EnableCallback cb) { do_in_jni_thread(base::BindOnce(cb, action, btm_status_value(tBTM_STATUS::BTM_SUCCESS))); } -#if TARGET_FLOSS /** Is MSFT Extension supported? */ bool BleScannerInterfaceImpl::IsMsftSupported() { log::info("in shim layer"); @@ -314,7 +309,6 @@ void BleScannerInterfaceImpl::OnMsftAdvMonitorEnable(bool enable, msft_callbacks_.Enable.Run((uint8_t)status); } -#endif /** Sets the LE scan interval and window in units of N*0.625 msec */ void BleScannerInterfaceImpl::SetScanParameters(int scanner_id, uint8_t scan_type, diff --git a/system/main/shim/stack.cc b/system/main/shim/stack.cc index d66e2d4afa7..73526bc4dd5 100644 --- a/system/main/shim/stack.cc +++ b/system/main/shim/stack.cc @@ -34,9 +34,7 @@ #include "hci/hci_layer.h" #include "hci/le_advertising_manager.h" #include "hci/le_scanning_manager.h" -#if TARGET_FLOSS #include "hci/msft.h" -#endif #include "hci/remote_name_request.h" #include "main/shim/acl.h" #include "main/shim/acl_interface.h" @@ -88,9 +86,7 @@ void Stack::StartEverything() { modules.add(); modules.add(); modules.add(); -#if TARGET_FLOSS modules.add(); -#endif modules.add(); modules.add(); Start(&modules); diff --git a/system/test/mock/mock_main_shim_entry.cc b/system/test/mock/mock_main_shim_entry.cc index ac45931b643..72054dad81b 100644 --- a/system/test/mock/mock_main_shim_entry.cc +++ b/system/test/mock/mock_main_shim_entry.cc @@ -57,9 +57,7 @@ os::Handler* GetGdShimHandler() { return hci::testing::mock_gd_shim_handler_; } hal::SnoopLogger* GetSnoopLogger() { return nullptr; } storage::StorageModule* GetStorage() { return nullptr; } metrics::CounterMetrics* GetCounterMetrics() { return nullptr; } -#if TARGET_FLOSS hci::MsftExtensionManager* GetMsftExtensionManager() { return nullptr; } -#endif hci::RemoteNameRequestModule* GetRemoteNameRequest() { return nullptr; } } // namespace shim -- GitLab From a7e1ae52f693ed0e235865124aa5f699108cde69 Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Mon, 7 Oct 2024 18:31:41 +0000 Subject: [PATCH 179/875] PandoraServer: Implement L2cap#disconnect Bug: 371563204 Test: atest pts-bot Change-Id: I259149f3fccfa5d5af4fcd97f15a1d00e6236529 --- android/pandora/server/src/L2cap.kt | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/android/pandora/server/src/L2cap.kt b/android/pandora/server/src/L2cap.kt index 1d1e9c8a211..0ee9cbf6820 100644 --- a/android/pandora/server/src/L2cap.kt +++ b/android/pandora/server/src/L2cap.kt @@ -25,6 +25,7 @@ import com.google.protobuf.Any import com.google.protobuf.ByteString import io.grpc.stub.StreamObserver import java.io.Closeable +import java.io.IOException import java.util.concurrent.atomic.AtomicLong import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -128,6 +129,30 @@ class L2cap(val context: Context) : L2CAPImplBase(), Closeable { } } + override fun disconnect( + request: DisconnectRequest, + responseObserver: StreamObserver, + ) { + grpcUnary(scope, responseObserver) { + val channel = request.channel + val bluetoothSocket = channel.toBluetoothSocket(channels) + Log.i(TAG, "disconnect: ${channel.id()} ") + + try { + bluetoothSocket.close() + DisconnectResponse.getDefaultInstance() + } catch (e: IOException) { + Log.e(TAG, "disconnect: exception while closing the socket: $e") + + DisconnectResponse.newBuilder() + .setErrorValue(CommandRejectReason.COMMAND_NOT_UNDERSTOOD_VALUE) + .build() + } finally { + channels.remove(channel.id()) + } + } + } + override fun send(request: SendRequest, responseObserver: StreamObserver) { grpcUnary(scope, responseObserver) { Log.i(TAG, "send") @@ -167,6 +192,8 @@ class L2cap(val context: Context) : L2CAPImplBase(), Closeable { return channel } + fun Channel.id(): Long = this.cookie.value.toStringUtf8().toLong() + fun Channel.toBluetoothSocket(channels: HashMap): BluetoothSocket = - channels.get(this.cookie.value.toStringUtf8().toLong())!! + channels.get(this.id())!! } -- GitLab From c84965b43bf3ae4ce08d3519f7d51fe22047f094 Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Mon, 7 Oct 2024 20:33:23 +0000 Subject: [PATCH 180/875] PandoraServer: Implement L2cap#WaitDisconnection Bug: 371562950 Test: atest pts-bot Change-Id: I027632581637164d83676764f27cbc2a0179066b --- android/pandora/server/src/L2cap.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/android/pandora/server/src/L2cap.kt b/android/pandora/server/src/L2cap.kt index 0ee9cbf6820..d54cb3bec0e 100644 --- a/android/pandora/server/src/L2cap.kt +++ b/android/pandora/server/src/L2cap.kt @@ -153,6 +153,20 @@ class L2cap(val context: Context) : L2CAPImplBase(), Closeable { } } + override fun waitDisconnection( + request: WaitDisconnectionRequest, + responseObserver: StreamObserver, + ) { + grpcUnary(scope, responseObserver) { + Log.i(TAG, "waitDisconnection: ${request.channel.id()}") + val bluetoothSocket = request.channel.toBluetoothSocket(channels) + + while (bluetoothSocket.isConnected()) Thread.sleep(100) + + WaitDisconnectionResponse.getDefaultInstance() + } + } + override fun send(request: SendRequest, responseObserver: StreamObserver) { grpcUnary(scope, responseObserver) { Log.i(TAG, "send") -- GitLab From fe9a28c65a5a2b2ce4d910896e2a22d467fea2b0 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 7 Oct 2024 18:58:00 +0000 Subject: [PATCH 181/875] Initialize ras only if the controller support channel soudning. Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 372010287 Test: m com.android.btservices Change-Id: Ib3e60495737c0c33073c106b2afc02b73a36d245 --- system/bta/ras/ras_client.cc | 7 +++++++ system/bta/ras/ras_server.cc | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/system/bta/ras/ras_client.cc b/system/bta/ras/ras_client.cc index b007c71ff43..a2d3ab84785 100644 --- a/system/bta/ras/ras_client.cc +++ b/system/bta/ras/ras_client.cc @@ -20,6 +20,8 @@ #include "bta/include/bta_gatt_api.h" #include "bta/include/bta_ras_api.h" #include "bta/ras/ras_types.h" +#include "gd/hci/controller_interface.h" +#include "main/shim/entry.h" #include "os/logging/log_adapter.h" #include "stack/include/bt_types.h" #include "stack/include/btm_ble_addr.h" @@ -100,6 +102,11 @@ public: }; void Initialize() override { + auto controller = bluetooth::shim::GetController(); + if (controller && !controller->SupportsBleChannelSounding()) { + log::info("controller does not support channel sounding."); + return; + } BTA_GATTC_AppRegister( [](tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { if (instance && p_data) { diff --git a/system/bta/ras/ras_server.cc b/system/bta/ras/ras_server.cc index e6720a440c4..a676deb6c44 100644 --- a/system/bta/ras/ras_server.cc +++ b/system/bta/ras/ras_server.cc @@ -23,8 +23,10 @@ #include "bta/include/bta_gatt_api.h" #include "bta/include/bta_ras_api.h" #include "bta/ras/ras_types.h" +#include "gd/hci/controller_interface.h" #include "gd/hci/uuid.h" #include "gd/os/rand.h" +#include "main/shim/entry.h" #include "os/logging/log_adapter.h" #include "stack/include/bt_types.h" #include "stack/include/btm_ble_addr.h" @@ -74,11 +76,15 @@ public: uint16_t last_overwritten_procedure_ = 0; }; - void Initialize() { + void Initialize() override { + auto controller = bluetooth::shim::GetController(); + if (controller && !controller->SupportsBleChannelSounding()) { + log::info("controller does not support channel sounding."); + return; + } Uuid uuid = Uuid::From128BitBE(bluetooth::os::GenerateRandom()); app_uuid_ = uuid; log::info("Register server with uuid:{}", app_uuid_.ToString()); - BTA_GATTS_AppRegister( app_uuid_, [](tBTA_GATTS_EVT event, tBTA_GATTS* p_data) { -- GitLab From bafbd7187a57c71c319a1344ece791ef1b47c5f7 Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Thu, 12 Sep 2024 20:41:36 +0000 Subject: [PATCH 182/875] Fix crash in l2cap-fuzzer l2cap-fuzzer initializes itself via L2CA_RegisterWithSecurity, which calls through into BTM_SetSecurityLevel. For the client interface defined for these fuzzers, BTM_SetSecurityLevel is nullptr, which leads to a crash on startup. Add a mock for this in the default client interface. Bug: 326853665 Test: m libbluetooth Test: l2cap-fuzzer Flag: EXEMPT test_only Change-Id: I282db97b683efb1ba2596d4fad0070215f4cb62c --- system/test/mock/mock_stack_btm_interface.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/system/test/mock/mock_stack_btm_interface.cc b/system/test/mock/mock_stack_btm_interface.cc index 7016d4b6622..116d2008af4 100644 --- a/system/test/mock/mock_stack_btm_interface.cc +++ b/system/test/mock/mock_stack_btm_interface.cc @@ -142,6 +142,10 @@ struct btm_client_interface_t default_btm_client_interface = { }, .BTM_IsLinkKeyKnown = [](const RawAddress& /* bd_addr */, tBT_TRANSPORT /* transport */) -> bool { return false; }, + .BTM_SetSecurityLevel = [](bool /* is_originator */, const char* /*p_name */, + uint8_t /* service_id */, uint16_t /* sec_level */, + uint16_t /* psm */, uint32_t /* mx_proto_id */, + uint32_t /* mx_chan_id */) -> bool { return false; }, .BTM_SecClrService = [](uint8_t /* service_id */) -> uint8_t { return 0; }, .BTM_SecClrServiceByPsm = [](uint16_t /* psm */) -> uint8_t { return 0; }, .BTM_SecBond = [](const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */, @@ -150,7 +154,6 @@ struct btm_client_interface_t default_btm_client_interface = { .BTM_SecBondCancel = [](const RawAddress& /* bd_addr */) -> tBTM_STATUS { return tBTM_STATUS::BTM_SUCCESS; }, - .BTM_RemoteOobDataReply = [](tBTM_STATUS /* res */, const RawAddress& /* bd_addr */, const Octet16& /* c */, const Octet16& /* r */) {}, .BTM_PINCodeReply = [](const RawAddress& /* bd_addr */, tBTM_STATUS /* res */, -- GitLab From 585fecf2aebf1d583f1f8d785bb486b702491e78 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 7 Oct 2024 13:22:45 -0700 Subject: [PATCH 183/875] GetName/SetName: Broadcast intent from server Since the server is responsible for having an up to date name, it make sense for it to be the source of the associated intent. Bug: 371656429 Bug: 368114370 Flag: com.android.bluetooth.flags.get_name_and_address_as_callback Test: atest CtsBluetoothTestCases:BluetoothAdapterTest#setName_getName Change-Id: I8cfe2d73d160db86c20bbb4296e004e555671cb1 --- .../android/bluetooth/btservice/AdapterProperties.java | 1 + .../android/server/bluetooth/BluetoothManagerService.java | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index 448c9aa8550..728bad66cf3 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -977,6 +977,7 @@ class AdapterProperties { mName = name; if (Flags.getNameAndAddressAsCallback()) { mService.updateAdapterName(mName); + break; } intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName); diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 6c0f74c635f..b59ab9de452 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -16,6 +16,7 @@ package com.android.server.bluetooth; +import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.bluetooth.BluetoothAdapter.STATE_BLE_ON; import static android.bluetooth.BluetoothAdapter.STATE_BLE_TURNING_OFF; import static android.bluetooth.BluetoothAdapter.STATE_BLE_TURNING_ON; @@ -254,6 +255,13 @@ class BluetoothManagerService { } mName = name; Log.v(TAG, "storeName(" + mName + "): Success"); + mContext.sendBroadcastAsUser( + new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED) + .putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, name) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT), + UserHandle.ALL, + BLUETOOTH_CONNECT, + getTempAllowlistBroadcastOptions()); } private void storeAddress(String address) { -- GitLab From 55e3304a4e2534c3106484f67d947191fd02d0d8 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Mon, 7 Oct 2024 22:39:53 +0000 Subject: [PATCH 184/875] [le audio] Get Broadcast quality based on selected output codec config Get Broadcast Audio Quality based on selected output codec config instead of input codec config for connected sink devices. Bug: 370236114 Flag: EXEMPT; trivial fix covered by unit tests Test: atest LeAudioBroadcastServiceTest Test: manual testing with specific remote devices Change-Id: Ibb9578e89e04eabc698b4fed947464153daa7958 --- .../bluetooth/le_audio/LeAudioService.java | 2 +- .../le_audio/LeAudioBroadcastServiceTest.java | 49 +++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) 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 1f7e07e3173..a6cd25b3959 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -1239,7 +1239,7 @@ public class LeAudioService extends ProfileService { BluetoothLeAudioCodecStatus codecStatus = getCodecStatus(groupId); if (codecStatus != null - && !codecStatus.isInputCodecConfigSelectable(BROADCAST_HIGH_QUALITY_CONFIG)) { + && !codecStatus.isOutputCodecConfigSelectable(BROADCAST_HIGH_QUALITY_CONFIG)) { // If any sink device does not support high quality audio config, // set all subgroup audio quality to standard quality for now before multi codec // config support is ready diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 10909db22d9..613fe815fe8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -534,7 +534,7 @@ public class LeAudioBroadcastServiceTest { } @Test - public void testCreateBroadcast_updateQualityToStandard() { + public void testCreateBroadcast_noAudioQualityUpdate() { byte[] code = {0x00, 0x01, 0x00, 0x02}; int groupId = 1; @@ -551,9 +551,52 @@ public class LeAudioBroadcastServiceTest { BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1); when(mBassClientService.getConnectedDevices()).thenReturn(List.of(mDevice)); - // update selectable configs to be STANDARD quality + // update input selectable configs to be STANDARD quality + // keep output selectable configs as HIGH quality injectGroupSelectableCodecConfigChanged( - groupId, INPUT_SELECTABLE_CONFIG_STANDARD, OUTPUT_SELECTABLE_CONFIG_STANDARD); + groupId, INPUT_SELECTABLE_CONFIG_STANDARD, OUTPUT_SELECTABLE_CONFIG_HIGH); + injectGroupCurrentCodecConfigChanged(groupId, LC3_16KHZ_CONFIG, LC3_48KHZ_CONFIG); + + mService.createBroadcast(settings); + + // Test data with only one subgroup + // Verify quality is not updated to standard because HIGH is selectable in output + int[] expectedQualityArray = {BluetoothLeBroadcastSubgroupSettings.QUALITY_HIGH}; + byte[][] expectedDataArray = { + settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata() + }; + + verify(mLeAudioBroadcasterNativeInterface, times(1)) + .createBroadcast( + eq(true), + eq(TEST_BROADCAST_NAME), + eq(code), + eq(settings.getPublicBroadcastMetadata().getRawMetadata()), + eq(expectedQualityArray), + eq(expectedDataArray)); + } + + @Test + public void testCreateBroadcast_updateAudioQualityToStandard() { + byte[] code = {0x00, 0x01, 0x00, 0x02}; + int groupId = 1; + + initializeNative(); + prepareConnectedUnicastDevice(groupId, mDevice); + + synchronized (mService.mBroadcastCallbacks) { + mService.mBroadcastCallbacks.register(mCallbacks); + } + + BluetoothLeAudioContentMetadata.Builder meta_builder = + new BluetoothLeAudioContentMetadata.Builder(); + BluetoothLeAudioContentMetadata meta = meta_builder.build(); + BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1); + + when(mBassClientService.getConnectedDevices()).thenReturn(List.of(mDevice)); + // update output selectable configs to be STANDARD quality + injectGroupSelectableCodecConfigChanged( + groupId, INPUT_SELECTABLE_CONFIG_HIGH, OUTPUT_SELECTABLE_CONFIG_STANDARD); injectGroupCurrentCodecConfigChanged(groupId, LC3_16KHZ_CONFIG, LC3_48KHZ_CONFIG); mService.createBroadcast(settings); -- GitLab From 771aed3ea225d9ca2ef91e88f45f330ced952772 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Wed, 2 Oct 2024 03:50:00 +0000 Subject: [PATCH 185/875] Reset permissions for not bonded device According to the PBAP specification, The PSE user shall have to confirm at least the first Phone Book Access Profile connection from each new PCE. According to the MAP specification, The MCE and MSE shall be bonded before setting up a Message Access Profile connection. Let's remove the permissions when the device is unbonded. Flag: EXEMPT, security fix Bug: 289375038 Bug: 289811388 Test: atest BluetoothInstrumentationTests Ignore-AOSP-First: security fix Change-Id: I94478a4a45a434732d4bc4810da31ef45ef891af --- .../com/android/bluetooth/btservice/AdapterService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 19c8aee207c..3937a8e8811 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -27,6 +27,7 @@ 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.BluetoothDevice.BATTERY_LEVEL_UNKNOWN; +import static android.bluetooth.BluetoothDevice.BOND_NONE; import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO; import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -6121,6 +6122,13 @@ public class AdapterService extends Service { mCsipSetCoordinatorService.handleBondStateChanged(device, fromState, toState); } mDatabaseManager.handleBondStateChanged(device, fromState, toState); + + if (toState == BOND_NONE) { + // Remove the permissions for unbonded devices + setMessageAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); + setPhonebookAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); + setSimAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); + } } static int convertScanModeToHal(int mode) { -- GitLab From ffd365e6c683fd9a8bbbfaebba6bc91c24396a67 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 7 Oct 2024 21:35:47 -0700 Subject: [PATCH 186/875] Update lint-baseline with current failures Bug: 289445022 Test: m Bluetooth Flag: Exempt lint only Change-Id: I81d8c5cba2a34b21e5d484b7d653d6d1441bf287 --- android/app/lint-baseline.xml | 20241 ++++++++++++++++++++++++++------ 1 file changed, 16963 insertions(+), 3278 deletions(-) diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml index d4fdf373939..ce57d4d93e6 100644 --- a/android/app/lint-baseline.xml +++ b/android/app/lint-baseline.xml @@ -1,7130 +1,20815 @@ - + + message="If intercepting back events, this should be handled through the registration of callbacks on the window level; Please see https://developer.android.com/about/versions/13/features/predictive-back-gesture" + errorLine1=" if (keyCode == KeyEvent.KEYCODE_BACK) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="101" + column="24"/> + message="If intercepting back events, this should be handled through the registration of callbacks on the window level; Please see https://developer.android.com/about/versions/13/features/predictive-back-gesture" + errorLine1=" if (keyCode == KeyEvent.KEYCODE_BACK) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="178" + column="24"/> + message="This LinearLayout should use `android:layout_height="wrap_content"`" + errorLine1=" android:layout_height="match_parent"" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="26" + column="5"/> + message="This LinearLayout should use `android:layout_height="wrap_content"`" + errorLine1=" android:layout_height="match_parent"" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="28" + column="9"/> + message="This LinearLayout should use `android:layout_height="wrap_content"`" + errorLine1=" android:layout_height="match_parent"" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="26" + column="9"/> + message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" + errorLine1=" String.format(" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java" + line="455" + column="25"/> + message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" + errorLine1=" offsetString = String.format("%1$02d", -(offset));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java" + line="403" + column="32"/> + message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" + errorLine1=" offsetString = String.format("%1$02d", offset);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java" + line="407" + column="32"/> + message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" + errorLine1=" return String.format(" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java" + line="911" + column="20"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"ብሉቱዝ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"بلوتوث"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"ব্লুটুথ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"ব্লুটুথ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎Bluetooth‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-es/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetootha"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-eu/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"بلوتوث"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"બ્લૂટૂથ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"ब्लूटूथ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-hi/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-hu/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values-in/strings.xml" + line="19" + column="13" + message="Previously defined here"/> + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="4" + column="13"/> + + id="DuplicateDefinition" + message="`app_name` has already been defined in this folder" + errorLine1=" <string name="app_name" msgid="7766152617107310582">"Bluetooth"</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirm record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎Confirm record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Kinnita kirje"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Berretsi erregistroa"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"تأیید سابقه"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Vahvista tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmar rexistro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"રેકોર્ડની પુષ્ટિ કરો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"रिकॉर्ड की पुष्टि करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Potvrdi zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Rekord megerősítése"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Հաստատել գրառումը"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Konfirmasi catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Staðfesta færslu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Conferma record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"אישור רשומה"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"レコードを確認"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"ჩანაწერის დადასტურება"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Жазбаны растау"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"បញ្ជាក់​កំណត់ត្រា"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"ರೆಕಾರ್ಡ್‌ ಅನ್ನು ಖಚಿತಪಡಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"기록 확인"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Жазууну ырастоо"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"ຢືນຢັນການບັນທຶກ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Patvirtinti įrašą"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Ieraksta apstiprinājums"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Потврди запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"റെക്കോർഡ് സ്ഥിരീകരിക്കുക"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Бичлэгийг баталгаажуулах"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"रेकॉर्डची पुष्टी करा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Sahkan rekod"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"မှတ်တမ်းအတည်ပြုရန်"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Bekreft oppføring"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"रेकर्ड निश्चित गर्नुहोस्"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Record bevestigen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"ରେକର୍ଡ ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"ਰਿਕਾਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Potwierdź rekord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmar registo"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmar registro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Confirmă înregistrarea"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Подтвердить запись"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"වාර්තාව සහතික කරන්න"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-si/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Potvrdiť záznam"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sk/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Potrdi zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sl/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Konfirmo të dhënat"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sq/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Потврди запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Bekräfta post"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sv/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Thibitisha rekodi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sw/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"பதிவை உறுதிப்படுத்து"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"రికార్డ్‌ను నిర్ధారించండి"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-te/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"ยืนยันบันทึก"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-th/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Kumpirmahin ang tala"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tl/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Kaydı onayla"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Підтвердити запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uk/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"ریکارڈ کی توثیق کریں"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Yozuvni tasdiqlash"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Xác nhận bản ghi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"确认记录"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"確認記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"確認記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""update_record" is translated here but not found in default locale" + errorLine1=" <string name="update_record" msgid="7201772850942641237">"Qinisekisa irekhodi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="6" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack-rekord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack መዝገብ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"‏سجل Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"স্বীকৃত কৰা ৰেকৰ্ড"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack qeydəalma"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Запіс"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Запис на Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack রেকর্ড"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Evidencija Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Registre de notificacions"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Záznam ACK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack-post"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Aufnahme bestätigen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Αρχείο ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎Ack record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Confirmación de la grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Confirmar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Acki kirje"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ACK erregistroa"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"‏سابقه Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Hyv. tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Enregistrement accusé de réception"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Enregistrement accusé de réception"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Rexistro Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack રેકોર્ડ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"रिकॉर्ड अभिस्वीकृत करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ACK rekord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ACK գրառում"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Akui catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack-færsla"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Record ACK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"אישור רשומה"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ackレコード"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack ჩანაწერი"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Жазбаны тану"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"កំណត់ត្រា​ការ​ទទួល​ស្គាល់"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack ರೆಕಾರ್ಡ್‌ ಮಾಡಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"기록 인식"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ບັນທຶກ Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Įrašas apie patvirtinimą"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack ieraksts"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack റെക്കോർഡ്"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack бичлэг"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack रेकॉर्ड"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Rekod Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"အသိအမှတ်ပြု မှတ်တမ်း"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack-oppføring"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack रेकर्ड"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ACK-record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ରେକର୍ଡ ସ୍ୱୀକୃତ କରନ୍ତୁ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack ਰਿਕਾਰਡ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Rekord Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Registo de confirmação"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Confirmar registro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Înregistrare Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Запись подтверждения"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack වාර්තාව"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-si/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Záznam ACK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sk/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Zapis potrditve"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sl/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Të dhënat \"Ack\""</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sq/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Bekräftelsepost"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sv/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Rekodi ya Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sw/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ஒப்புதல் பதிவு"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"సమ్మతి ధృవీకరణ రికార్డ్"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-te/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"บันทึก Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-th/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack na tala"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tl/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Onay kaydı"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Запис TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uk/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"‏Ack ریکارڈ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack yozuvi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Bản ghi Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack记录"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack 記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack 記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Irekhodi ye-Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="7" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Vee alle rekords uit"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ሁሉንም መዝገብ ሰርዝ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"حذف السجل كله"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"আটাইবোৰ ৰেকৰ্ড মচক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Bütün qeydləri silin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Izbriši sve zapise"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Выдаліць усе запісы"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Изтриване на всички записи"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"সব রেকর্ড মুছে দিন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Izbriši svu evidenciju"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Suprimeix tots els registres"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Smazat všechny záznamy"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Slet alle poster"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Gesamte Aufnahme löschen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Διαγραφή όλων των αρχείων"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‎Delete all record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eliminar todas las grabaciones"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eliminar todas las grabaciones"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Kustuta kõik kirjed"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Ezabatu erregistro guztiak"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"حذف همه سابقه"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Poista kaikki tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Supprimer tout l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Supprimer tout l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eliminar todos os rexistros"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"તમામ રેકોર્ડ કાઢી નાખો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"सभी रिकॉर्ड मिटाएं"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Izbriši sve zapise"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Minden rekord törlése"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Ջնջել բոլոր գրառումները"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Hapus semua catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eyða öllum færslum"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Elimina tutti i record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"מחיקת כל הרשומות"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"レコードをすべて削除"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ყველა ჩანაწერის წაშლა"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Барлық жазбаларды жою"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"លុប​កំណត់​ត្រា​ទាំងអស់"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ಎಲ್ಲ ರೆಕಾರ್ಡ್‌ ಅನ್ನು ಅಳಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"모든 기록 삭제"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Бардык жазууларды жок кылуу"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ລຶບບັນທຶກທັງໝົດ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Ištrinti visus įrašus"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Dzēst visus ierakstus"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Избриши ги сите записи"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"എല്ലാ റെക്കോർഡും ഇല്ലാതാക്കുക"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Бүх бичлэгийг устгах"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"सर्व रेकॉर्ड हटवा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Padamkan semua rekod"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"မှတ်တမ်းအားလုံးကို ဖျက်ရန်"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Slett hele oppføringen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"सबै रेकर्ड मेटाउनुहोस्"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Alle records verwijderen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ସମସ୍ତ ରେକର୍ଡ ଡିଲିଟ୍‌ କରନ୍ତୁ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ਸਾਰੇ ਰਿਕਾਰਡ ਮਿਟਾਓ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Usuń wszystkie rekordy"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eliminar todo o registo"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Excluir todos os registros"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Șterge toate înregistrările"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Удалить все записи"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"සියලු වාර්තා මකන්න"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-si/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Odstrániť všetky záznamy"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sk/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Izbriši ves zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sl/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Fshiji të gjitha të dhënat"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sq/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Избриши све записе"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Ta bort alla poster"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sv/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Futa rekodi zote"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sw/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"எல்லா பதிவையும் நீக்கு"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"మొత్తం రికార్డ్‌ను తొలగించండి"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-te/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ลบบันทึกทั้งหมด"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-th/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"I-delete ang lahat ng tala"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tl/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Tüm kayıtları silin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Видалити всі записи"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uk/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"سبھی ریکارڈ حذف کریں"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Barcha yozuvlarni o‘chirish"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Xóa tất cả bản ghi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"删除所有记录"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"刪除所有記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"刪除所有記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Susa yonke irekhodi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="8" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"እሺ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"حسنًا"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ঠিক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Potvrdi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ОК"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ঠিক আছে"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Uredu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"D\'acord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Ok"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ΟΚ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎OK‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Aceptar"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Aceptar"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Ados"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"تأیید"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Aceptar"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ઓકે"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ठीक है"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"U redu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Եղավ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Oke"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Í lagi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"אישור"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"კარგი"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Жарайды"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"យល់​ព្រម​"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ಸರಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"확인"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ຕົກລົງ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Gerai"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Labi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Во ред"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ശരി"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ठीक"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ठिक छ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ଠିକ ଅଛି"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ਠੀਕ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ОК"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"හරි"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-si/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sk/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"V redu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sl/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Në rregull"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sq/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Потврди"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sv/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Sawa"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sw/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"சரி"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"సరే"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-te/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ตกลง"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-th/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tl/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Tamam"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uk/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ٹھیک ہے"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"确定"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"確定"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"確定"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"KULUNGILE"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="9" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Vee rekord uit"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"መዝገብ ሰርዝ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"حذف السجل"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ৰেকৰ্ড মচক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Qeydi silin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Izbriši zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Выдаліць запіс"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Изтриване на записа"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"রেকর্ড মুছে দিন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Izbriši evidenciju"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Suprimeix el registre"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Smazat záznam"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Slet post"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Aufnahme löschen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Διαγραφή αρχείου"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎Delete record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eliminar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eliminar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Kustuta kirje"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Ezabatu erregistroa"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"حذف سابقه"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Poista tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Supprimer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Supprimer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eliminar rexistro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"રેકોર્ડ કાઢી નાખો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"रिकॉर्ड मिटाएं"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Izbriši zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Rekord törlése"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Ջնջել գրառումը"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Hapus catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eyða færslu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Elimina record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"מחיקת רשומה"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"レコードを削除"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ჩანაწერის წაშლა"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Жазбаны жою"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"លុប​កំណត់​ត្រា"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ರೆಕಾರ್ಡ್‌ ಅಳಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"기록 삭제"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Жазууну жок кылуу"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ລຶບການບັນທຶກ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Ištrinti įrašą"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Dzēst ierakstu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Избриши запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"റെക്കോർഡ് ഇല്ലാതാക്കുക"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Бичлэгийг устгах"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"रेकॉर्ड हटवा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Padamkan rekod"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"မှတ်တမ်းကို ဖျက်ရန်"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Slett oppføring"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"रेकर्ड मेटाउनुहोस्"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Record verwijderen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ରେକର୍ଡ ଡିଲିଟ୍‌ କରନ୍ତୁ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ਰਿਕਾਰਡ ਮਿਟਾਓ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Usuń rekord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eliminar registo"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Excluir registro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Șterge înregistrarea"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Удалить запись"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"වාර්තාව මකන්න"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-si/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Odstrániť záznam"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sk/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Izbriši zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sl/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Fshi të dhënat"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sq/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Избриши запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Ta bort post"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sv/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Futa rekodi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sw/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"பதிவை நீக்கு"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"రికార్డ్‌ను తొలగించండి"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-te/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ลบบันทึก"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-th/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"I-delete ang tala"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tl/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Kaydı sil"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Видалити запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uk/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ریکارڈ حذف کریں"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Yozuvni o‘chirish"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Xóa bản ghi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"删除记录"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"刪除記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"刪除記錄"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Susa irekhodi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="10" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Begin TCP-bediener"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP አገልጋይን ጀምር"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‏بدء الخادم TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP ছাৰ্ভাৰ আৰম্ভ কৰক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP serverinə başlayın"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Pokreni TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Запусціць сервер TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Стартиране на TCP сървър"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP সার্ভার শুরু করুন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Pokreni TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Inicia el servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Spustit server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP-Server starten"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Εκκίνηση διακομιστή TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎Start TCP server‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar el servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Käivita TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Hasi TCP zerbitzaria"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‏راه‌اندازی سرور TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Käynnistä TCP-palvelin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Démarrer le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Démarrer le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP સર્વર પ્રારંભ કરો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP सर्वर शरू करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Pokreni TCP poslužitelj"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP-szerver indítása"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Մեկնարկել TCP սերվերը"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Mulai server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Ræsa TCP-þjón"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Avvia server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‏הפעלת שרת TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCPサーバーを起動"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP სერვერის დაწყება"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP серверін бастау"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"ចាប់ផ្ដើម​​ម៉ាស៊ីន​មេ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP ಸರ್ವರ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP 서버 시작"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP серверин баштоо"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"ເລີ່ມ TCP ເຊີບເວີ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Paleisti TCP serverį"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Palaist TCP serveri"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Започни TCP сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP സെർവർ ആരംഭിക്കുക"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP серверийг эхлүүлэх"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP सर्व्‍हर सुरू करा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Mulakan pelayan TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP ဆာဗာ စတင်ရန်"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TPC-tjener"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP सर्भर सुरु गर्नुहोस्"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP-server starten"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP ସର୍ଭର୍‌ ଆରମ୍ଭ କରନ୍ତୁ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP ਸਰਵਰ ਚਾਲੂ ਕਰੋ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Uruchom serwer TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Pornește serverul TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Запустить TCP-сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP සේවාදායකය ආරම්භ කරන්න"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-si/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Spustiť server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sk/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Zaženi strežnik TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sl/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Nis serverin TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sq/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Покрени TCP сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Starta TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sv/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Anzisha seva ya TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sw/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP சேவையகத்தைத் தொடங்கு"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP సర్వర్‌ను ప్రారంభించండి"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-te/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"เริ่มต้นเซิร์ฟเวอร์ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-th/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Simulan ang TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tl/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP sunucusunu başlat"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Запустити TCP сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uk/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‏TCP سرور شروع کریں"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP serverni ishga tushirish"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Khởi động máy chủ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"启动TCP服务器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"啟動 TCP 伺服器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"啟動 TCP 伺服器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Qala iseva ye-TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="11" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Stel TCP-bediener in kennis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP አገልጋይን አሳውቅ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‏إعلام الخادم TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP ছাৰ্ভাৰক জাননী দিয়ক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP serverinə bildirin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Obavesti TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Апавясцiць сервер TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Известяване на TCP сървър"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP সার্ভার সূচিত করুন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Obavijesti TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notifica-ho al servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Upozornit server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Meddel TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP-Server benachrichtigen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Να ειδοποιείται ο διακομιστής TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎Notify TCP server‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notificar al servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Informar al servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Teavita TCP-serverit"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Jakinarazi TCP zerbitzariari"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‏اعلان سرور TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Ilmoita TCP-palvelin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Avertir le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Avertir le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notificar ao servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP સર્વરને સૂચિત કરો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP सर्वर को सूचित करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Obavijesti TCP poslužitelj"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP-szerver értesítése"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Ծանուցել TCP սերվերին"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Beri tahu server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Tilkynna TCP-þjóni"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Invia notifica al server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‏שליחת התראה לשרת TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCPサーバーに通知"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP სერვერის შეტყობინება"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP (жібреуі басқару протоколы) серверін ескерту"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"ជូន​ដំណឹង​ម៉ាស៊ីន​មេ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP ಸರ್ವರ್ ಅನ್ನು ಸೂಚಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP 서버 알림"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP серверин маалымдоо"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"ແຈ້ງເຕືອນ TCP ເຊີບເວີ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Pranešti TCP serveriui"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Paziņot TCP serverim"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Извести TCP сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP സെർവറിനെ അറിയിക്കുക"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP серверт мэдэгдэх"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP सर्व्‍हरला सूचित करा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Beritahu pelayan TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP ဆာဗာကို အကြောင်းကြားရန်"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Varsle TCP-tjener"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP सर्भर सूचित गर्नुहोस्"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Melden aan TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP ସର୍ଭର୍‌କୁ ସୂଚିତ କରନ୍ତୁ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP ਸਰਵਰ ਨੂੰ ਸੂਚਿਤ ਕਰੋ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Powiadom serwer TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notificar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notificar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notifică serverul TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Уведомить TCP-сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP සේවාදායකයට දැනුම් දෙන්න"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-si/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Upozorniť server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sk/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Obvesti strežnik TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sl/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Njofto serverin TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sq/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Обавести TCP сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Avisera TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sv/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Arifu seva ya TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sw/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP சேவையகத்தைத் தெரிவி"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP సర్వర్‌కు తెలియజేయండి"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-te/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"แจ้งเตือนเซิร์ฟเวอร์ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-th/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"I-notify ang TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tl/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP sunucusuna bildir"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Повідом. TCP сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uk/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‏TCP سرور کی اطلاع دیں"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP serverga xabar berish"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Thông báo cho máy chủ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"通知TCP服务器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"通知 TCP 伺服器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"通知 TCP 伺服器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="12" + column="13"/> + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Yazisa iseva ye-TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="12" + column="13"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% ተጠናቋል።"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"اكتمل بنسبة 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"১০০% সম্পূৰ্ণ হ’ল"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Dovršeno je 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Завершана 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% завършено"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"১০০% সম্পূর্ণ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Dovršeno 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Dokončeno 100 %"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Ολοκληρώθηκε το 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Completado el 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% کامل شد"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% પૂર્ણ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% पूरा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% ավարտուն"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"‏הושלם ב-‎100%‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100%完了"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"დასრულდა 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% аяқталды"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"​បញ្ចប់ 100​%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% ಪೂರ್ಣವಾಗಿದೆ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% 완료"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% бүттү"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100​% ສໍາ​ເລັດແລ້ວ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% завршено"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% പൂർത്തിയായി"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% дууссан"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% पूर्ण"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Selesai 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"၁၀၀%ပြီးပါပြီ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"१००% पुरा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% ସମ୍ପୂର୍ଣ୍ଣ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/strings.xml" + line="48" + column="5"/> + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% ਪੂਰਾ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/strings.xml" + line="48" + column="5"/> + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Ukończono w 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% завершено."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% සම්පූර්ණයි"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Dokončano: 100 %"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Довршено је 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-sr/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Imekamilika 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% முடிந்தது"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ta/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% పూర్తయింది"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"เสร็จสมบูรณ์ 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"%100 tamamlandı"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-tr/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% виконано"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% مکمل"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ur/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Hoàn tất 100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"已完成100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"傳送完成"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/strings.xml" + line="48" + column="5"/> + + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"已傳送所有檔案"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="StringFormatCount" + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 0 here and 1 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Iqede ngo-100%"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + file="packages/modules/Bluetooth/android/app/res/values/strings.xml" + line="104" + column="5" + message="Conflicting number of arguments (1) here"/> + id="ExportedContentProvider" + message="Exported content providers can provide access to potentially sensitive data" + errorLine1=" <provider" + errorLine2=" ~~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="144" + column="10"/> + id="ExportedReceiver" + message="Exported receiver does not require permission" + errorLine1=" <receiver" + errorLine2=" ~~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="209" + column="10"/> + message="Exported service does not require permission" + errorLine1=" <service" + errorLine2=" ~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="129" + column="10"/> + message="Exported service does not require permission" + errorLine1=" <service" + errorLine2=" ~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="348" + column="10"/> + id="InvalidPermission" + message="Protecting an unsupported element with a permission is a no-op and potentially dangerous" + errorLine1=" android:permission="android.permission.ACCESS_BLUETOOTH_SHARE" />" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="206" + column="17"/> + id="QueryAllPackagesPermission" + message="A `<queries>` declaration should generally be used instead of QUERY_ALL_PACKAGES; see https://g.co/dev/packagevisibility for details" + errorLine1=" <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="61" + column="22"/> + id="QueryAllPackagesPermission" + message="A `<queries>` declaration should generally be used instead of QUERY_ALL_PACKAGES; see https://g.co/dev/packagevisibility for details" + errorLine1=" <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="61" + column="22"/> + id="Wakelock" + message="The `release()` call is not always reached (can exit the method via path acquire() → d() → removeMessages() → sendMessageDelayed() → obtainMessage() → break → exit; use try/finally to ensure `release` is always called)" + errorLine1=" mWakeLock.release();" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" + line="429" + column="35"/> + id="Wakelock" + message="The `release()` call is not always reached (because of a possible exception in the path acquire() → try → sleep() → if → ! → then → connect() → = → loop → if → ! → then → doSend() → exit; use try/finally to ensure `release` is always called)" + errorLine1=" mWakeLock.release();" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java" + line="216" + column="27"/> + id="Wakelock" + message="The `release()` call is not always reached (can exit the method via path acquire() → w() → report() → removeMessages() → sendMessageDelayed() → obtainMessage() → break → exit; use try/finally to ensure `release` is always called)" + errorLine1=" mWakeLock.release();" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java" + line="543" + column="35"/> + id="Wakelock" + message="The `release()` call is not always reached (can exit the method via path acquire() → d() → removeMessages() → sendMessageDelayed() → obtainMessage() → break → exit; use try/finally to ensure `release` is always called)" + errorLine1=" mWakeLock.release();" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/sap/SapService.java" + line="505" + column="43"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="6161" + column="17"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="235" + column="13"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="418" + column="25"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="177" + column="13"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mPartialWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="325" + column="13"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="527" + column="25"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="296" + column="13"/> + message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery." + errorLine1=" mWakeLock.acquire();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="494" + column="33"/> + id="ObsoleteSdkInt" + message="Unnecessary; SDK_INT is always >= 34" + errorLine1=" @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java" + line="418" + column="5"/> + message="This `AsyncTask` class should be static or leaks might occur (anonymous android.os.AsyncTask)" + errorLine1=" new AsyncTask<Void, Void, Void>() {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="773" + column="9"/> + message="Do not place Android context classes in static fields (static reference to `BluetoothOppManager` which has field `mContext` pointing to `Context`); this is a memory leak" + errorLine1=" @VisibleForTesting static BluetoothOppManager sInstance;" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppManager.java" + line="73" + column="24"/> + message="Do not place Android context classes in static fields (static reference to `BluetoothOppPreference` which has field `mContext` pointing to `Context`); this is a memory leak" + errorLine1=" private static BluetoothOppPreference sInstance;" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppPreference.java" + line="55" + column="13"/> + message="Do not place Android context classes in static fields (static reference to `MediaPlayerList` which has field `mContext` pointing to `Context`); this is a memory leak" + errorLine1=" static MediaPlayerList sMediaPlayerListForTesting = null;" + errorLine2=" ~~~~~~"> + line="90" + column="5"/> + message="Do not place Android context classes in static fields (static reference to `MediaPlayerWrapper` which has field `mContext` pointing to `Context`); this is a memory leak" + errorLine1=" private static MediaPlayerWrapper sInjectedWrapper;" + errorLine2=" ~~~~~~"> - - - - + line="32" + column="13"/> + id="VectorPath" + message="Very long vector path (1535 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector." + errorLine1=" android:pathData="M450,472.15L277.08,645.08Q268.77,653.38 256.19,653.58Q243.62,653.77 234.92,645.08Q226.23,636.38 226.23,624Q226.23,611.62 234.92,602.92L437.85,400L234.92,197.08Q226.62,188.77 226.42,176.19Q226.23,163.62 234.92,154.92Q243.62,146.23 256,146.23Q268.38,146.23 277.08,154.92L450,327.85L450,71.23Q450,54.77 461.04,44.62Q472.08,34.46 486.15,34.46Q493,34.46 499.42,37.08Q505.85,39.69 511.46,45.31L668.84,202.69Q674.46,208.31 676.77,214.54Q679.08,220.77 679.08,228Q679.08,235.23 676.77,241.46Q674.46,247.69 668.84,253.31L522.15,400L668.84,546.69Q674.46,552.31 676.77,558.54Q679.08,564.77 679.08,572Q679.08,579.23 676.77,585.46Q674.46,591.69 668.84,597.31L511.46,754.69Q505.85,760.31 499.42,762.92Q493,765.54 486.15,765.54Q472.08,765.54 461.04,755.38Q450,745.23 450,728.77L450,472.15ZM510,670.62L609.85,572L510,472.15L510,670.62ZM510,327.85L609.85,228L510,129.38L510,327.85ZM320,955.38Q305.31,955.38 294.96,945.04Q284.62,934.69 284.62,920Q284.62,905.31 294.96,894.96Q305.31,884.62 320,884.62Q334.69,884.62 345.04,894.96Q355.38,905.31 355.38,920Q355.38,934.69 345.04,945.04Q334.69,955.38 320,955.38ZM480,955.38Q465.31,955.38 454.96,945.04Q444.62,934.69 444.62,920Q444.62,905.31 454.96,894.96Q465.31,884.62 480,884.62Q494.69,884.62 505.04,894.96Q515.38,905.31 515.38,920Q515.38,934.69 505.04,945.04Q494.69,955.38 480,955.38ZM640,955.38Q625.31,955.38 614.96,945.04Q604.62,934.69 604.62,920Q604.62,905.31 614.96,894.96Q625.31,884.62 640,884.62Q654.69,884.62 665.04,894.96Q675.38,905.31 675.38,920Q675.38,934.69 665.04,945.04Q654.69,955.38 640,955.38Z" />" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/drawable/ic_bluetooth_settings.xml" + line="9" + column="27"/> + message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)" + errorLine1=" new Handler() {" + errorLine2=" ^"> + line="119" + column="13"/> + message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)" + errorLine1=" new Handler() {" + errorLine2=" ^"> + line="227" + column="13"/> + message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)" + errorLine1=" new Handler() {" + errorLine2=" ^"> + line="230" + column="13"/> + message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)" + errorLine1=" new Handler() {" + errorLine2=" ^"> + line="384" + column="13"/> + message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)" + errorLine1=" new Handler() {" + errorLine2=" ^"> - - - - + line="262" + column="13"/> + message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)" + errorLine1=" new Handler() {" + errorLine2=" ^"> - - - - + line="376" + column="13"/> + message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)" + errorLine1=" new Handler() {" + errorLine2=" ^"> - - - - + line="456" + column="13"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"جارٍ استلام الملف..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Fayl qəbulu edilir..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Primanje datoteke..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Атрыманне файла..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Файлът се получава..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"S\'està rebent un fitxer..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Přijímání souboru..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Datei wird heruntergeladen..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Λήψη αρχείου..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Recibiendo archivo..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Faili vastuvõtmine ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Recibindo ficheiro..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"ફાઇલ પ્રાપ્ત થઈ રહી છે ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Primanje datoteke..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Fájl fogadása..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Ֆայլի ստացում..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"ファイルを受信中..."</string>" + errorLine2=" ~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"파일을 수신하는 중..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"ກຳລັງຮັບເອົາໄຟລ໌..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Gaunamas failas..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Notiek faila saņemšana..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Примање датотеки..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"फाइल प्राप्त करत आहे..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Menerima fail..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Mottar fil ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"फाइल प्राप्त गर्दै..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"A receber ficheiro..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Se primește fișierul..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Получение файла..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Prebieha prijímanie súboru..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Prejemanje datoteke ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Примање датотеке..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Tar emot fil ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Inapokea faili..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"กำลังรับไฟล์..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Dosya alınıyor..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Отримання файлу..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"正在接收文件..."</string>" + errorLine2=" ~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="download_line5" msgid="4124272066218470715">"Yamukela ifayela..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="55" + column="63"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"ፋይል በመላክ ላይ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"جارٍ إرسال الملف..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Fayl göndərilir..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Slanje datoteke..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Адпраўка файла..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Файлът се изпраща..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"ফাইল পাঠানো হচ্ছে..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"S\'està enviant el fitxer..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Odesílání souboru..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Datei wird gesendet..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Αποστολή αρχείου..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Enviando archivo..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Faili saatmine ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Envoi de fichier en cours..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Enviando ficheiro..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Slanje datoteke..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Fájl küldése..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Ֆայլն ուղարկվում է..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"ファイルを送信中..."</string>" + errorLine2=" ~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"파일을 보내는 중..."</string>" + errorLine2=" ~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"ກຳລັງສົ່ງໄຟລ໌..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Siunčiamas failas..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Notiek faila sūtīšana..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Испраќање датотека..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Menghantar fail..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Sender filen ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"फाइल पठाउँदै..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"A enviar ficheiro..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Se trimite fișierul..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Отправка файла..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Odosielanie súboru..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Pošiljanje datoteke ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Слање датотеке..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Skickar fil ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Inatuma faili..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"กำลังส่งไฟล์..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Nagpapadala ng file..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Dosya gönderiliyor..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Надсил-ня файлу..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"正在发送文件..."</string>" + errorLine2=" ~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="upload_line5" msgid="3477751464103201364">"Ithumela ifayela..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="69" + column="61"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Lütfən, gözləyin..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Чакайце..."</string>" + errorLine2=" ~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"দয়া করে অপেক্ষা করুন..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Čekejte prosím..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Vent..."</string>" + errorLine2=" ~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Bitte warten..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Περιμένετε..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Por favor, espera..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Por favor, espera..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Palun oodake ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Veuillez patienter..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Agarda..."</string>" + errorLine2=" ~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"કૃપા કરીને રાહ જુઓ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"कृपया इंतज़ार करें..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Kérjük, várjon..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Խնդրում ենք սպասել..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"יש להמתין..."</string>" + errorLine2=" ~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"お待ちください..."</string>" + errorLine2=" ~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"გთხოვთ, მოითმინოთ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"សូម​រង់ចាំ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"ກະລຸນາລໍຖ້າ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Palaukite..."</string>" + errorLine2=" ~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Почекајте..."</string>" + errorLine2=" ~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Түр хүлээнэ үү..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"कृपया प्रतीक्षा करा..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Sila tunggu..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Vent litt ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"कृपया प्रतीक्षा गर्नुहोस्..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Een ogenblik geduld..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"ਕਿਰਪਾ ਕਰਕੇ ਠਹਿਰੋ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Aguarde..."</string>" + errorLine2=" ~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Aguarde..."</string>" + errorLine2=" ~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Așteaptă..."</string>" + errorLine2=" ~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Подождите..."</string>" + errorLine2=" ~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"කරුණාකර රැඳී සිටින්න..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Čakajte..."</string>" + errorLine2=" ~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Počakajte ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Qëndro në pritje..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"దయచేసి వేచి ఉండండి..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"โปรดรอสักครู่..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Lütfen bekleyin..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Vui lòng đợi..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"请稍候..."</string>" + errorLine2=" ~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Sicela ulinde..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="80" + column="72"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"ብሉቱዝ በማብራት ላይ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"جارٍ تفعيل البلوتوث..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Bluetooth yandırılır..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Уключэнне Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Bluetooth се включва..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"ব্লুটুথ চালু করা হচ্ছে..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"S\'està activant el Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Aktiverer Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Bluetooth wird aktiviert..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Activando Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Activando Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Bluetoothi sisselülitamine ..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Otetaan Bluetooth käyttöön..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Bluetooth bekapcsolása..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Bluetooth-ը միանում է..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Menghidupkan Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"BluetoothをONにしています..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"블루투스 켜는 중..."</string>" + errorLine2=" ~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"ກຳລັງເປີດ Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Tiek ieslēgts Bluetooth savienojums..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Вклучување Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Menghidupkan Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"ब्लुटुथलाई सक्रिय पार्दै..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Ativando Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Se activează Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Включение Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Prebieha zapínanie rozhrania Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Inawasha Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Bluetooth açılıyor..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Увімкнення Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"正在打开蓝牙..."</string>" + errorLine2=" ~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"正在開啟藍牙..."</string>" + errorLine2=" ~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="enabling_progress_content" msgid="685427201206684584">"Ivula i-Bluetooth..."</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + line="81" + column="73"/> + message="Replace "..." with ellipsis character (…, &#8230;) ?" + errorLine1=" <string name="bt_toast_4" msgid="480365991944956695">"Datei wird an „<xliff:g id="RECIPIENT">%1$s</xliff:g>“ gesendet..."</string>" + errorLine2=" ~~~~~~~~~~~~~~"> + line="85" + column="98"/> + message="The application adaptive icon is missing a monochrome tag" + errorLine1="<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">" + errorLine2="^"> + line="16" + column="1"/> + message="This text field does not specify an `inputType`" + errorLine1=" <EditText" + errorLine2=" ~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - + line="39" + column="6"/> + message="Missing `autofillHints` attribute" + errorLine1=" <EditText" + errorLine2=" ~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + line="39" + column="6"/> + message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`" + errorLine1=" <EditText" + errorLine2=" ~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - + line="39" + column="6"/> + message="Do not concatenate text displayed with `setText`. Use resource string with placeholders." + errorLine1=" getString(R.string.bt_enable_line1)" + errorLine2=" ^"> - - - - + line="74" + column="17"/> + message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry" + errorLine1=" android:paddingStart="10dip"" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + line="61" + column="9"/> -- GitLab From e590aafa0fafcabd534baa9f681258e4e298c835 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 7 Oct 2024 21:58:59 -0700 Subject: [PATCH 187/875] Properly escape % in xml Before we have this number of error 50 id="StringFormatCount" 95 id="StringFormatInvalid" After we have this 21 id="StringFormatInvalid" 23 id="StringFormatCount" Bug: 289445022 Test: m Bluetooth Flag: Exempt lint Change-Id: I6870f26b98e83cc19d8c59fc40bb15ea6cce4af4 --- android/app/lint-baseline.xml | 6975 ++++++++++++---------------- android/app/res/values/strings.xml | 2 +- 2 files changed, 2860 insertions(+), 4117 deletions(-) diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml index ce57d4d93e6..9929c4003c8 100644 --- a/android/app/lint-baseline.xml +++ b/android/app/lint-baseline.xml @@ -9640,826 +9640,716 @@ + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Voeg rekord in"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-af/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"መዝገብ አስገባ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-am/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"إدراج سجل"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ar/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"ৰেকৰ্ড ভৰাওক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-as/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Qeyd daxil edin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-az/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Umetni zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-b+sr+Latn/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Уставіць запіс"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-be/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Вмъкване на запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bg/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"রেকর্ড ঢোকান"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bn/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Umetni zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-bs/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insereix un registre"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ca/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Vložit záznam"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-cs/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Indsæt post"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-da/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Aufnahme einfügen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-de/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Εισαγωγή αρχείου"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-el/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insert record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rAU/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insert record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rCA/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insert record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rGB/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insert record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rIN/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎Insert record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-en-rXC/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insertar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es-rUS/test_strings.xml" + line="5" + column="13"/> - + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insertar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Sisestage kirje"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-et/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Sartu erregistroa"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-eu/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"درج سابقه"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fa/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Lisää tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fi/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insérer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr-rCA/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Insérer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-fr/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Inserir rexistro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gl/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"રેકોર્ડ શામેલ કરો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-gu/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"रिकॉर्ड सम्मिलित करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hi/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Umetni zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hr/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Rekord beszúrása"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hu/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Կատարեք գրառում"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-hy/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Masukkan catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-in/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Setja inn færslu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-is/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Inserisci record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-it/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"הוספת רשומה"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-iw/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"記録を挿入"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ja/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"ჩანაწერის ჩასმა"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ka/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Жазбаны енгізу"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kk/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"បញ្ចូល​កំណត់ត្រា"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-km/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"ರೆಕಾರ್ಡ್‌ ಸೇರಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-kn/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"기록 삽입"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ko/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Жазуу киргизүү"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ky/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"ໃສ່ບັນທຶກ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lo/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Įterpti įrašą"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lt/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Ievietot ierakstu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-lv/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Вметни запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mk/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"റെക്കോർഡ് ചേർക്കുക"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ml/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Бичлэг оруулах"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mn/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"रेकॉर्ड घाला"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-mr/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Masukkan rekod"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ms/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"မှတ်တမ်း ထည့်သွင်းရန်"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-my/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Sett inn oppføring"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nb/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"रेकर्ड राख्नुहोस्"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ne/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Record invoegen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-nl/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"ରେକର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-or/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"ਰਿਕਾਰਡ ਦਾਖਲ ਕਰੋ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pa/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Wstaw rekord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pl/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Inserir registo"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt-rPT/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Inserir registro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-pt/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Inserează o înregistrare"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-ro/test_strings.xml" + line="5" + column="13"/> + id="ExtraTranslation" + message=""insert_record" is translated here but not found in default locale" + errorLine1=" <string name="insert_record" msgid="4024416351836939752">"Вставить запись"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + file="packages/modules/Bluetooth/android/app/res/values-ru/test_strings.xml" + line="5" + column="13"/> @@ -10467,10 +10357,10 @@ @@ -10478,10 +10368,10 @@ @@ -10489,10 +10379,10 @@ @@ -10500,10 +10390,10 @@ @@ -10511,10 +10401,10 @@ @@ -10522,10 +10412,10 @@ @@ -10533,10 +10423,10 @@ @@ -10544,10 +10434,10 @@ @@ -10555,10 +10445,10 @@ @@ -10566,10 +10456,10 @@ @@ -10577,10 +10467,10 @@ @@ -10588,10 +10478,10 @@ @@ -10599,10 +10489,10 @@ @@ -10610,10 +10500,10 @@ @@ -10621,10 +10511,10 @@ @@ -10632,10 +10522,10 @@ @@ -10643,10 +10533,10 @@ @@ -10654,10 +10544,10 @@ @@ -10665,725 +10555,725 @@ @@ -11391,10 +11281,10 @@ @@ -11402,10 +11292,10 @@ @@ -11413,10 +11303,10 @@ @@ -11424,10 +11314,10 @@ @@ -11435,10 +11325,10 @@ @@ -11446,10 +11336,10 @@ @@ -11457,10 +11347,10 @@ @@ -11468,10 +11358,10 @@ @@ -11479,10 +11369,10 @@ @@ -11490,10 +11380,10 @@ @@ -11501,10 +11391,10 @@ @@ -11512,10 +11402,10 @@ @@ -11523,10 +11413,10 @@ @@ -11534,10 +11424,10 @@ @@ -11545,10 +11435,10 @@ @@ -11556,10 +11446,10 @@ @@ -11567,10 +11457,10 @@ @@ -11578,10 +11468,10 @@ @@ -11589,725 +11479,615 @@ - + + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack መዝገብ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"‏سجل Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"স্বীকৃত কৰা ৰেকৰ্ড"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack qeydəalma"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Запіс"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Запис на Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack রেকর্ড"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Evidencija Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Registre de notificacions"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Záznam ACK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack-post"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Aufnahme bestätigen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Αρχείο ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎Ack record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Confirmación de la grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Confirmar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Acki kirje"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ACK erregistroa"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"‏سابقه Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Hyv. tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Enregistrement accusé de réception"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Enregistrement accusé de réception"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Rexistro Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack રેકોર્ડ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"रिकॉर्ड अभिस्वीकृत करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ACK rekord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ACK գրառում"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Akui catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack-færsla"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Record ACK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"אישור רשומה"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ackレコード"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack ჩანაწერი"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Жазбаны тану"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"កំណត់ត្រា​ការ​ទទួល​ស្គាល់"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack ರೆಕಾರ್ಡ್‌ ಮಾಡಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"기록 인식"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"ບັນທຶກ Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Įrašas apie patvirtinimą"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack ieraksts"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack റെക്കോർഡ്"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack бичлэг"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Ack रेकॉर्ड"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Rekod Ack"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + message=""ack_record" is translated here but not found in default locale" + errorLine1=" <string name="ack_record" msgid="2404738476192250210">"အသိအမှတ်ပြု မှတ်တမ်း"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -12315,10 +12095,10 @@ @@ -12326,10 +12106,10 @@ @@ -12337,10 +12117,10 @@ @@ -12348,10 +12128,10 @@ @@ -12359,10 +12139,10 @@ @@ -12370,10 +12150,10 @@ @@ -12381,10 +12161,10 @@ @@ -12392,10 +12172,10 @@ @@ -12403,10 +12183,10 @@ @@ -12414,10 +12194,10 @@ @@ -12428,7 +12208,7 @@ errorLine1=" <string name="ack_record" msgid="2404738476192250210">"Záznam ACK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -12436,10 +12216,10 @@ @@ -12447,10 +12227,10 @@ @@ -12458,10 +12238,10 @@ @@ -12469,10 +12249,10 @@ @@ -12480,10 +12260,10 @@ @@ -12491,10 +12271,10 @@ @@ -12502,10 +12282,10 @@ @@ -12513,10 +12293,10 @@ @@ -12524,10 +12304,10 @@ @@ -12535,10 +12315,10 @@ @@ -12546,10 +12326,10 @@ @@ -12557,10 +12337,10 @@ @@ -12568,10 +12348,10 @@ @@ -12579,10 +12359,10 @@ @@ -12590,10 +12370,10 @@ @@ -12601,10 +12381,10 @@ @@ -12612,10 +12392,10 @@ @@ -12623,615 +12403,593 @@ + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Vee alle rekords uit"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ሁሉንም መዝገብ ሰርዝ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"حذف السجل كله"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"আটাইবোৰ ৰেকৰ্ড মচক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Bütün qeydləri silin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Izbriši sve zapise"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Выдаліць усе запісы"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Изтриване на всички записи"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"সব রেকর্ড মুছে দিন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Izbriši svu evidenciju"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Suprimeix tots els registres"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Smazat všechny záznamy"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Slet alle poster"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Gesamte Aufnahme löschen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Διαγραφή όλων των αρχείων"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Delete all record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‎Delete all record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eliminar todas las grabaciones"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eliminar todas las grabaciones"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Kustuta kõik kirjed"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Ezabatu erregistro guztiak"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"حذف همه سابقه"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Poista kaikki tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Supprimer tout l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Supprimer tout l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eliminar todos os rexistros"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"તમામ રેકોર્ડ કાઢી નાખો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"सभी रिकॉर्ड मिटाएं"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Izbriši sve zapise"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Minden rekord törlése"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Ջնջել բոլոր գրառումները"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Hapus semua catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Eyða öllum færslum"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Elimina tutti i record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"מחיקת כל הרשומות"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"レコードをすべて削除"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ყველა ჩანაწერის წაშლა"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Барлық жазбаларды жою"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"លុប​កំណត់​ត្រា​ទាំងអស់"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ಎಲ್ಲ ರೆಕಾರ್ಡ್‌ ಅನ್ನು ಅಳಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"모든 기록 삭제"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Бардык жазууларды жок кылуу"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"ລຶບບັນທຶກທັງໝົດ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Ištrinti visus įrašus"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Dzēst visus ierakstus"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Избриши ги сите записи"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"എല്ലാ റെക്കോർഡും ഇല്ലാതാക്കുക"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"Бүх бичлэгийг устгах"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - + message=""deleteAll_record" is translated here but not found in default locale" + errorLine1=" <string name="deleteAll_record" msgid="7932073446547882011">"सर्व रेकॉर्ड हटवा"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -13239,10 +12997,10 @@ @@ -13250,10 +13008,10 @@ @@ -13261,10 +13019,10 @@ @@ -13272,10 +13030,10 @@ @@ -13283,10 +13041,10 @@ @@ -13294,10 +13052,10 @@ @@ -13305,10 +13063,10 @@ @@ -13316,10 +13074,10 @@ @@ -13327,10 +13085,10 @@ @@ -13338,10 +13096,10 @@ @@ -13349,10 +13107,10 @@ @@ -13360,10 +13118,10 @@ @@ -13371,10 +13129,10 @@ @@ -13382,10 +13140,10 @@ @@ -13393,10 +13151,10 @@ @@ -13404,10 +13162,10 @@ @@ -13415,10 +13173,10 @@ @@ -13426,10 +13184,10 @@ @@ -13437,10 +13195,10 @@ @@ -13448,10 +13206,10 @@ @@ -13459,10 +13217,10 @@ @@ -13470,10 +13228,10 @@ @@ -13481,10 +13239,10 @@ @@ -13492,10 +13250,10 @@ @@ -13503,10 +13261,10 @@ @@ -13514,10 +13272,10 @@ @@ -13525,10 +13283,10 @@ @@ -13536,10 +13294,10 @@ @@ -13547,10 +13305,10 @@ @@ -13558,10 +13316,10 @@ @@ -13569,583 +13327,583 @@ + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"እሺ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"حسنًا"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ঠিক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Potvrdi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ОК"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ঠিক আছে"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Uredu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"D\'acord"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Ok"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ΟΚ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎OK‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Aceptar"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Aceptar"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Ados"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"تأیید"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Aceptar"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ઓકે"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ठीक है"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"U redu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Եղավ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Oke"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Í lagi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"אישור"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"კარგი"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Жарайды"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"យល់​ព្រម​"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ಸರಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"확인"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ຕົກລົງ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Gerai"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Labi"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"Во ред"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ശരി"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> + message=""ok_button" is translated here but not found in default locale" + errorLine1=" <string name="ok_button" msgid="719865942400179601">"ठीक"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14155,7 +13913,7 @@ errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14163,10 +13921,10 @@ @@ -14174,10 +13932,10 @@ @@ -14185,10 +13943,10 @@ @@ -14199,7 +13957,7 @@ errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14207,10 +13965,10 @@ @@ -14218,10 +13976,10 @@ @@ -14232,7 +13990,7 @@ errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14240,10 +13998,10 @@ @@ -14251,10 +14009,10 @@ @@ -14262,10 +14020,10 @@ @@ -14273,10 +14031,10 @@ @@ -14284,10 +14042,10 @@ @@ -14295,10 +14053,10 @@ @@ -14306,10 +14064,10 @@ @@ -14317,10 +14075,10 @@ @@ -14328,10 +14086,10 @@ @@ -14342,7 +14100,7 @@ errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14350,10 +14108,10 @@ @@ -14361,10 +14119,10 @@ @@ -14372,10 +14130,10 @@ @@ -14383,10 +14141,10 @@ @@ -14397,7 +14155,7 @@ errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14405,10 +14163,10 @@ @@ -14416,10 +14174,10 @@ @@ -14427,10 +14185,10 @@ @@ -14441,7 +14199,7 @@ errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14452,7 +14210,7 @@ errorLine1=" <string name="ok_button" msgid="719865942400179601">"OK"</string>" errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -14460,10 +14218,10 @@ @@ -14471,10 +14229,10 @@ @@ -14482,10 +14240,10 @@ @@ -14493,593 +14251,560 @@ + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Vee rekord uit"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"መዝገብ ሰርዝ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"حذف السجل"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ৰেকৰ্ড মচক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Qeydi silin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Izbriši zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Выдаліць запіс"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Изтриване на записа"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"রেকর্ড মুছে দিন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Izbriši evidenciju"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Suprimeix el registre"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Smazat záznam"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Slet post"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Aufnahme löschen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Διαγραφή αρχείου"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Delete record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎Delete record‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eliminar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eliminar grabación"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Kustuta kirje"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - + + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"حذف سابقه"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Poista tiedot"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Supprimer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Supprimer l\'enregistrement"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eliminar rexistro"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"રેકોર્ડ કાઢી નાખો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"रिकॉर्ड मिटाएं"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Izbriši zapis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Rekord törlése"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Ջնջել գրառումը"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Hapus catatan"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Eyða færslu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Elimina record"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"מחיקת רשומה"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"レコードを削除"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ჩანაწერის წაშლა"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Жазбаны жою"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"លុប​កំណត់​ត្រា"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ರೆಕಾರ್ಡ್‌ ಅಳಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"기록 삭제"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Жазууну жок кылуу"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"ລຶບການບັນທຶກ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Ištrinti įrašą"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Dzēst ierakstu"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""delete_record" is translated here but not found in default locale" + errorLine1=" <string name="delete_record" msgid="5713885957446255270">"Избриши запис"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - @@ -15087,10 +14812,10 @@ @@ -15098,10 +14823,10 @@ @@ -15109,10 +14834,10 @@ @@ -15120,10 +14845,10 @@ @@ -15131,10 +14856,10 @@ @@ -15142,10 +14867,10 @@ @@ -15153,10 +14878,10 @@ @@ -15164,10 +14889,10 @@ @@ -15175,10 +14900,10 @@ @@ -15186,10 +14911,10 @@ @@ -15197,10 +14922,10 @@ @@ -15208,10 +14933,10 @@ @@ -15219,10 +14944,10 @@ @@ -15230,10 +14955,10 @@ @@ -15241,10 +14966,10 @@ @@ -15252,10 +14977,10 @@ @@ -15263,10 +14988,10 @@ @@ -15274,10 +14999,10 @@ @@ -15285,10 +15010,10 @@ @@ -15296,10 +15021,10 @@ @@ -15307,10 +15032,10 @@ @@ -15318,10 +15043,10 @@ @@ -15329,10 +15054,10 @@ @@ -15340,10 +15065,10 @@ @@ -15351,10 +15076,10 @@ @@ -15362,10 +15087,10 @@ @@ -15373,10 +15098,10 @@ @@ -15384,10 +15109,10 @@ @@ -15395,10 +15120,10 @@ @@ -15406,10 +15131,10 @@ @@ -15417,10 +15142,10 @@ @@ -15428,10 +15153,10 @@ @@ -15439,10 +15164,10 @@ @@ -15450,560 +15175,560 @@ + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Begin TCP-bediener"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP አገልጋይን ጀምር"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‏بدء الخادم TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP ছাৰ্ভাৰ আৰম্ভ কৰক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP serverinə başlayın"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Pokreni TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Запусціць сервер TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Стартиране на TCP сървър"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP সার্ভার শুরু করুন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Pokreni TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Inicia el servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Spustit server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP-Server starten"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Εκκίνηση διακομιστή TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Start TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎Start TCP server‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar el servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Käivita TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Hasi TCP zerbitzaria"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‏راه‌اندازی سرور TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Käynnistä TCP-palvelin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Démarrer le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Démarrer le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Iniciar servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP સર્વર પ્રારંભ કરો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP सर्वर शरू करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Pokreni TCP poslužitelj"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP-szerver indítása"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Մեկնարկել TCP սերվերը"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Mulai server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Ræsa TCP-þjón"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Avvia server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"‏הפעלת שרת TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCPサーバーを起動"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP სერვერის დაწყება"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP серверін бастау"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"ចាប់ផ្ដើម​​ម៉ាស៊ីន​មេ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP ಸರ್ವರ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP 서버 시작"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"TCP серверин баштоо"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"ເລີ່ມ TCP ເຊີບເວີ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Paleisti TCP serverį"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Palaist TCP serveri"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + message=""start_server" is translated here but not found in default locale" + errorLine1=" <string name="start_server" msgid="134483798422082514">"Започни TCP сервер"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -16011,10 +15736,10 @@ @@ -16022,10 +15747,10 @@ @@ -16033,10 +15758,10 @@ @@ -16044,10 +15769,10 @@ @@ -16055,10 +15780,10 @@ @@ -16066,10 +15791,10 @@ @@ -16077,10 +15802,10 @@ @@ -16088,10 +15813,10 @@ @@ -16099,10 +15824,10 @@ @@ -16110,10 +15835,10 @@ @@ -16121,10 +15846,10 @@ @@ -16132,10 +15857,10 @@ @@ -16143,10 +15868,10 @@ @@ -16154,10 +15879,10 @@ @@ -16165,10 +15890,10 @@ @@ -16176,10 +15901,10 @@ @@ -16187,10 +15912,10 @@ @@ -16198,10 +15923,10 @@ @@ -16209,10 +15934,10 @@ @@ -16220,10 +15945,10 @@ @@ -16231,10 +15956,10 @@ @@ -16242,10 +15967,10 @@ @@ -16253,10 +15978,10 @@ @@ -16264,10 +15989,10 @@ @@ -16275,10 +16000,10 @@ @@ -16286,10 +16011,10 @@ @@ -16297,10 +16022,10 @@ @@ -16308,10 +16033,10 @@ @@ -16319,10 +16044,10 @@ @@ -16330,10 +16055,10 @@ @@ -16341,10 +16066,10 @@ @@ -16352,10 +16077,10 @@ @@ -16363,10 +16088,10 @@ @@ -16374,670 +16099,538 @@ + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Stel TCP-bediener in kennis"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP አገልጋይን አሳውቅ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‏إعلام الخادم TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP ছাৰ্ভাৰক জাননী দিয়ক"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP serverinə bildirin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Obavesti TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Апавясцiць сервер TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Известяване на TCP сървър"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP সার্ভার সূচিত করুন"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Obavijesti TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notifica-ho al servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Upozornit server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Meddel TCP-server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP-Server benachrichtigen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Να ειδοποιείται ο διακομιστής TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notify TCP server"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎Notify TCP server‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notificar al servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Informar al servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-es/test_strings.xml" + line="12" + column="13"/> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Teavita TCP-serverit"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Jakinarazi TCP zerbitzariari"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‏اعلان سرور TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Ilmoita TCP-palvelin"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Avertir le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Avertir le serveur TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Notificar ao servidor TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP સર્વરને સૂચિત કરો"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP सर्वर को सूचित करें"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Obavijesti TCP poslužitelj"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP-szerver értesítése"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Ծանուցել TCP սերվերին"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Beri tahu server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Tilkynna TCP-þjóni"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Invia notifica al server TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"‏שליחת התראה לשרת TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCPサーバーに通知"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP სერვერის შეტყობინება"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP (жібреуі басқару протоколы) серверін ескерту"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"ជូន​ដំណឹង​ម៉ាស៊ីន​មេ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP ಸರ್ವರ್ ಅನ್ನು ಸೂಚಿಸಿ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP 서버 알림"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP серверин маалымдоо"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"ແຈ້ງເຕືອນ TCP ເຊີບເວີ"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Pranešti TCP serveriui"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -17045,10 +16638,10 @@ @@ -17056,10 +16649,10 @@ @@ -17067,10 +16660,10 @@ @@ -17078,10 +16671,10 @@ @@ -17089,10 +16682,10 @@ @@ -17100,10 +16693,10 @@ @@ -17111,10 +16704,10 @@ @@ -17122,10 +16715,10 @@ @@ -17133,10 +16726,10 @@ @@ -17144,10 +16737,10 @@ @@ -17155,10 +16748,10 @@ @@ -17166,10 +16759,10 @@ @@ -17177,10 +16770,10 @@ @@ -17188,10 +16781,10 @@ @@ -17199,10 +16792,10 @@ @@ -17210,10 +16803,10 @@ @@ -17221,10 +16814,10 @@ @@ -17232,10 +16825,10 @@ @@ -17243,10 +16836,10 @@ @@ -17254,10 +16847,10 @@ @@ -17265,10 +16858,10 @@ @@ -17276,10 +16869,10 @@ @@ -17287,10 +16880,10 @@ @@ -17298,10 +16891,10 @@ @@ -17309,10 +16902,10 @@ @@ -17320,10 +16913,10 @@ @@ -17331,10 +16924,10 @@ @@ -17342,10 +16935,10 @@ @@ -17353,10 +16946,10 @@ @@ -17364,1285 +16957,446 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"TCP serverga xabar berish"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-uz/test_strings.xml" + line="12" + column="13"/> - + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Thông báo cho máy chủ TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-vi/test_strings.xml" + line="12" + column="13"/> - + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"通知TCP服务器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rCN/test_strings.xml" + line="12" + column="13"/> - + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"通知 TCP 伺服器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rHK/test_strings.xml" + line="12" + column="13"/> - + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"通知 TCP 伺服器"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zh-rTW/test_strings.xml" + line="12" + column="13"/> - + id="ExtraTranslation" + message=""notify_server" is translated here but not found in default locale" + errorLine1=" <string name="notify_server" msgid="8832385166935137731">"Yazisa iseva ye-TCP"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/res/values-zu/test_strings.xml" + line="12" + column="13"/> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100 % fuldført"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"Zu 100 % abgeschlossen"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> - - - - - + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% complete"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% complete"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% complete"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎100% complete‎‏‎‎‏‎"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Conflicting number of arguments (0) here"/> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100 % effectués"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100 % effectués"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% completado"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% dovršeno"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% selesai"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100 % baigta"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100 % fullført"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% concluído"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100% concluído"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100 % finalizat"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Inconsistent number of arguments in formatting string `notification_sent_complete`; found both 1 here and 0 in values/strings.xml" + errorLine1=" <string name="notification_sent_complete" msgid="6293391081175517098">"100 % hotovo"</string>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Conflicting number of arguments (0) here"/> + message="Conflicting number of arguments (0) here"/> - - - - Bluetooth share: Sent %1$s - 100% complete + 100%% complete Bluetooth share: File %1$s not sent -- GitLab From 23a3c64829405180d6670ad8a8b18d746c213190 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 7 Oct 2024 22:28:22 -0700 Subject: [PATCH 188/875] Properly inject mediaPlayerList in test Fix a staticFieldLeak Bug: 289445022 Test: m Bluetooth Flag: Exempt lint Change-Id: Ic065b351c4dd0fcb0c6c3b69391b6fa4e2641c79 --- android/app/lint-baseline.xml | 57 ++++++++----------- .../bluetooth/mcp/MediaControlProfile.java | 16 ++---- .../mcp/MediaControlProfileTest.java | 3 +- 3 files changed, 29 insertions(+), 47 deletions(-) diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml index 9929c4003c8..8b51a67d099 100644 --- a/android/app/lint-baseline.xml +++ b/android/app/lint-baseline.xml @@ -17042,7 +17042,7 @@ column="5"/> @@ -17058,7 +17058,7 @@ column="5"/> @@ -17074,7 +17074,7 @@ column="5"/> @@ -17090,7 +17090,7 @@ column="5"/> @@ -17106,7 +17106,7 @@ column="5"/> @@ -17122,7 +17122,7 @@ column="5"/> @@ -17138,7 +17138,7 @@ column="5"/> @@ -17154,7 +17154,7 @@ column="5"/> @@ -17170,7 +17170,7 @@ column="5"/> @@ -17186,7 +17186,7 @@ column="5"/> @@ -17202,7 +17202,7 @@ column="5"/> @@ -17218,7 +17218,7 @@ column="5"/> @@ -17234,7 +17234,7 @@ column="5"/> @@ -17250,7 +17250,7 @@ column="5"/> @@ -17266,7 +17266,7 @@ column="5"/> @@ -17282,7 +17282,7 @@ column="5"/> @@ -17298,7 +17298,7 @@ column="5"/> @@ -17314,7 +17314,7 @@ column="5"/> @@ -17330,7 +17330,7 @@ column="5"/> @@ -17346,7 +17346,7 @@ column="5"/> @@ -17362,7 +17362,7 @@ column="5"/> @@ -17378,7 +17378,7 @@ column="5"/> @@ -17394,7 +17394,7 @@ column="5"/> @@ -17641,17 +17641,6 @@ column="13"/> - - - - Date: Tue, 8 Oct 2024 14:34:15 +0800 Subject: [PATCH 189/875] btm_acl: Only allow automatic flush if packet boundary is supported Bug: 372035961 Tag: #floss Test: mmm packages/modules/Bluetooth Test: bluetooth_AdapterAUHealth.au_hfp_nbs_dut_as_source_test.floss Flag: EXEMPT, behind Floss-only prop (bluetooth.core.classic.auto_flush_timeout) Change-Id: I0c68e1a3042282b2a3188f2b9b9506f072b643b1 --- system/stack/acl/btm_acl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 858f139d272..6d0e5d8a06c 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -193,7 +193,7 @@ void NotifyAclFeaturesReadComplete(tACL_CONN& p_acl, uint8_t max_page_number) { btm_process_remote_ext_features(&p_acl, max_page_number); btm_set_link_policy(&p_acl, btm_cb.acl_cb_.DefaultLinkPolicy()); int32_t flush_timeout = osi_property_get_int32(PROPERTY_AUTO_FLUSH_TIMEOUT, 0); - if (flush_timeout != 0) { + if (bluetooth::shim::GetController()->SupportsNonFlushablePb() && flush_timeout != 0) { acl_write_automatic_flush_timeout(p_acl.remote_addr, static_cast(flush_timeout)); } BTA_dm_notify_remote_features_complete(p_acl.remote_addr); -- GitLab From bc363fdd83c015847d2b9f403a31fc27bfe3dc32 Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Tue, 3 Sep 2024 13:00:10 +0000 Subject: [PATCH 190/875] Bass: Broadcast resync helper, out of range case Helps sinks to resync to external broadcast when out of range. When there is a SINK PAUSE and BASS cannot sync to the broadcaster, then it will try to sync till MESSAGE_BROADCAST_MONITOR_TIMEOUT occur, which is 5 minutes. If it syncs to the broadcaster then MESSAGE_BROADCAST_MONITOR_TIMEOUT is removed, but MESSAGE_BIG_MONITOR_TIMEOUT is still counting to the 30 minutes. MESSAGE_BIG_MONITOR_TIMEOUT is used to help sinks to resync when BIG appear, i.e. when unpausing. Bug: 363950680 Bug: 363168099 Test: atest BassClientServiceTest Change-Id: Idee9165dfb756b8eceae92afb0f56a3cc28979fa --- .../bass_client/BassClientService.java | 139 +++++++---- .../bass_client/BassClientServiceTest.java | 218 ++++++++++++++++-- 2 files changed, 295 insertions(+), 62 deletions(-) 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 2f95d067039..772b295ca12 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -123,8 +123,10 @@ public class BassClientService extends ProfileService { private static final int BROADCAST_STATE_STREAMING = 6; @VisibleForTesting static final int MESSAGE_SYNC_TIMEOUT = 1; - @VisibleForTesting static final int MESSAGE_BIG_CHECK_START = 2; - @VisibleForTesting static final int MESSAGE_BIG_CHECK_STOP = 3; + @VisibleForTesting static final int MESSAGE_BIG_MONITOR_TIMEOUT = 2; + @VisibleForTesting static final int MESSAGE_BIG_CHECK_START = 3; + @VisibleForTesting static final int MESSAGE_BIG_CHECK_STOP = 4; + @VisibleForTesting static final int MESSAGE_BROADCAST_MONITOR_TIMEOUT = 5; /* 1 minute timeout for primary device reconnection in Private Broadcast case */ private static final int DIALING_OUT_TIMEOUT_MS = 60000; @@ -135,11 +137,14 @@ public class BassClientService extends ProfileService { // 6 seconds to start BIG check. It has to be greater than kPeriodicSyncTimeout private static final Duration sBigCheckStart = Duration.ofSeconds(6); - // 2 second for check if BIG exist + // 2 seconds for check if BIG exist private static final Duration sBigCheckStop = Duration.ofSeconds(2); - // 5 minutes timeout for monitoring BIG resynchronization - private static final Duration sBigMonitorTimeout = Duration.ofMinutes(5); + // 30 minutes timeout for monitoring BIG resynchronization + private static final Duration sBigMonitorTimeout = Duration.ofMinutes(30); + + // 5 minutes timeout for monitoring broadcaster + private static final Duration sBroadcasterMonitorTimeout = Duration.ofMinutes(5); private enum PauseType { HOST_INTENTIONAL, @@ -219,13 +224,33 @@ public class BassClientService extends ProfileService { switch (msg.what) { case MESSAGE_SYNC_TIMEOUT: { - if (!leaudioBroadcastResyncHelper()) { - clearAllSyncData(); + log("MESSAGE_SYNC_TIMEOUT"); + clearAllSyncData(); + break; + } + case MESSAGE_BROADCAST_MONITOR_TIMEOUT: + { + log("MESSAGE_BROADCAST_MONITOR_TIMEOUT"); + int broadcastId = msg.arg1; + List activeSyncedSrc = + new ArrayList<>(getActiveSyncedSources()); + if (activeSyncedSrc.contains( + getSyncHandleForBroadcastId(broadcastId))) { break; } - log("MESSAGE_SYNC_TIMEOUT"); + log("Notify broadcast source lost, broadcast id: " + broadcastId); + mCallbacks.notifySourceLost(broadcastId); + // fall through + } + case MESSAGE_BIG_MONITOR_TIMEOUT: + { + log("MESSAGE_BIG_MONITOR_TIMEOUT"); int broadcastId = msg.arg1; - stopBigMonitoring(broadcastId, false); + if (isSinkUnintentionalPauseType(broadcastId)) { + stopSourceReceivers(broadcastId); + } else { + stopBigMonitoring(broadcastId, false); + } synchronized (mSearchScanCallbackLock) { // when searching is stopped then clear all sync data if (mSearchScanCallback == null) { @@ -242,6 +267,7 @@ public class BassClientService extends ProfileService { mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_CHECK_STOP); newMsg.arg1 = broadcastId; + log("Started MESSAGE_BIG_CHECK_STOP"); mHandler.sendMessageDelayed(newMsg, sBigCheckStop.toMillis()); break; } @@ -258,13 +284,6 @@ public class BassClientService extends ProfileService { broadcastId, PauseType.SINK_UNINTENTIONAL); cacheSuspendingSources(broadcastId); } - // Timer starts even if pause is SINK_INTENTIONAL to keep sync in - // case that buds send SyncInfo Request - mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT); - log("Started timeout for canceling syncs"); - Message newMsg = mHandler.obtainMessage(MESSAGE_SYNC_TIMEOUT); - newMsg.arg1 = broadcastId; - mHandler.sendMessageDelayed(newMsg, sBigMonitorTimeout.toMillis()); break; } default: @@ -1066,7 +1085,14 @@ public class BassClientService extends ProfileService { mHandler.removeMessages(MESSAGE_BIG_CHECK_START); Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_CHECK_START); newMsg.arg1 = broadcastId; + log("Started MESSAGE_BIG_CHECK_START"); mHandler.sendMessageDelayed(newMsg, sBigCheckStart.toMillis()); + + mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); + newMsg = mHandler.obtainMessage(MESSAGE_BIG_MONITOR_TIMEOUT); + newMsg.arg1 = broadcastId; + log("Started MESSAGE_BIG_MONITOR_TIMEOUT"); + mHandler.sendMessageDelayed(newMsg, sBigMonitorTimeout.toMillis()); } } } else if (isEmptyBluetoothDevice(receiveState.getSourceDevice())) { @@ -2057,15 +2083,18 @@ public class BassClientService extends ProfileService { null); addActiveSyncedSource(syncHandle); - synchronized (mSearchScanCallbackLock) { - // when searching is stopped then start timer to stop active sync - if (mSearchScanCallback == null) { - mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT); - log("Started timeout for canceling syncs"); - Message newMsg = mHandler.obtainMessage(MESSAGE_SYNC_TIMEOUT); - newMsg.arg1 = broadcastId; - mHandler.sendMessageDelayed(newMsg, sSyncActiveTimeout.toMillis()); + if (!leaudioBroadcastResyncHelper()) { + synchronized (mSearchScanCallbackLock) { + // when searching is stopped then start timer to stop active syncs + if (mSearchScanCallback == null) { + mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT); + log("Started MESSAGE_SYNC_TIMEOUT"); + mHandler.sendEmptyMessageDelayed( + MESSAGE_SYNC_TIMEOUT, sSyncActiveTimeout.toMillis()); + } } + } else { + mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); } // update valid sync handle in mPeriodicAdvCallbacksMap @@ -2113,15 +2142,24 @@ public class BassClientService extends ProfileService { } } } - stopBigMonitoring(broadcastId, false); synchronized (mSourceSyncRequestsQueue) { int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1; mSyncFailureCounter.put(broadcastId, failsCounter); } - synchronized (mSearchScanCallbackLock) { + if (isAnySinkPauseType(broadcastId)) { + if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { + Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT); + newMsg.arg1 = broadcastId; + log("Started MESSAGE_BROADCAST_MONITOR_TIMEOUT"); + mHandler.sendMessageDelayed(newMsg, sBroadcasterMonitorTimeout.toMillis()); + } + addSelectSourceRequest(broadcastId, true); + } else { // Clear from cache to make possible sync again (only during active searching) - if (mSearchScanCallback != null) { - mCachedBroadcasts.remove(broadcastId); + synchronized (mSearchScanCallbackLock) { + if (mSearchScanCallback != null) { + mCachedBroadcasts.remove(broadcastId); + } } } mPeriodicAdvCallbacksMap.remove(BassConstants.INVALID_SYNC_HANDLE); @@ -2186,22 +2224,31 @@ public class BassClientService extends ProfileService { public void onSyncLost(int syncHandle) { int broadcastId = getBroadcastIdForSyncHandle(syncHandle); log("OnSyncLost: syncHandle=" + syncHandle + ", broadcastID=" + broadcastId); + clearAllDataForSyncHandle(syncHandle); if (broadcastId != BassConstants.INVALID_BROADCAST_ID) { - if (leaudioBroadcastMonitorSourceSyncStatus()) { - log("Notify broadcast source lost, broadcast id: " + broadcastId); - mCallbacks.notifySourceLost(broadcastId); - } - stopBigMonitoring(broadcastId, false); synchronized (mSourceSyncRequestsQueue) { int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1; mSyncFailureCounter.put(broadcastId, failsCounter); } - } - clearAllDataForSyncHandle(syncHandle); - // Clear from cache to make possible sync again (only during active searching) - synchronized (mSearchScanCallbackLock) { - if (mSearchScanCallback != null) { - mCachedBroadcasts.remove(broadcastId); + if (isAnySinkPauseType(broadcastId)) { + if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { + Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT); + newMsg.arg1 = broadcastId; + log("Started MESSAGE_BROADCAST_MONITOR_TIMEOUT"); + mHandler.sendMessageDelayed(newMsg, sBroadcasterMonitorTimeout.toMillis()); + } + addSelectSourceRequest(broadcastId, true); + } else { + // Clear from cache to make possible sync again (only during active searching) + synchronized (mSearchScanCallbackLock) { + if (mSearchScanCallback != null) { + mCachedBroadcasts.remove(broadcastId); + } + } + if (leaudioBroadcastMonitorSourceSyncStatus()) { + log("Notify broadcast source lost, broadcast id: " + broadcastId); + mCallbacks.notifySourceLost(broadcastId); + } } } } @@ -3445,14 +3492,20 @@ public class BassClientService extends ProfileService { && mPausedBroadcastIds.get(broadcastId).equals(PauseType.HOST_INTENTIONAL)); } + private boolean isSinkUnintentionalPauseType(int broadcastId) { + return (mPausedBroadcastIds.containsKey(broadcastId) + && mPausedBroadcastIds.get(broadcastId).equals(PauseType.SINK_UNINTENTIONAL)); + } + public void stopBigMonitoring() { if (!leaudioBroadcastResyncHelper()) { return; } log("stopBigMonitoring"); - mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT); + mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); mHandler.removeMessages(MESSAGE_BIG_CHECK_START); mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); + mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); mPausedBroadcastSinks.clear(); @@ -3479,9 +3532,10 @@ public class BassClientService extends ProfileService { while (iterator.hasNext()) { int pausedBroadcastId = iterator.next(); if (!isAnyReceiverSyncedToBroadcast(pausedBroadcastId)) { - mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT); + mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); mHandler.removeMessages(MESSAGE_BIG_CHECK_START); mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); + mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); iterator.remove(); synchronized (mSearchScanCallbackLock) { // when searching is stopped then stop active sync @@ -3499,9 +3553,10 @@ public class BassClientService extends ProfileService { return; } log("stopBigMonitoring broadcastId: " + broadcastId + ", hostInitiated: " + hostInitiated); - mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT); + mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); mHandler.removeMessages(MESSAGE_BIG_CHECK_START); mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); + mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); if (hostInitiated) { mPausedBroadcastIds.put(broadcastId, PauseType.HOST_INTENTIONAL); } else { diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 3ba383a656c..897515a3036 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -1133,6 +1133,7 @@ public class BassClientServiceTest { @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) + @DisableFlags(Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER) public void testStopSearchingForSources_timeoutForActiveSync() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -1172,6 +1173,7 @@ public class BassClientServiceTest { @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) + @DisableFlags(Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER) public void testStopSearchingForSources_clearTimeoutForActiveSync() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -5423,10 +5425,10 @@ public class BassClientServiceTest { any(), any(), anyInt(), anyInt(), any(), any()); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // No BIG, SINK_UNINTENTIONAL checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); } private void sinkUnintentionalDuringScanning() { @@ -5436,10 +5438,10 @@ public class BassClientServiceTest { BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); injectRemoteSourceStateChanged(meta, false); checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // No BIG, SINK_UNINTENTIONAL checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); } private void sinkIntentionalWithoutScanning() { @@ -5454,12 +5456,12 @@ public class BassClientServiceTest { any(), any(), anyInt(), anyInt(), any(), any()); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // BIG, SINK_INTENTIONAL onPeriodicAdvertisingReport(); onBigInfoAdvertisingReport(); checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); } private void sinkIntentionalDuringScanning() { @@ -5469,12 +5471,12 @@ public class BassClientServiceTest { BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); injectRemoteSourceStateChanged(meta, false); checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // BIG, SINK_INTENTIONAL onPeriodicAdvertisingReport(); onBigInfoAdvertisingReport(); checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); } private void checkResumeSynchronizationByBig() { @@ -5524,18 +5526,20 @@ public class BassClientServiceTest { } private void verifyStopBigMonitoringWithUnsync() { - checkNoMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_START); checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_STOP); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerUnregisterSync(any(), any()); } private void verifyStopBigMonitoringWithoutUnsync() { - checkNoMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_START); checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_STOP); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -5562,9 +5566,10 @@ public class BassClientServiceTest { .verify(mMethodProxy, never()) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkNoMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_START); checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_STOP); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); } private void checkSinkPause() { @@ -5843,7 +5848,7 @@ public class BassClientServiceTest { (long) 0x00000000); } } - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Unsync all sinks cause stop monitoring for (BassClientStateMachine sm : mStateMachines.values()) { @@ -5885,7 +5890,7 @@ public class BassClientServiceTest { (long) 0x00000000); } } - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Unsync all sinks cause stop monitoring for (BassClientStateMachine sm : mStateMachines.values()) { @@ -5922,7 +5927,7 @@ public class BassClientServiceTest { mCurrentDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Disconnect all sinks cause stop monitoring doReturn(BluetoothProfile.STATE_DISCONNECTED) @@ -5954,7 +5959,7 @@ public class BassClientServiceTest { mCurrentDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Disconnect all sinks cause stop monitoring doReturn(BluetoothProfile.STATE_DISCONNECTED) @@ -5974,11 +5979,28 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkUnintentional_syncLost_withoutScanning() { + public void sinkUnintentional_syncLost_withoutScanning_outOfRange() { sinkUnintentionalWithoutScanning(); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + onSyncLost(); + checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + checkAndDispatchMessage( + BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); verifyStopBigMonitoringWithUnsync(); + verifyRemoveMessageAndInjectSourceRemoval(); checkNoResumeSynchronizationByBig(); } @@ -5987,11 +6009,56 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkUnintentional_syncLost_duringScanning() { + public void sinkUnintentional_syncLost_duringScanning_outOfRange() { sinkUnintentionalDuringScanning(); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + onSyncLost(); + checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + checkAndDispatchMessage( + BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); verifyStopBigMonitoringWithoutUnsync(); + verifyRemoveMessageAndInjectSourceRemoval(); + checkNoResumeSynchronizationByBig(); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void sinkUnintentional_bigMonitorTimeout_withoutScanning() { + sinkUnintentionalWithoutScanning(); + + checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + verifyStopBigMonitoringWithUnsync(); + verifyRemoveMessageAndInjectSourceRemoval(); + checkNoResumeSynchronizationByBig(); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void sinkUnintentional_bigMonitorTimeout_duringScanning() { + sinkUnintentionalDuringScanning(); + + checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + verifyStopBigMonitoringWithoutUnsync(); + verifyRemoveMessageAndInjectSourceRemoval(); checkNoResumeSynchronizationByBig(); } @@ -6348,7 +6415,7 @@ public class BassClientServiceTest { (long) 0x00000000); } } - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Unsync all sinks cause stop monitoring for (BassClientStateMachine sm : mStateMachines.values()) { @@ -6390,7 +6457,7 @@ public class BassClientServiceTest { (long) 0x00000000); } } - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Unsync all sinks cause stop monitoring for (BassClientStateMachine sm : mStateMachines.values()) { @@ -6427,7 +6494,7 @@ public class BassClientServiceTest { mCurrentDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Disconnect all sinks cause stop monitoring doReturn(BluetoothProfile.STATE_DISCONNECTED) @@ -6459,7 +6526,7 @@ public class BassClientServiceTest { mCurrentDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Disconnect all sinks cause stop monitoring doReturn(BluetoothProfile.STATE_DISCONNECTED) @@ -6479,10 +6546,26 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_syncLost_withoutScanning() { + public void sinkIntentional_syncLost_withoutScanning_outOfRange() { sinkIntentionalWithoutScanning(); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + onSyncLost(); + checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + checkAndDispatchMessage( + BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); verifyStopBigMonitoringWithUnsync(); checkNoResumeSynchronizationByBig(); } @@ -6492,10 +6575,52 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_syncLost_duringScanning() { + public void sinkIntentional_syncLost_duringScanning_outOfRange() { sinkIntentionalDuringScanning(); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + onSyncLost(); + checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + checkAndDispatchMessage( + BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + verifyStopBigMonitoringWithoutUnsync(); + checkNoResumeSynchronizationByBig(); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void sinkIntentional_bigMonitorTimeout_withoutScanning() { + sinkIntentionalWithoutScanning(); + + checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + verifyStopBigMonitoringWithUnsync(); + checkNoResumeSynchronizationByBig(); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void sinkIntentional_bigMonitorTimeout_duringScanning() { + sinkIntentionalDuringScanning(); + + checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); verifyStopBigMonitoringWithoutUnsync(); checkNoResumeSynchronizationByBig(); } @@ -6842,7 +6967,7 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void stopMonitoring_syncEstablishedFailed() { + public void outOfRange_syncEstablishedFailed_stopMonitoringAfterTimeout() { prepareSynchronizedPairAndStopSearching(); // Bis unsynced, SINK_UNKNOWN, verify broadcast sync and MESSAGE_BIG_CHECK_START @@ -6852,11 +6977,64 @@ public class BassClientServiceTest { .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); + checkMessage(BassClientService.MESSAGE_BIG_CHECK_START); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + checkAndDispatchMessage( + BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); verifyStopBigMonitoringWithUnsync(); } + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void outOfRange_syncEstablishedFailed_clearTimeout() { + prepareSynchronizedPairAndStopSearching(); + + // Bis unsynced, SINK_UNKNOWN, verify broadcast sync and MESSAGE_BIG_CHECK_START + BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); + injectRemoteSourceStateChanged(meta, false); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + checkMessage(BassClientService.MESSAGE_BIG_CHECK_START); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + + onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + } + @Test @EnableFlags({ Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, -- GitLab From b08f8c0e2700d6166cce4df6bf62367c97be346f Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Fri, 6 Sep 2024 14:36:58 +0000 Subject: [PATCH 191/875] Bass: Broadcast resync helper, simplified sink pause detection Removed SINK_UNKNOWN and SINK_INTENTIONAL. SINK_UNINTENTIONAL set immediately when PA and BIS are unsynced. Bug: 363950680 Bug: 363168099 Test: atest BassClientServiceTest Change-Id: I95176393141dc0aa8b1dfd01ba20d90bdf9be160 --- .../bass_client/BassClientService.java | 106 +-- .../bass_client/BassClientServiceTest.java | 901 +++--------------- 2 files changed, 159 insertions(+), 848 deletions(-) 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 772b295ca12..14515521341 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -124,9 +124,7 @@ public class BassClientService extends ProfileService { @VisibleForTesting static final int MESSAGE_SYNC_TIMEOUT = 1; @VisibleForTesting static final int MESSAGE_BIG_MONITOR_TIMEOUT = 2; - @VisibleForTesting static final int MESSAGE_BIG_CHECK_START = 3; - @VisibleForTesting static final int MESSAGE_BIG_CHECK_STOP = 4; - @VisibleForTesting static final int MESSAGE_BROADCAST_MONITOR_TIMEOUT = 5; + @VisibleForTesting static final int MESSAGE_BROADCAST_MONITOR_TIMEOUT = 3; /* 1 minute timeout for primary device reconnection in Private Broadcast case */ private static final int DIALING_OUT_TIMEOUT_MS = 60000; @@ -134,12 +132,6 @@ public class BassClientService extends ProfileService { // 30 secs timeout for keeping PSYNC active when searching is stopped private static final Duration sSyncActiveTimeout = Duration.ofSeconds(30); - // 6 seconds to start BIG check. It has to be greater than kPeriodicSyncTimeout - private static final Duration sBigCheckStart = Duration.ofSeconds(6); - - // 2 seconds for check if BIG exist - private static final Duration sBigCheckStop = Duration.ofSeconds(2); - // 30 minutes timeout for monitoring BIG resynchronization private static final Duration sBigMonitorTimeout = Duration.ofMinutes(30); @@ -148,8 +140,6 @@ public class BassClientService extends ProfileService { private enum PauseType { HOST_INTENTIONAL, - SINK_UNKNOWN, - SINK_INTENTIONAL, SINK_UNINTENTIONAL } @@ -176,7 +166,6 @@ public class BassClientService extends ProfileService { private final Map mBroadcastMetadataMap = new ConcurrentHashMap<>(); private final HashSet mPausedBroadcastSinks = new HashSet<>(); - private final HashSet mBigInfoReportExistForBroadcast = new HashSet<>(); private final Map mPausedBroadcastIds = new HashMap<>(); private final Deque mPendingAddSources = new ArrayDeque<>(); private final Map> mLocalBroadcastReceivers = @@ -246,11 +235,7 @@ public class BassClientService extends ProfileService { { log("MESSAGE_BIG_MONITOR_TIMEOUT"); int broadcastId = msg.arg1; - if (isSinkUnintentionalPauseType(broadcastId)) { - stopSourceReceivers(broadcastId); - } else { - stopBigMonitoring(broadcastId, false); - } + stopSourceReceivers(broadcastId); synchronized (mSearchScanCallbackLock) { // when searching is stopped then clear all sync data if (mSearchScanCallback == null) { @@ -259,33 +244,6 @@ public class BassClientService extends ProfileService { } break; } - case MESSAGE_BIG_CHECK_START: - { - log("MESSAGE_BIG_CHECK_START"); - int broadcastId = msg.arg1; - mBigInfoReportExistForBroadcast.remove(broadcastId); - mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); - Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_CHECK_STOP); - newMsg.arg1 = broadcastId; - log("Started MESSAGE_BIG_CHECK_STOP"); - mHandler.sendMessageDelayed(newMsg, sBigCheckStop.toMillis()); - break; - } - case MESSAGE_BIG_CHECK_STOP: - { - log("MESSAGE_BIG_CHECK_STOP"); - int broadcastId = msg.arg1; - if (mBigInfoReportExistForBroadcast.contains(broadcastId)) { - mPausedBroadcastIds.put( - broadcastId, PauseType.SINK_INTENTIONAL); - logPausedBroadcastsAndSinks(); - } else { - mPausedBroadcastIds.put( - broadcastId, PauseType.SINK_UNINTENTIONAL); - cacheSuspendingSources(broadcastId); - } - break; - } default: break; } @@ -1064,32 +1022,32 @@ public class BassClientService extends ProfileService { && !isLocalBroadcast(receiveState) && !isEmptyBluetoothDevice(receiveState.getSourceDevice()) && !isHostPauseType(broadcastId)) { - boolean isPlaying = false; - for (int i = 0; i < receiveState.getNumSubgroups(); i++) { - Long syncState = receiveState.getBisSyncState().get(i); - /* Synced to BIS */ - if (syncState != BassConstants.BIS_SYNC_NOT_SYNC_TO_BIS - && syncState != BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG) { - isPlaying = true; - break; + boolean isReadyToAutoResync = false; + if (receiveState.getPaSyncState() + == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED) { + isReadyToAutoResync = true; + } else { + for (int i = 0; i < receiveState.getNumSubgroups(); i++) { + Long syncState = receiveState.getBisSyncState().get(i); + /* Synced to BIS */ + if (syncState != BassConstants.BIS_SYNC_NOT_SYNC_TO_BIS + && syncState != BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG) { + isReadyToAutoResync = true; + break; + } } } - if (isPlaying) { + if (isReadyToAutoResync) { stopBigMonitoring(broadcastId, false); } else if (!mPausedBroadcastIds.containsKey(broadcastId)) { if (mCachedBroadcasts.containsKey(broadcastId)) { addSelectSourceRequest(broadcastId, true); - mPausedBroadcastIds.put(broadcastId, PauseType.SINK_UNKNOWN); - logPausedBroadcastsAndSinks(); - mHandler.removeMessages(MESSAGE_BIG_CHECK_START); - Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_CHECK_START); - newMsg.arg1 = broadcastId; - log("Started MESSAGE_BIG_CHECK_START"); - mHandler.sendMessageDelayed(newMsg, sBigCheckStart.toMillis()); + mPausedBroadcastIds.put(broadcastId, PauseType.SINK_UNINTENTIONAL); + cacheSuspendingSources(broadcastId); mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - newMsg = mHandler.obtainMessage(MESSAGE_BIG_MONITOR_TIMEOUT); + Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_MONITOR_TIMEOUT); newMsg.arg1 = broadcastId; log("Started MESSAGE_BIG_MONITOR_TIMEOUT"); mHandler.sendMessageDelayed(newMsg, sBigMonitorTimeout.toMillis()); @@ -1119,7 +1077,7 @@ public class BassClientService extends ProfileService { /* Assistant become inactive */ if (mIsAssistantActive && mPausedBroadcastSinks.isEmpty() - && !isAnySinkPauseType(broadcastId)) { + && !isSinkUnintentionalPauseType(broadcastId)) { mIsAssistantActive = false; mUnicastSourceStreamStatus = Optional.empty(); leAudioService.activeBroadcastAssistantNotification(false); @@ -2146,7 +2104,7 @@ public class BassClientService extends ProfileService { int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1; mSyncFailureCounter.put(broadcastId, failsCounter); } - if (isAnySinkPauseType(broadcastId)) { + if (isSinkUnintentionalPauseType(broadcastId)) { if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT); newMsg.arg1 = broadcastId; @@ -2230,7 +2188,7 @@ public class BassClientService extends ProfileService { int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1; mSyncFailureCounter.put(broadcastId, failsCounter); } - if (isAnySinkPauseType(broadcastId)) { + if (isSinkUnintentionalPauseType(broadcastId)) { if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT); newMsg.arg1 = broadcastId; @@ -2285,11 +2243,8 @@ public class BassClientService extends ProfileService { log("Notify broadcast source found"); mCallbacks.notifySourceFound(metaData); } - if (mPausedBroadcastIds.containsKey(broadcastId)) { - mBigInfoReportExistForBroadcast.add(broadcastId); - if (mPausedBroadcastIds.get(broadcastId).equals(PauseType.SINK_UNINTENTIONAL)) { - resumeReceiversSourceSynchronization(); - } + if (isSinkUnintentionalPauseType(broadcastId)) { + resumeReceiversSourceSynchronization(); } } @@ -3280,7 +3235,7 @@ public class BassClientService extends ProfileService { } if (!mPausedBroadcastSinks.contains(device) - || isAnySinkPauseType(receiveState.getBroadcastId())) { + || isSinkUnintentionalPauseType(receiveState.getBroadcastId())) { // Remove device if not paused yet sourcesToRemove.put(device, receiveState.getSourceId()); } @@ -3482,11 +3437,6 @@ public class BassClientService extends ProfileService { + mPausedBroadcastSinks); } - private boolean isAnySinkPauseType(int broadcastId) { - return (mPausedBroadcastIds.containsKey(broadcastId) - && !mPausedBroadcastIds.get(broadcastId).equals(PauseType.HOST_INTENTIONAL)); - } - private boolean isHostPauseType(int broadcastId) { return (mPausedBroadcastIds.containsKey(broadcastId) && mPausedBroadcastIds.get(broadcastId).equals(PauseType.HOST_INTENTIONAL)); @@ -3503,8 +3453,6 @@ public class BassClientService extends ProfileService { } log("stopBigMonitoring"); mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - mHandler.removeMessages(MESSAGE_BIG_CHECK_START); - mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); mPausedBroadcastSinks.clear(); @@ -3533,8 +3481,6 @@ public class BassClientService extends ProfileService { int pausedBroadcastId = iterator.next(); if (!isAnyReceiverSyncedToBroadcast(pausedBroadcastId)) { mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - mHandler.removeMessages(MESSAGE_BIG_CHECK_START); - mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); iterator.remove(); synchronized (mSearchScanCallbackLock) { @@ -3554,8 +3500,6 @@ public class BassClientService extends ProfileService { } log("stopBigMonitoring broadcastId: " + broadcastId + ", hostInitiated: " + hostInitiated); mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - mHandler.removeMessages(MESSAGE_BIG_CHECK_START); - mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP); mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); if (hostInitiated) { mPausedBroadcastIds.put(broadcastId, PauseType.HOST_INTENTIONAL); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 897515a3036..58aa3320e60 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -1514,65 +1514,37 @@ public class BassClientServiceTest { } private void injectRemoteSourceStateChanged( - BluetoothLeBroadcastMetadata meta, boolean isBisSynced) { + BluetoothLeBroadcastMetadata meta, boolean isPaSynced, boolean isBisSynced) { for (BassClientStateMachine sm : mStateMachines.values()) { // Update receiver state if (sm.getDevice().equals(mCurrentDevice)) { - if (isBisSynced) { - injectRemoteSourceStateChanged( - sm, - meta, - TEST_SOURCE_ID, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - meta.isEncrypted() - ? BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_DECRYPTING - : BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000001); - } else { - injectRemoteSourceStateChanged( - sm, - meta, - TEST_SOURCE_ID, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - meta.isEncrypted() - ? BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_DECRYPTING - : BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000000); - } + injectRemoteSourceStateChanged( + sm, + meta, + TEST_SOURCE_ID, + isPaSynced + ? BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED + : BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState + .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null, + isBisSynced ? (long) 0x00000001 : (long) 0x00000000); } else if (sm.getDevice().equals(mCurrentDevice1)) { - if (isBisSynced) { - injectRemoteSourceStateChanged( - sm, - meta, - TEST_SOURCE_ID + 1, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - meta.isEncrypted() - ? BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_DECRYPTING - : BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000002); - } else { - injectRemoteSourceStateChanged( - sm, - meta, - TEST_SOURCE_ID + 1, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - meta.isEncrypted() - ? BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_DECRYPTING - : BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000000); - } + injectRemoteSourceStateChanged( + sm, + meta, + TEST_SOURCE_ID + 1, + isPaSynced + ? BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED + : BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState + .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null, + isBisSynced ? (long) 0x00000002 : (long) 0x00000000); } } } @@ -1608,7 +1580,8 @@ public class BassClientServiceTest { TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); } - private void prepareRemoteSourceState(BluetoothLeBroadcastMetadata meta, boolean isBisSynced) { + private void prepareRemoteSourceState( + BluetoothLeBroadcastMetadata meta, boolean isPaSynced, boolean isBisSynced) { for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { injectRemoteSourceStateSourceAdded( @@ -1634,7 +1607,7 @@ public class BassClientServiceTest { null); } } - injectRemoteSourceStateChanged(meta, isBisSynced); + injectRemoteSourceStateChanged(meta, isPaSynced, isBisSynced); } /** @@ -1719,7 +1692,7 @@ public class BassClientServiceTest { onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, false); + prepareRemoteSourceState(meta, true, false); // Update broadcast source using other member of the same group BluetoothLeBroadcastMetadata metaUpdate = @@ -1762,7 +1735,7 @@ public class BassClientServiceTest { onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, false); + prepareRemoteSourceState(meta, true, false); // Remove broadcast source using other member of the same group mBassClientService.removeSource(mCurrentDevice1, TEST_SOURCE_ID + 1); @@ -1904,7 +1877,7 @@ public class BassClientServiceTest { onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, false); + prepareRemoteSourceState(meta, true, false); // Remove broadcast source mBassClientService.removeSource(mCurrentDevice, TEST_SOURCE_ID); @@ -1947,7 +1920,7 @@ public class BassClientServiceTest { BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); BluetoothLeBroadcastMetadata newMeta = createBroadcastMetadata(TEST_BROADCAST_ID + 1); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, true); + prepareRemoteSourceState(meta, true, true); // Add another new broadcast source onScanResult(mSourceDevice2, TEST_BROADCAST_ID + 1); @@ -2035,7 +2008,7 @@ public class BassClientServiceTest { onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); verifyAddSourceForGroup(meta); assertThat(mStateMachines.size()).isEqualTo(2); - prepareRemoteSourceState(meta, true); + prepareRemoteSourceState(meta, true, true); // Add another broadcast source BluetoothLeBroadcastMetadata meta1 = @@ -2200,7 +2173,7 @@ public class BassClientServiceTest { // Prepare valid source for group BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, false); + prepareRemoteSourceState(meta, true, false); // Verify errors are reported for the entire group mBassClientService.modifySource(mCurrentDevice, TEST_SOURCE_ID, null); @@ -2916,7 +2889,7 @@ public class BassClientServiceTest { // Add source 1 BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(broadcastId1); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, true); + prepareRemoteSourceState(meta, true, true); // Scan 5 cause removing first element which is not synced to any sink onScanResult(device5, broadcastId5); @@ -4052,7 +4025,12 @@ public class BassClientServiceTest { || ((m.what == BassClientStateMachine .ADD_BCAST_SOURCE) - && (m.obj.equals(meta)))) + && (m.obj.equals(meta))) + || ((m.what + == BassClientStateMachine + .SWITCH_BCAST_SOURCE) + && (m.obj.equals(meta)) + && (m.arg1 == TEST_SOURCE_ID))) .count(); assertThat(count).isEqualTo(1); } else if (sm.getDevice().equals(mCurrentDevice1)) { @@ -4071,7 +4049,12 @@ public class BassClientServiceTest { || ((m.what == BassClientStateMachine .ADD_BCAST_SOURCE) - && (m.obj.equals(meta)))) + && (m.obj.equals(meta))) + || ((m.what + == BassClientStateMachine + .SWITCH_BCAST_SOURCE) + && (m.obj.equals(meta)) + && (m.arg1 == TEST_SOURCE_ID + 1))) .count(); assertThat(count).isEqualTo(1); } @@ -4086,18 +4069,18 @@ public class BassClientServiceTest { onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, false); + prepareRemoteSourceState(meta, true, false); if (Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - injectRemoteSourceStateChanged(meta, true); + injectRemoteSourceStateChanged(meta, true, true); verify(mLeAudioService).activeBroadcastAssistantNotification(eq(true)); Mockito.clearInvocations(mLeAudioService); + /* Imitate broadcast source stop, sink notify about loosing BIS sync */ + injectRemoteSourceStateChanged(meta, true, false); + /* Unicast would like to stream */ mBassClientService.cacheSuspendingSources(TEST_BROADCAST_ID); - - /* Imitate broadcast source stop, sink notify about loosing BIS sync */ - injectRemoteSourceStateChanged(meta, false); } else { mBassClientService.suspendAllReceiversSourceSynchronization(); verifyRemoveMessageAndInjectSourceRemoval(); @@ -4122,7 +4105,7 @@ public class BassClientServiceTest { .getAllBroadcastMetadata(); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, true); + prepareRemoteSourceState(meta, true, true); verify(mLeAudioService).activeBroadcastAssistantNotification(eq(true)); @@ -4132,7 +4115,7 @@ public class BassClientServiceTest { if (Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { /* Imitate broadcast source stop, sink notify about loosing BIS sync */ - injectRemoteSourceStateChanged(meta, false); + injectRemoteSourceStateChanged(meta, true, false); } else { verifyRemoveMessageAndInjectSourceRemoval(); } @@ -4144,7 +4127,7 @@ public class BassClientServiceTest { verifyAllGroupMembersGettingUpdateOrAddSource(meta); // Update receiver state with lost BIS sync - injectRemoteSourceStateChanged(meta, false); + injectRemoteSourceStateChanged(meta, true, false); if (!Flags.leaudioBroadcastResyncHelper()) { verify(mLeAudioService).activeBroadcastAssistantNotification(eq(false)); } @@ -4165,7 +4148,7 @@ public class BassClientServiceTest { .getAllBroadcastMetadata(); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, true); + prepareRemoteSourceState(meta, true, true); verify(mLeAudioService).activeBroadcastAssistantNotification(eq(true)); @@ -4224,14 +4207,14 @@ public class BassClientServiceTest { onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, false); + prepareRemoteSourceState(meta, true, false); List devices = mBassClientService.getConnectedDevices(); // Verify isAnyReceiverReceivingBroadcast returns false if no BIS synced assertThat(mBassClientService.isAnyReceiverReceivingBroadcast(devices)).isFalse(); // Update receiver state with BIS sync - injectRemoteSourceStateChanged(meta, true); + injectRemoteSourceStateChanged(meta, true, true); BluetoothDevice invalidDevice = TestUtils.getTestDevice(mBluetoothAdapter, 2); // Verify isAnyReceiverReceivingBroadcast returns false if invalid device expect.that(mBassClientService.isAnyReceiverReceivingBroadcast(List.of(invalidDevice))) @@ -4250,13 +4233,13 @@ public class BassClientServiceTest { BluetoothLeBroadcastMetadata metaNoBroadcast = createEmptyBroadcastMetadata(); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(metaNoBroadcast, false); + prepareRemoteSourceState(metaNoBroadcast, true, false); // Verify getSyncedBroadcastSinks returns empty device list if no broadcst ID assertThat(mBassClientService.getSyncedBroadcastSinks().isEmpty()).isTrue(); // Update receiver state with broadcast ID - injectRemoteSourceStateChanged(meta, false); + injectRemoteSourceStateChanged(meta, true, false); List activeSinks = mBassClientService.getSyncedBroadcastSinks(); if (Flags.leaudioBigDependsOnAudioState()) { @@ -4270,7 +4253,7 @@ public class BassClientServiceTest { } // Update receiver state with BIS sync - injectRemoteSourceStateChanged(meta, true); + injectRemoteSourceStateChanged(meta, true, true); // Verify getSyncedBroadcastSinks returns correct device list if BIS synced activeSinks = mBassClientService.getSyncedBroadcastSinks(); @@ -5399,7 +5382,7 @@ public class BassClientServiceTest { verifyAddSourceForGroup(meta); // Bis syned - prepareRemoteSourceState(meta, true); + prepareRemoteSourceState(meta, true, true); verify(mLeAudioService).activeBroadcastAssistantNotification(eq(true)); } @@ -5416,67 +5399,24 @@ public class BassClientServiceTest { private void sinkUnintentionalWithoutScanning() { prepareSynchronizedPairAndStopSearching(); - // Bis unsynced, SINK_UNKNOWN, verify broadcast sync and MESSAGE_BIG_CHECK_START + // Bis and PA unsynced, SINK_UNINTENTIONAL BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); + injectRemoteSourceStateChanged(meta, false, false); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - - // No BIG, SINK_UNINTENTIONAL - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); } private void sinkUnintentionalDuringScanning() { prepareSynchronizedPair(); - // Bis unsynced, SINK_UNKNOWN, verify MESSAGE_BIG_CHECK_START - BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - - // No BIG, SINK_UNINTENTIONAL - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); - } - - private void sinkIntentionalWithoutScanning() { - prepareSynchronizedPairAndStopSearching(); - - // Bis unsynced, SINK_UNKNOWN, verify broadcast sync and MESSAGE_BIG_CHECK_START - BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerRegisterSync( - any(), any(), anyInt(), anyInt(), any(), any()); - onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - - // BIG, SINK_INTENTIONAL - onPeriodicAdvertisingReport(); - onBigInfoAdvertisingReport(); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); - } - - private void sinkIntentionalDuringScanning() { - prepareSynchronizedPair(); - - // Bis unsynced, SINK_UNKNOWN, verify MESSAGE_BIG_CHECK_START + // Bis and PA unsynced, SINK_UNINTENTIONAL BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_START, TEST_BROADCAST_ID); + injectRemoteSourceStateChanged(meta, false, false); checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - - // BIG, SINK_INTENTIONAL - onPeriodicAdvertisingReport(); - onBigInfoAdvertisingReport(); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_CHECK_STOP, TEST_BROADCAST_ID); } private void checkResumeSynchronizationByBig() { @@ -5527,8 +5467,6 @@ public class BassClientServiceTest { private void verifyStopBigMonitoringWithUnsync() { checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_START); - checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_STOP); checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy) @@ -5537,8 +5475,6 @@ public class BassClientServiceTest { private void verifyStopBigMonitoringWithoutUnsync() { checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_START); - checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_STOP); checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy, never()) @@ -5548,34 +5484,32 @@ public class BassClientServiceTest { private void resyncAndVerifyWithUnsync() { // Resync, verify stopBigMonitoring with broadcast unsync BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, true); + injectRemoteSourceStateChanged(meta, true, true); verifyStopBigMonitoringWithUnsync(); } private void resyncAndVerifyWithoutUnsync() { // Resync, verify stopBigMonitoring without broadcast unsync BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, true); + injectRemoteSourceStateChanged(meta, true, true); verifyStopBigMonitoringWithoutUnsync(); } private void checkNoSinkPause() { BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); + injectRemoteSourceStateChanged(meta, false, false); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_START); - checkNoMessage(BassClientService.MESSAGE_BIG_CHECK_STOP); checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); } private void checkSinkPause() { BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); - checkMessage(BassClientService.MESSAGE_BIG_CHECK_START); + injectRemoteSourceStateChanged(meta, false, false); + checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); } @Test @@ -5842,7 +5776,7 @@ public class BassClientServiceTest { sm, createEmptyBroadcastMetadata(), TEST_SOURCE_ID, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); @@ -5858,7 +5792,7 @@ public class BassClientServiceTest { sm, createEmptyBroadcastMetadata(), TEST_SOURCE_ID + 1, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); @@ -5884,7 +5818,7 @@ public class BassClientServiceTest { sm, createEmptyBroadcastMetadata(), TEST_SOURCE_ID, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); @@ -5900,7 +5834,7 @@ public class BassClientServiceTest { sm, createEmptyBroadcastMetadata(), TEST_SOURCE_ID + 1, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); @@ -6172,72 +6106,18 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_resyncByRemote_withoutScanning() { - sinkIntentionalWithoutScanning(); - - checkNoResumeSynchronizationByBig(); - resyncAndVerifyWithUnsync(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_resyncByRemote_duringScanning() { - sinkIntentionalDuringScanning(); - - checkNoResumeSynchronizationByBig(); - resyncAndVerifyWithoutUnsync(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_addNewSource() { - sinkIntentionalDuringScanning(); - - // Scan and sync second broadcast - onScanResult(mSourceDevice2, TEST_BROADCAST_ID + 1); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerRegisterSync( - any(), any(), anyInt(), anyInt(), any(), any()); - onSyncEstablished(mSourceDevice2, TEST_SYNC_HANDLE + 1); - - // Add second source, HOST_INTENTIONAL - BluetoothLeBroadcastMetadata.Builder builder = - new BluetoothLeBroadcastMetadata.Builder() - .setEncrypted(false) - .setSourceDevice(mSourceDevice2, BluetoothDevice.ADDRESS_TYPE_RANDOM) - .setSourceAdvertisingSid(TEST_ADVERTISER_SID) - .setBroadcastId(TEST_BROADCAST_ID + 1) - .setBroadcastCode(null) - .setPaSyncInterval(TEST_PA_SYNC_INTERVAL) - .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS); - // builder expect at least one subgroup - builder.addSubgroup(createBroadcastSubgroup()); - BluetoothLeBroadcastMetadata meta2 = builder.build(); - mBassClientService.addSource(mCurrentDevice, meta2, true); - verifyStopBigMonitoringWithoutUnsync(); - - // BIG for first broadcast not cause resume synchronization - checkNoResumeSynchronizationByBig(); - } + public void hostIntentional_addSameSource() { + prepareSynchronizedPair(); - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_addSameSource() { - sinkIntentionalDuringScanning(); + // Remove source, HOST_INTENTIONAL + mBassClientService.removeSource(mCurrentDevice, TEST_SOURCE_ID); + checkNoSinkPause(); + verifyRemoveMessageAndInjectSourceRemoval(); - // Verify add source clear the SINK_UNINTENTIONAL + // Verify add source clear the HOST_INTENTIONAL BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); mBassClientService.addSource(mCurrentDevice, meta, true); + verifyAddSourceForGroup(meta); checkSinkPause(); } @@ -6246,14 +6126,13 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_removeSource_withoutScanning() { - sinkIntentionalWithoutScanning(); + public void hostIntentional_removeSource_withoutScanning() { + prepareSynchronizedPairAndStopSearching(); // Remove source, HOST_INTENTIONAL mBassClientService.removeSource(mCurrentDevice, TEST_SOURCE_ID); - verifyStopBigMonitoringWithUnsync(); + checkNoSinkPause(); verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); } @Test @@ -6261,14 +6140,13 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_removeSource_duringScanning() { - sinkIntentionalDuringScanning(); + public void hostIntentional_removeSource_duringScanning() { + prepareSynchronizedPair(); // Remove source, HOST_INTENTIONAL mBassClientService.removeSource(mCurrentDevice, TEST_SOURCE_ID); - verifyStopBigMonitoringWithoutUnsync(); + checkNoSinkPause(); verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); } @Test @@ -6276,15 +6154,13 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_stopReceivers_withoutScanning() { - sinkIntentionalWithoutScanning(); + public void hostIntentional_stopReceivers_withoutScanning() { + prepareSynchronizedPairAndStopSearching(); // Stop receivers, HOST_INTENTIONAL mBassClientService.stopReceiversSourceSynchronization(TEST_BROADCAST_ID); - verifyStopBigMonitoringWithUnsync(); + checkNoSinkPause(); verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); - checkNoResumeSynchronizationByHost(); } @Test @@ -6292,15 +6168,13 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_stopReceivers_duringScanning() { - sinkIntentionalDuringScanning(); + public void hostIntentional_stopReceivers_duringScanning() { + prepareSynchronizedPair(); // Stop receivers, HOST_INTENTIONAL mBassClientService.stopReceiversSourceSynchronization(TEST_BROADCAST_ID); - verifyStopBigMonitoringWithoutUnsync(); + checkNoSinkPause(); verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); - checkNoResumeSynchronizationByHost(); } @Test @@ -6308,14 +6182,15 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_suspendReceivers_withoutScanning() { - sinkIntentionalWithoutScanning(); + public void hostIntentional_suspendReceivers_withoutScanning() { + prepareSynchronizedPairAndStopSearching(); // Suspend receivers, HOST_INTENTIONAL mBassClientService.suspendReceiversSourceSynchronization(TEST_BROADCAST_ID); - verifyStopBigMonitoringWithUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); + checkNoSinkPause(); + if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { + verifyRemoveMessageAndInjectSourceRemoval(); + } checkResumeSynchronizationByHost(); } @@ -6324,14 +6199,15 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_suspendReceivers_duringScanning() { - sinkIntentionalDuringScanning(); + public void hostIntentional_suspendReceivers_duringScanning() { + prepareSynchronizedPair(); // Suspend receivers, HOST_INTENTIONAL mBassClientService.suspendReceiversSourceSynchronization(TEST_BROADCAST_ID); - verifyStopBigMonitoringWithoutUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); + checkNoSinkPause(); + if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { + verifyRemoveMessageAndInjectSourceRemoval(); + } checkResumeSynchronizationByHost(); } @@ -6340,14 +6216,15 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_suspendAllReceivers_withoutScanning() { - sinkIntentionalWithoutScanning(); + public void hostIntentional_suspendAllReceivers_withoutScanning() { + prepareSynchronizedPairAndStopSearching(); // Suspend all receivers, HOST_INTENTIONAL mBassClientService.suspendAllReceiversSourceSynchronization(); - verifyStopBigMonitoringWithUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); + checkNoSinkPause(); + if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { + verifyRemoveMessageAndInjectSourceRemoval(); + } checkResumeSynchronizationByHost(); } @@ -6356,14 +6233,15 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_suspendAllReceivers_duringScanning() { - sinkIntentionalDuringScanning(); + public void hostIntentional_suspendAllReceivers_duringScanning() { + prepareSynchronizedPair(); // Suspend all receivers, HOST_INTENTIONAL mBassClientService.suspendAllReceiversSourceSynchronization(); - verifyStopBigMonitoringWithoutUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); + checkNoSinkPause(); + if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { + verifyRemoveMessageAndInjectSourceRemoval(); + } checkResumeSynchronizationByHost(); } @@ -6372,530 +6250,21 @@ public class BassClientServiceTest { Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE }) - public void sinkIntentional_publicStopBigMonitoring_withoutScanning() { - sinkIntentionalWithoutScanning(); - - mBassClientService.stopBigMonitoring(); - verifyStopBigMonitoringWithUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_publicStopBigMonitoring_duringScanning() { - sinkIntentionalDuringScanning(); - - mBassClientService.stopBigMonitoring(); - verifyStopBigMonitoringWithoutUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_unsync_withoutScanning() { - sinkIntentionalWithoutScanning(); - - // Unsync not all sinks not cause stop monitoring - for (BassClientStateMachine sm : mStateMachines.values()) { - // Update receiver state - if (sm.getDevice().equals(mCurrentDevice)) { - injectRemoteSourceStateChanged( - sm, - createEmptyBroadcastMetadata(), - TEST_SOURCE_ID, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000000); - } - } - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + public void hostIntentional_handleUnicastSourceStreamStatusChange_withoutScanning() { + prepareSynchronizedPairAndStopSearching(); - // Unsync all sinks cause stop monitoring - for (BassClientStateMachine sm : mStateMachines.values()) { - // Update receiver state - if (sm.getDevice().equals(mCurrentDevice1)) { - injectRemoteSourceStateChanged( - sm, - createEmptyBroadcastMetadata(), - TEST_SOURCE_ID + 1, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000000); - } + /* Unicast would like to stream */ + mBassClientService.handleUnicastSourceStreamStatusChange( + 0 /* STATUS_LOCAL_STREAM_REQUESTED */); + checkNoSinkPause(); + if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { + verifyRemoveMessageAndInjectSourceRemoval(); } - verifyStopBigMonitoringWithUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_unsync_duringScanning() { - sinkIntentionalDuringScanning(); - - // Unsync not all sinks not cause stop monitoring - for (BassClientStateMachine sm : mStateMachines.values()) { - // Update receiver state - if (sm.getDevice().equals(mCurrentDevice)) { - injectRemoteSourceStateChanged( - sm, - createEmptyBroadcastMetadata(), - TEST_SOURCE_ID, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000000); - } - } - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - - // Unsync all sinks cause stop monitoring - for (BassClientStateMachine sm : mStateMachines.values()) { - // Update receiver state - if (sm.getDevice().equals(mCurrentDevice1)) { - injectRemoteSourceStateChanged( - sm, - createEmptyBroadcastMetadata(), - TEST_SOURCE_ID + 1, - BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, - BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - (long) 0x00000000); - } - } - verifyStopBigMonitoringWithoutUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_disconnect_withoutScanning() { - sinkIntentionalWithoutScanning(); - - // Disconnect not all sinks not cause stop monitoring - doReturn(BluetoothProfile.STATE_DISCONNECTED) - .when(mStateMachines.get(mCurrentDevice)) - .getConnectionState(); - doReturn(false).when(mStateMachines.get(mCurrentDevice)).isConnected(); - mBassClientService.connectionStateChanged( - mCurrentDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - - // Disconnect all sinks cause stop monitoring - doReturn(BluetoothProfile.STATE_DISCONNECTED) - .when(mStateMachines.get(mCurrentDevice1)) - .getConnectionState(); - doReturn(false).when(mStateMachines.get(mCurrentDevice1)).isConnected(); - mBassClientService.connectionStateChanged( - mCurrentDevice1, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTED); - verifyStopBigMonitoringWithUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_disconnect_duringScanning() { - sinkIntentionalDuringScanning(); - - // Disconnect not all sinks not cause stop monitoring - doReturn(BluetoothProfile.STATE_DISCONNECTED) - .when(mStateMachines.get(mCurrentDevice)) - .getConnectionState(); - doReturn(false).when(mStateMachines.get(mCurrentDevice)).isConnected(); - mBassClientService.connectionStateChanged( - mCurrentDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - - // Disconnect all sinks cause stop monitoring - doReturn(BluetoothProfile.STATE_DISCONNECTED) - .when(mStateMachines.get(mCurrentDevice1)) - .getConnectionState(); - doReturn(false).when(mStateMachines.get(mCurrentDevice1)).isConnected(); - mBassClientService.connectionStateChanged( - mCurrentDevice1, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTED); - verifyStopBigMonitoringWithoutUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_syncLost_withoutScanning_outOfRange() { - sinkIntentionalWithoutScanning(); - - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); - - onSyncLost(); - checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerRegisterSync( - any(), any(), anyInt(), anyInt(), any(), any()); - - onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerRegisterSync( - any(), any(), anyInt(), anyInt(), any(), any()); - - checkAndDispatchMessage( - BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); - verifyStopBigMonitoringWithUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_syncLost_duringScanning_outOfRange() { - sinkIntentionalDuringScanning(); - - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); - - onSyncLost(); - checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerRegisterSync( - any(), any(), anyInt(), anyInt(), any(), any()); - - onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerRegisterSync( - any(), any(), anyInt(), anyInt(), any(), any()); - - checkAndDispatchMessage( - BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); - verifyStopBigMonitoringWithoutUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_bigMonitorTimeout_withoutScanning() { - sinkIntentionalWithoutScanning(); - - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); - verifyStopBigMonitoringWithUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_bigMonitorTimeout_duringScanning() { - sinkIntentionalDuringScanning(); - - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); - verifyStopBigMonitoringWithoutUnsync(); - checkNoResumeSynchronizationByBig(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_handleUnicastSourceStreamStatusChange_withoutScanning() { - sinkIntentionalWithoutScanning(); - - /* Unicast would like to stream */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 0 /* STATUS_LOCAL_STREAM_REQUESTED */); - verifyStopBigMonitoringWithUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); - - /* Unicast finished streaming */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); - onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - verifyAllGroupMembersGettingUpdateOrAddSource(createBroadcastMetadata(TEST_BROADCAST_ID)); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_handleUnicastSourceStreamStatusChange_duringScanning() { - sinkIntentionalDuringScanning(); - - /* Unicast would like to stream */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 0 /* STATUS_LOCAL_STREAM_REQUESTED */); - verifyStopBigMonitoringWithoutUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); /* Unicast finished streaming */ mBassClientService.handleUnicastSourceStreamStatusChange( 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); - verifyAllGroupMembersGettingUpdateOrAddSource(createBroadcastMetadata(TEST_BROADCAST_ID)); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_handleUnicastSourceStreamStatusChangeNoContext_withoutScanning() { - sinkIntentionalWithoutScanning(); - - /* Unicast would like to stream */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); - verifyStopBigMonitoringWithUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); - - /* Unicast finished streaming */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); - onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - verifyAllGroupMembersGettingUpdateOrAddSource(createBroadcastMetadata(TEST_BROADCAST_ID)); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_handleUnicastSourceStreamStatusChangeNoContext_duringScanning() { - sinkIntentionalDuringScanning(); - - /* Unicast would like to stream */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); - verifyStopBigMonitoringWithoutUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); - checkNoResumeSynchronizationByBig(); - - /* Unicast finished streaming */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); - verifyAllGroupMembersGettingUpdateOrAddSource(createBroadcastMetadata(TEST_BROADCAST_ID)); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void sinkIntentional_autoSyncToBroadcast_onStopSearching() { - sinkUnintentionalDuringScanning(); - - // Verify that start searching cause sync when broadcaster synced to sinks - mBassClientService.stopSearchingForSources(); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerUnregisterSync(any(), any()); - mInOrderMethodProxy - .verify(mMethodProxy) - .periodicAdvertisingManagerRegisterSync( - any(), any(), anyInt(), anyInt(), any(), any()); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_addSameSource() { - prepareSynchronizedPair(); - - // Remove source, HOST_INTENTIONAL - mBassClientService.removeSource(mCurrentDevice, TEST_SOURCE_ID); - checkNoSinkPause(); - verifyRemoveMessageAndInjectSourceRemoval(); - - // Verify add source clear the HOST_INTENTIONAL - BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - mBassClientService.addSource(mCurrentDevice, meta, true); - verifyAddSourceForGroup(meta); - checkSinkPause(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_removeSource_withoutScanning() { - prepareSynchronizedPairAndStopSearching(); - - // Remove source, HOST_INTENTIONAL - mBassClientService.removeSource(mCurrentDevice, TEST_SOURCE_ID); - checkNoSinkPause(); - verifyRemoveMessageAndInjectSourceRemoval(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_removeSource_duringScanning() { - prepareSynchronizedPair(); - - // Remove source, HOST_INTENTIONAL - mBassClientService.removeSource(mCurrentDevice, TEST_SOURCE_ID); - checkNoSinkPause(); - verifyRemoveMessageAndInjectSourceRemoval(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_stopReceivers_withoutScanning() { - prepareSynchronizedPairAndStopSearching(); - - // Stop receivers, HOST_INTENTIONAL - mBassClientService.stopReceiversSourceSynchronization(TEST_BROADCAST_ID); - checkNoSinkPause(); - verifyRemoveMessageAndInjectSourceRemoval(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_stopReceivers_duringScanning() { - prepareSynchronizedPair(); - - // Stop receivers, HOST_INTENTIONAL - mBassClientService.stopReceiversSourceSynchronization(TEST_BROADCAST_ID); - checkNoSinkPause(); - verifyRemoveMessageAndInjectSourceRemoval(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_suspendReceivers_withoutScanning() { - prepareSynchronizedPairAndStopSearching(); - - // Suspend receivers, HOST_INTENTIONAL - mBassClientService.suspendReceiversSourceSynchronization(TEST_BROADCAST_ID); - checkNoSinkPause(); - if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - verifyRemoveMessageAndInjectSourceRemoval(); - } - checkResumeSynchronizationByHost(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_suspendReceivers_duringScanning() { - prepareSynchronizedPair(); - - // Suspend receivers, HOST_INTENTIONAL - mBassClientService.suspendReceiversSourceSynchronization(TEST_BROADCAST_ID); - checkNoSinkPause(); - if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - verifyRemoveMessageAndInjectSourceRemoval(); - } - checkResumeSynchronizationByHost(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_suspendAllReceivers_withoutScanning() { - prepareSynchronizedPairAndStopSearching(); - - // Suspend all receivers, HOST_INTENTIONAL - mBassClientService.suspendAllReceiversSourceSynchronization(); - checkNoSinkPause(); - if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - verifyRemoveMessageAndInjectSourceRemoval(); - } - checkResumeSynchronizationByHost(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_suspendAllReceivers_duringScanning() { - prepareSynchronizedPair(); - - // Suspend all receivers, HOST_INTENTIONAL - mBassClientService.suspendAllReceiversSourceSynchronization(); - checkNoSinkPause(); - if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - verifyRemoveMessageAndInjectSourceRemoval(); - } - checkResumeSynchronizationByHost(); - } - - @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE - }) - public void hostIntentional_handleUnicastSourceStreamStatusChange_withoutScanning() { - prepareSynchronizedPairAndStopSearching(); - - /* Unicast would like to stream */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 0 /* STATUS_LOCAL_STREAM_REQUESTED */); - checkNoSinkPause(); - if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - verifyRemoveMessageAndInjectSourceRemoval(); - } - - /* Unicast finished streaming */ - mBassClientService.handleUnicastSourceStreamStatusChange( - 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); - if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - } + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); // In case of add source to inactive verifyAllGroupMembersGettingUpdateOrAddSource(createBroadcastMetadata(TEST_BROADCAST_ID)); } @@ -6970,14 +6339,13 @@ public class BassClientServiceTest { public void outOfRange_syncEstablishedFailed_stopMonitoringAfterTimeout() { prepareSynchronizedPairAndStopSearching(); - // Bis unsynced, SINK_UNKNOWN, verify broadcast sync and MESSAGE_BIG_CHECK_START + // Bis and PA unsynced, SINK_UNINTENTIONAL BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); + injectRemoteSourceStateChanged(meta, false, false); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkMessage(BassClientService.MESSAGE_BIG_CHECK_START); checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); @@ -7007,14 +6375,13 @@ public class BassClientServiceTest { public void outOfRange_syncEstablishedFailed_clearTimeout() { prepareSynchronizedPairAndStopSearching(); - // Bis unsynced, SINK_UNKNOWN, verify broadcast sync and MESSAGE_BIG_CHECK_START + // Bis and PA unsynced, SINK_UNINTENTIONAL BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); - injectRemoteSourceStateChanged(meta, false); + injectRemoteSourceStateChanged(meta, false, false); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkMessage(BassClientService.MESSAGE_BIG_CHECK_START); checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); -- GitLab From e329332b7268e35441a85df4462fd118fce73070 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Tue, 8 Oct 2024 17:40:08 +0800 Subject: [PATCH 192/875] floss: fix some rust warnings * Add serde feature in hcidoc_packets (the generated files has serde configuration feature) * Allow dead code in hcidoc parser (the structs correctly represent the actual packet despite the value is never read) * Don't use DateTime::from_timestamp_micros in hcidoc parser because it needs chrono version above what's available on our rust_crates * Use underscore for default match arm * Remove unused FromPrimitive trait Bug: None Test: m -j Flag: EXEMPT, floss only changes Change-Id: Ie81c021b02ca5fa7d142fc64e8cec061c6566f2c --- floss/hcidoc/packets/Cargo.toml | 3 +++ floss/hcidoc/src/parser.rs | 13 ++++++++++++- system/gd/rust/topshim/src/btif.rs | 2 +- system/gd/rust/topshim/src/syslog.rs | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/floss/hcidoc/packets/Cargo.toml b/floss/hcidoc/packets/Cargo.toml index cd633bb88c1..0b65fa4b263 100644 --- a/floss/hcidoc/packets/Cargo.toml +++ b/floss/hcidoc/packets/Cargo.toml @@ -37,3 +37,6 @@ walkdir = "2.2" [lib] path = "lib.rs" crate-type = ["rlib"] + +[features] +serde = [] diff --git a/floss/hcidoc/src/parser.rs b/floss/hcidoc/src/parser.rs index 26659bc424f..572040cabed 100644 --- a/floss/hcidoc/src/parser.rs +++ b/floss/hcidoc/src/parser.rs @@ -103,6 +103,7 @@ const SNOOP_Y0_TO_Y1970_US: i64 = 62_168_256_000_000_000; /// Snoop file packet format. #[derive(Debug, Clone)] +#[allow(dead_code)] pub struct SnoopPacketPreamble { /// The original length of the captured packet as received via a network. pub original_length: u32, @@ -177,7 +178,15 @@ pub trait GeneralSnoopPacket { fn get_timestamp(&self) -> Option { let preamble = self.preamble(); let ts_i64 = i64::try_from(preamble.timestamp_us).unwrap_or(i64::MAX); - DateTime::from_timestamp_micros(ts_i64 - SNOOP_Y0_TO_Y1970_US).map(|date| date.naive_utc()) + + // TODO: directly use Datetime::from_timestamp_micros() once chrono package is re-vendored + // to v0.4.35. Below is the actual implementation of that function. + let from_timestamp_micros = |micros: i64| -> Option> { + let secs = micros.div_euclid(1_000_000); + let nsecs = micros.rem_euclid(1_000_000) as u32 * 1000; + DateTime::from_timestamp(secs, nsecs) + }; + from_timestamp_micros(ts_i64 - SNOOP_Y0_TO_Y1970_US).map(|date| date.naive_utc()) } } @@ -420,6 +429,7 @@ impl<'a> TryFrom<&'a dyn GeneralSnoopPacket> for PacketChild { /// A single processable packet of data. #[derive(Debug, Clone)] +#[allow(dead_code)] pub struct Packet { /// Timestamp of this packet pub ts: NaiveDateTime, @@ -454,6 +464,7 @@ impl<'a> TryFrom<(usize, &'a dyn GeneralSnoopPacket)> for Packet { } } +#[allow(dead_code)] pub enum AclContent { Control(Control), LeControl(LeControl), diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index b5df64fb7e8..b7e8dbbac67 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -435,7 +435,7 @@ impl ToString for BtVendorProductInfo { match self.vendor_id_src { 1 => "bluetooth", 2 => "usb", - default => "unknown", + _ => "unknown", }, self.vendor_id, self.product_id, diff --git a/system/gd/rust/topshim/src/syslog.rs b/system/gd/rust/topshim/src/syslog.rs index 5af01c49489..628d6682c4b 100644 --- a/system/gd/rust/topshim/src/syslog.rs +++ b/system/gd/rust/topshim/src/syslog.rs @@ -5,7 +5,7 @@ //! to tune log levels for syslog. use num_derive::{FromPrimitive, ToPrimitive}; -use num_traits::cast::{FromPrimitive, ToPrimitive}; +use num_traits::cast::ToPrimitive; use std::ffi::CString; use std::os::raw::c_char; -- GitLab From abb6c474d1c85c9f611893724cd0aa8cb959222d Mon Sep 17 00:00:00 2001 From: Yun-Hao Chung Date: Tue, 8 Oct 2024 11:03:40 +0000 Subject: [PATCH 193/875] Floss: Temporary skip setting log level for tags Some modules, ex. message_loop_thread, have additional cleanup in their destructor, if the destructor tries to log something but the |tag_level_map| has been freed, the crash happens. Temprorary skipping the setting to avoid the crash until we finalize the solution. Bug: 371889111 Tag: #floss Test: mmm packages/modules/Bluetooth Test: toggle on/off adapter and verify no crash Flag: EXEMPT, Floss-only changes Change-Id: I30a40af90934802864c270752f4baa957d1f02be --- system/gd/rust/linux/stack/src/bluetooth_logging.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/gd/rust/linux/stack/src/bluetooth_logging.rs b/system/gd/rust/linux/stack/src/bluetooth_logging.rs index fea9303a333..b3d0b226183 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_logging.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_logging.rs @@ -98,6 +98,9 @@ impl BluetoothLogging { fn apply_libbluetooth_log_level(&self) { set_default_log_level(self.log_level); + + // TODO(b/371889111): Don't set log level for tag until b/371889111 is fixed. + /* // Levels for verbose-only tags. let level = match self.log_level { Level::Verbose => Level::Verbose, @@ -107,6 +110,7 @@ impl BluetoothLogging { log::info!("Setting log level for tag {} to {:?}", tag, level); set_log_level_for_tag(tag, level); } + */ } } -- GitLab From 8a3969cf16b1e90c2060e2f7ba28ef29262d7a31 Mon Sep 17 00:00:00 2001 From: Yun-Hao Chung Date: Tue, 8 Oct 2024 10:07:02 +0000 Subject: [PATCH 194/875] Floss: Fix Rust bluetooth logging on initialization When applying Rust log level on initializing BluetoothLogging, we can't directly call |is_debug_enabled| since |self.initialized| is not yet set. This refactors some of the functions to fix the issue. Bug: 371889111 Tag: #floss Test: mmm packages/modules/Bluetooth Test: Verified manually Flag: EXEMPT, Floss-only changes Change-Id: I2fcaf73ea120d3a7e98edf7ef5bfde1b00f59c2c --- system/gd/rust/linux/stack/src/bluetooth_logging.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/system/gd/rust/linux/stack/src/bluetooth_logging.rs b/system/gd/rust/linux/stack/src/bluetooth_logging.rs index b3d0b226183..2a07a22efe7 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_logging.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_logging.rs @@ -85,8 +85,12 @@ impl BluetoothLogging { Ok(()) } + fn should_enable_debug_mode(&self) -> bool { + self.log_level == Level::Debug || self.log_level == Level::Verbose + } + fn get_log_level_filter(&self) -> LevelFilter { - match self.is_debug_enabled() { + match self.should_enable_debug_mode() { true => LevelFilter::Debug, false => LevelFilter::Info, } @@ -116,7 +120,7 @@ impl BluetoothLogging { impl IBluetoothLogging for BluetoothLogging { fn is_debug_enabled(&self) -> bool { - self.is_initialized && (self.log_level == Level::Debug || self.log_level == Level::Verbose) + self.is_initialized && self.should_enable_debug_mode() } fn set_debug_logging(&mut self, enabled: bool) { -- GitLab From 1bd6a8d4a6c8f0e6c5d6816696af63d63596be01 Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Sun, 6 Oct 2024 22:50:27 +0800 Subject: [PATCH 195/875] floss: Remove the wrong "#[allow(unused)]" This was missed in https://r.android.com/3288142. Bug: 331817295 Test: mmm packages/modules/Bluetooth Flag: EXEMPT, Floss-only change Change-Id: I50dbd6277ccfc5ed54b1ce9f42dc9c1e6b8b05de --- system/gd/rust/linux/stack/src/bluetooth_admin.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/gd/rust/linux/stack/src/bluetooth_admin.rs b/system/gd/rust/linux/stack/src/bluetooth_admin.rs index ce34bc45a45..66ee4675fd0 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_admin.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_admin.rs @@ -422,8 +422,6 @@ impl RPCProxy for BluetoothDeviceCallbacks { mod tests { use crate::bluetooth_admin::{BluetoothAdmin, BluetoothAdminPolicyHelper}; use bt_topshim::btif::Uuid; - - #[allow(unused)] use serde_json::{json, Value}; #[test] -- GitLab From e8218e30acea4f74676ce0808363876a1f843397 Mon Sep 17 00:00:00 2001 From: zhenchao Date: Sun, 29 Sep 2024 16:48:12 +0800 Subject: [PATCH 196/875] [le audio] use broadcastId instead of Sid to check for local broadcast Advertising sid is likely to be same for local source and external source. As a result, external source is unable to be added while local source is enabled. This fix use broadcastId instead of advertising Sid to check for local broadcast source. Bug: 370267705 Test: manual Test: atest BassClientServiceTest LeAudioBroadcastServiceTest Change-Id: I6e969a4f47d4280019c32195c177654e2f713158 --- .../bass_client/BassClientService.java | 8 ++-- .../bass_client/BassClientServiceTest.java | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) 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 2f95d067039..5986a8713a4 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -3100,7 +3100,7 @@ public class BassClientService extends ProfileService { return stateMachine.getMaximumSourceCapacity(); } - private boolean isLocalBroadcast(int sourceAdvertisingSid) { + private boolean isLocalBroadcast(int broadcastId) { LeAudioService leAudioService = mServiceFactory.getLeAudioService(); if (leAudioService == null) { return false; @@ -3110,7 +3110,7 @@ public class BassClientService extends ProfileService { leAudioService.getAllBroadcastMetadata().stream() .anyMatch( meta -> { - return meta.getSourceAdvertisingSid() == sourceAdvertisingSid; + return meta.getBroadcastId() == broadcastId; }); log("isLocalBroadcast=" + wasFound); return wasFound; @@ -3121,7 +3121,7 @@ public class BassClientService extends ProfileService { return false; } - return isLocalBroadcast(metaData.getSourceAdvertisingSid()); + return isLocalBroadcast(metaData.getBroadcastId()); } boolean isLocalBroadcast(BluetoothLeBroadcastReceiveState receiveState) { @@ -3129,7 +3129,7 @@ public class BassClientService extends ProfileService { return false; } - return isLocalBroadcast(receiveState.getSourceAdvertisingSid()); + return isLocalBroadcast(receiveState.getBroadcastId()); } static void log(String msg) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 3ba383a656c..45044588d29 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -6926,4 +6926,45 @@ public class BassClientServiceTest { } } } + + @Test + public void testIsLocalBroadacst() { + int broadcastId = 12345; + + BluetoothLeBroadcastMetadata metadata = createBroadcastMetadata(broadcastId); + BluetoothLeBroadcastReceiveState receiveState = + new BluetoothLeBroadcastReceiveState( + TEST_SOURCE_ID, + metadata.getSourceAddressType(), + metadata.getSourceDevice(), + metadata.getSourceAdvertisingSid(), + metadata.getBroadcastId(), + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null, + metadata.getSubgroups().size(), + // Bis sync states + metadata.getSubgroups().stream() + .map(e -> (long) 0x00000001) + .collect(Collectors.toList()), + metadata.getSubgroups().stream() + .map(e -> e.getContentMetadata()) + .collect(Collectors.toList())); + + /* External broadcast check */ + doReturn(new ArrayList()) + .when(mLeAudioService) + .getAllBroadcastMetadata(); + + assertThat(mBassClientService.isLocalBroadcast(metadata)).isFalse(); + assertThat(mBassClientService.isLocalBroadcast(receiveState)).isFalse(); + + /* Local broadcast check */ + doReturn(new ArrayList(Arrays.asList(metadata))) + .when(mLeAudioService) + .getAllBroadcastMetadata(); + + assertThat(mBassClientService.isLocalBroadcast(metadata)).isTrue(); + assertThat(mBassClientService.isLocalBroadcast(receiveState)).isTrue(); + } } -- GitLab From 5ffa202285a79e40b157b24b9bfc8fa534182fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 8 Oct 2024 13:17:13 +0000 Subject: [PATCH 197/875] leaudio: Do not update local metadata if not needed local_metadata_context_types_ should be updated only on MetadataUpdate event. This will fix the problem, when offloader is changing source metadata to converational and then back to media. Without this patch, when context is changed to media, on the sink path we still would keep conversational, which might afect future configuration Bug: 367894783 Bug: 352686917 Test: atest bluetooth_le_audio_client_test Flag: com.android.bluetooth.flags.leaudio_speed_up_reconfiguration_between_call Change-Id: I4a560ce73e49116df4f0179fd71592443ab50558 --- system/bta/le_audio/client.cc | 21 +++++++------ system/bta/le_audio/le_audio_client_test.cc | 34 ++++++++++++--------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index a0568998e2e..448f1ad5052 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -4736,8 +4736,6 @@ public: local_metadata_context_types_.sink = ChooseMetadataContextType(local_metadata_context_types_.sink); - local_metadata_context_types_.source = - ChooseMetadataContextType(local_metadata_context_types_.source); /* Reconfigure or update only if the stream is already started * otherwise wait for the local sink to resume. @@ -4784,20 +4782,25 @@ public: SetInVoipCall(false); } + BidirectionalPair remote_metadata = { + .sink = local_metadata_context_types_.source, + .source = local_metadata_context_types_.sink}; + /* Make sure we have CONVERSATIONAL when in a call and it is not mixed * with any other bidirectional context */ if (IsInCall() || IsInVoipCall()) { log::debug("In Call preference used: {}, voip call: {}", IsInCall(), IsInVoipCall()); - local_metadata_context_types_.sink.unset_all(kLeAudioContextAllBidir); - local_metadata_context_types_.source.unset_all(kLeAudioContextAllBidir); - local_metadata_context_types_.sink.set(LeAudioContextType::CONVERSATIONAL); - local_metadata_context_types_.source.set(LeAudioContextType::CONVERSATIONAL); + remote_metadata.sink.unset_all(kLeAudioContextAllBidir); + remote_metadata.source.unset_all(kLeAudioContextAllBidir); + remote_metadata.sink.set(LeAudioContextType::CONVERSATIONAL); + remote_metadata.source.set(LeAudioContextType::CONVERSATIONAL); } - BidirectionalPair remote_metadata = { - .sink = local_metadata_context_types_.source, - .source = local_metadata_context_types_.sink}; + if (!com::android::bluetooth::flags::leaudio_speed_up_reconfiguration_between_call()) { + local_metadata_context_types_.sink = remote_metadata.source; + local_metadata_context_types_.source = remote_metadata.sink; + } if (IsInVoipCall()) { log::debug("Unsetting RINGTONE from remote sink"); diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 9b9498aa0f0..4496d21b365 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -1026,9 +1026,13 @@ protected: metadata_context_types, types::BidirectionalPair> ccid_lists) { auto group_state = group->GetState(); - log::info("StartStream: group {} state {}, context type {}", group->group_id_, - bluetooth::common::ToString(group_state), - bluetooth::common::ToString(context_type)); + log::info( + "StartStream: group {} state {}, context type {} sink metadata_ctx {}, " + "source metadata_ctx {}", + group->group_id_, bluetooth::common::ToString(group_state), + bluetooth::common::ToString(context_type), + bluetooth::common::ToString(metadata_context_types.sink), + bluetooth::common::ToString(metadata_context_types.source)); /* Do nothing if already streaming - the implementation would * probably update the metadata. @@ -10429,7 +10433,7 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { available_snk_context_types_ = (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE | types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA | - types::LeAudioContextType::LIVE) + types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS) .value(); supported_snk_context_types_ = available_snk_context_types_ | @@ -10460,7 +10464,7 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { LeAudioClient::Get()->GroupSetActive(group_id); SyncOnMainLoop(); - // 1) Start with the call first + log::info("TESTPOINT 1: Start with the call first"); // ----------------------------- // CONVERSATIONAL is from In Call preference, and RINGTONE is from metadata LeAudioClient::Get()->SetInCall(true); @@ -10486,7 +10490,7 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { uint8_t cis_count_in = 1; TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40); - // 2) Start MEDIA during the call, expect MEDIA only on the remote sink + log::info("TESTPOINT 2: Start MEDIA during the call, expect MEDIA only on the remote sink"); contexts = {.sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::MEDIA), .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)}; @@ -10501,25 +10505,27 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - // 2) Disable In Call preference but do not suspend the local sink - // We should stay in CONVERSATIONAL until the local sink suspends + log::info( + "TESTPOINT 3: Disable In Call preference but do not suspend the local sink. Play " + "notification on the same stream."); + // Verify both context are sent as the metadata. // --------------------------------------- LeAudioClient::Get()->SetInCall(false); EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0); - contexts = {.sink = types::AudioContexts(types::LeAudioContextType::MEDIA | + contexts = {.sink = types::AudioContexts(types::LeAudioContextType::NOTIFICATIONS | types::LeAudioContextType::CONVERSATIONAL), .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)}; EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, _)) .Times(1); - UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, + UpdateLocalSourceMetadata(AUDIO_USAGE_NOTIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, /*reconfigure=*/false); Mock::VerifyAndClearExpectations(&mock_state_machine_); Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - // 3) Disable call so we could go back to MEDIA + log::info("TESTPOING 4: Disable call so we could go back to MEDIA"); // --------------------------------------- // Suspend should stop the stream EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1); @@ -10546,7 +10552,7 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - // 4) Stop streaming + log::info("TESTPOINT 5: Stop streaming"); // ------------------ StopStreaming(group_id); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); @@ -10570,7 +10576,7 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes_SpeedUpReconfigFlagEnabled) { available_snk_context_types_ = (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE | types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA | - types::LeAudioContextType::LIVE) + types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS) .value(); supported_snk_context_types_ = available_snk_context_types_ | @@ -10656,7 +10662,7 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes_SpeedUpReconfigFlagEnabled) { Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - log::info("Step 2) Disable call so we could go back to MEDIA"); + log::info("Step 3) Disable call so we could go back to MEDIA"); // --------------------------------------- // Suspend should stop the stream EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1); -- GitLab From 388317486272c098bd01c99f8921fb3eb07ac36b Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 7 Oct 2024 17:43:59 +0000 Subject: [PATCH 198/875] system/btif/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I0cdf54ea822783073f861affc126a7962fba547f --- system/btif/Android.bp | 15 ---- system/btif/avrcp/avrcp_service.cc | 2 +- system/btif/co/bta_av_co_peer.cc | 2 +- system/btif/co/bta_hh_co.cc | 2 +- system/btif/src/btif_a2dp.cc | 2 +- system/btif/src/btif_a2dp_sink.cc | 3 +- system/btif/src/btif_av.cc | 2 +- system/btif/src/btif_hf.cc | 4 +- system/btif/src/btif_hf_client.cc | 2 +- system/btif/src/btif_hh.cc | 2 +- system/btif/src/btif_pan.cc | 2 +- system/btif/src/btif_rc.cc | 9 ++- .../btif/test/btif_hf_client_service_test.cc | 10 +-- system/btif/test/btif_rc_test.cc | 76 ++++++++++--------- 14 files changed, 64 insertions(+), 69 deletions(-) diff --git a/system/btif/Android.bp b/system/btif/Android.bp index eb4ee993d56..7eb29525247 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -165,9 +165,6 @@ cc_library_static { "libbtif-core", "libflatbuffers-cpp", ], - cflags: [ - "-Wno-unused-parameter", - ], apex_available: [ "com.android.btservices", ], @@ -391,9 +388,6 @@ cc_test { "libchrome", "libosi", ], - cflags: [ - "-Wno-unused-parameter", - ], shared_libs: [ "libbase", "liblog", @@ -432,9 +426,6 @@ cc_test { "libbase", "liblog", ], - cflags: [ - "-Wno-unused-parameter", - ], } // btif rc unit tests for target @@ -480,9 +471,6 @@ cc_test { shared_libs: ["libstatssocket"], }, }, - cflags: [ - "-Wno-unused-parameter", - ], sanitize: { address: true, cfi: true, @@ -520,9 +508,6 @@ cc_test { "libcom.android.sysprop.bluetooth.wrapped", "libgmock", ], - cflags: [ - "-Wno-unused-parameter", - ], } cc_test { diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc index c76c281c636..871177bff30 100644 --- a/system/btif/avrcp/avrcp_service.cc +++ b/system/btif/avrcp/avrcp_service.cc @@ -579,7 +579,7 @@ void AvrcpService::SendFolderUpdate(bool available_players, bool addressed_playe } // Send out the track changed info to update the playback state for each device -void AvrcpService::SendActiveDeviceChanged(const RawAddress& address) { +void AvrcpService::SendActiveDeviceChanged(const RawAddress& /*address*/) { SendMediaUpdate(false, true, false); } diff --git a/system/btif/co/bta_av_co_peer.cc b/system/btif/co/bta_av_co_peer.cc index 966f91add4b..de3f41e10f7 100644 --- a/system/btif/co/bta_av_co_peer.cc +++ b/system/btif/co/bta_av_co_peer.cc @@ -98,7 +98,7 @@ void BtaAvCoPeer::setCodecConfig(const uint8_t* new_codec_config) { } void BtaAvCoPeerCache::Init(const std::vector& codec_priorities, - std::vector* supported_codecs) { + std::vector* /*supported_codecs*/) { std::lock_guard lock(codec_lock_); codec_priorities_ = codec_priorities; diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index 5b2bffb4e7b..086ad115513 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -1037,7 +1037,7 @@ void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name, uint * Returns void. * ******************************************************************************/ -void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) { +void bta_hh_co_set_rpt_rsp([[maybe_unused]] uint8_t dev_handle, [[maybe_unused]] uint8_t status) { #if ENABLE_UHID_SET_REPORT log::verbose("dev_handle = {}", dev_handle); diff --git a/system/btif/src/btif_a2dp.cc b/system/btif/src/btif_a2dp.cc index d99b6c1e178..f8036bf8c8f 100644 --- a/system/btif/src/btif_a2dp.cc +++ b/system/btif/src/btif_a2dp.cc @@ -39,7 +39,7 @@ using namespace bluetooth; using bluetooth::audio::a2dp::BluetoothAudioStatus; -void btif_a2dp_on_idle(const RawAddress& peer_addr, const A2dpType local_a2dp_type) { +void btif_a2dp_on_idle(const RawAddress& /*peer_addr*/, const A2dpType local_a2dp_type) { log::verbose("Peer stream endpoint type:{}", peer_stream_endpoint_text(btif_av_get_peer_sep(local_a2dp_type))); if (btif_av_get_peer_sep(local_a2dp_type) == AVDT_TSEP_SNK) { diff --git a/system/btif/src/btif_a2dp_sink.cc b/system/btif/src/btif_a2dp_sink.cc index 0aba99e2016..ec9365a1b47 100644 --- a/system/btif/src/btif_a2dp_sink.cc +++ b/system/btif/src/btif_a2dp_sink.cc @@ -222,7 +222,8 @@ static void btif_a2dp_sink_startup_delayed() { // Nothing to do } -static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) { +static void btif_a2dp_sink_on_decode_complete([[maybe_unused]] uint8_t* data, + [[maybe_unused]] uint32_t len) { #ifdef __ANDROID__ BtifAvrcpAudioTrackWriteData(btif_a2dp_sink_cb.audio_track, reinterpret_cast(data), len); #endif diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 277dc493e1c..c62d54c2811 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -3662,7 +3662,7 @@ bool btif_av_is_sink_enabled(void) { return btif_av_sink.Enabled(); } bool btif_av_is_source_enabled(void) { return btif_av_source.Enabled(); } -void btif_av_stream_start(const A2dpType local_a2dp_type) { +void btif_av_stream_start(const A2dpType /*local_a2dp_type*/) { log::info(""); btif_av_source_dispatch_sm_event(btif_av_source_active_peer(), BTIF_AV_START_STREAM_REQ_EVT); diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index 317c00e2f3a..372bdf4262b 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -754,7 +754,7 @@ static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG* p_data) { * Returns bt_status_t * ******************************************************************************/ -static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) { +static bt_status_t connect_int(RawAddress* bd_addr, uint16_t /*uuid*/) { CHECK_BTHF_INIT(); if (is_connected(bd_addr)) { log::warn("device {} is already connected", *bd_addr); @@ -1500,7 +1500,7 @@ bt_status_t HeadsetInterface::PhoneStateChange(int num_active, int num_held, return status; } -bt_status_t HeadsetInterface::EnableSwb(bthf_swb_codec_t swb_codec, bool enable, +bt_status_t HeadsetInterface::EnableSwb(bthf_swb_codec_t /*swb_codec*/, bool enable, RawAddress* bd_addr) { return enable_aptx_swb_codec(enable, bd_addr); } diff --git a/system/btif/src/btif_hf_client.cc b/system/btif/src/btif_hf_client.cc index 79b9b543614..08e06e19e83 100644 --- a/system/btif/src/btif_hf_client.cc +++ b/system/btif/src/btif_hf_client.cc @@ -268,7 +268,7 @@ static bt_status_t init(bthf_client_callbacks_t* callbacks) { * Returns bt_status_t * ******************************************************************************/ -static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) { +static bt_status_t connect_int(RawAddress* bd_addr, uint16_t /*uuid*/) { btif_hf_client_cb_t* cb = btif_hf_client_allocate_cb(); if (cb == NULL) { log::error("could not allocate block!"); diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index 4a4bddd266f..49d13d28d0e 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -1299,7 +1299,7 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) { * ******************************************************************************/ -static void btif_hh_hsdata_rpt_copy_cb(uint16_t event, char* p_dest, const char* p_src) { +static void btif_hh_hsdata_rpt_copy_cb(uint16_t /*event*/, char* p_dest, const char* p_src) { tBTA_HH_HSDATA* p_dst_data = (tBTA_HH_HSDATA*)p_dest; tBTA_HH_HSDATA* p_src_data = (tBTA_HH_HSDATA*)p_src; BT_HDR* hdr; diff --git a/system/btif/src/btif_pan.cc b/system/btif/src/btif_pan.cc index f4705f99eba..527c6ae6836 100644 --- a/system/btif/src/btif_pan.cc +++ b/system/btif/src/btif_pan.cc @@ -758,7 +758,7 @@ static void btif_pan_close_all_conns() { } } -static void btpan_tap_fd_signaled(int fd, int type, int flags, uint32_t user_id) { +static void btpan_tap_fd_signaled(int fd, int /*type*/, int flags, uint32_t /*user_id*/) { log::assert_that(btpan_cb.tap_fd == INVALID_FD || btpan_cb.tap_fd == fd, "assert failed: btpan_cb.tap_fd == INVALID_FD || btpan_cb.tap_fd == fd"); diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index 5c82b54280b..50ecb6a1402 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -513,7 +513,7 @@ void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs, } } -void rc_cleanup_sent_cmd(void* p_data) { log::verbose(""); } +void rc_cleanup_sent_cmd(void* /*p_data*/) { log::verbose(""); } void handle_rc_ctrl_features_all(btif_rc_device_cb_t* p_dev) { if (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCTG) && @@ -3615,7 +3615,7 @@ static void cleanup_app_attr_val_txt_response(btif_rc_player_app_settings_t* p_a * Returns None * **************************************************************************/ -static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_RSP* p_rsp) { +static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_RSP* /*p_rsp*/) { uint8_t accepted = 0; btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle); @@ -4441,8 +4441,9 @@ static bt_status_t get_now_playing_list_cmd(const RawAddress& bd_addr, uint32_t * otherwise BT_STATUS_FAIL * **************************************************************************/ -static bt_status_t get_item_attribute_cmd(uint64_t uid, int scope, uint8_t num_attribute, - const uint32_t* p_attr_ids, btif_rc_device_cb_t* p_dev) { +static bt_status_t get_item_attribute_cmd(uint64_t uid, int scope, uint8_t /*num_attribute*/, + const uint32_t* /*p_attr_ids*/, + btif_rc_device_cb_t* p_dev) { tAVRC_COMMAND avrc_cmd = {0}; avrc_cmd.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES; avrc_cmd.get_attrs.scope = scope; diff --git a/system/btif/test/btif_hf_client_service_test.cc b/system/btif/test/btif_hf_client_service_test.cc index cfba41ff874..7b2e0456e86 100644 --- a/system/btif/test/btif_hf_client_service_test.cc +++ b/system/btif/test/btif_hf_client_service_test.cc @@ -22,18 +22,18 @@ int get_default_hf_client_features() { DEFAULT_BTIF_HF_CLIENT_FEATURES); } -tBTA_STATUS BTA_HfClientEnable(tBTA_HF_CLIENT_CBACK* p_cback, tBTA_HF_CLIENT_FEAT features, - const char* p_service_name) { +tBTA_STATUS BTA_HfClientEnable(tBTA_HF_CLIENT_CBACK* /*p_cback*/, tBTA_HF_CLIENT_FEAT features, + const char* /*p_service_name*/) { gFeatures = features; return BTA_SUCCESS; } void BTA_HfClientDisable(void) {} -bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event, char* p_params, - int param_len, tBTIF_COPY_CBACK* p_copy_cback) { +bt_status_t btif_transfer_context(tBTIF_CBACK* /*p_cback*/, uint16_t /*event*/, char* /*p_params*/, + int /*param_len*/, tBTIF_COPY_CBACK* /*p_copy_cback*/) { return BT_STATUS_SUCCESS; } void btif_queue_advance() {} -std::string dump_hf_client_event(uint16_t event) { return "UNKNOWN MSG ID"; } +std::string dump_hf_client_event(uint16_t /*event*/) { return "UNKNOWN MSG ID"; } class BtifHfClientTest : public ::testing::Test { protected: diff --git a/system/btif/test/btif_rc_test.cc b/system/btif/test/btif_rc_test.cc index bcd03e6851f..7ac956920c9 100644 --- a/system/btif/test/btif_rc_test.cc +++ b/system/btif/test/btif_rc_test.cc @@ -40,20 +40,25 @@ namespace avrcp { int VolChanged = 0; AvrcpService* AvrcpService::instance_ = nullptr; -void AvrcpService::SendMediaUpdate(bool track_changed, bool play_state, bool queue) {} -void AvrcpService::SendFolderUpdate(bool available_players, bool addressed_players, bool uids) {} -void AvrcpService::SendActiveDeviceChanged(const RawAddress& address) {} -void AvrcpService::SendPlayerSettingsChanged(std::vector attributes, - std::vector values) {} -void AvrcpService::ServiceInterfaceImpl::Init(MediaInterface* media_interface, - VolumeInterface* volume_interface, - PlayerSettingsInterface* player_settings_interface) {} -void AvrcpService::ServiceInterfaceImpl::RegisterBipServer(int psm) {} +void AvrcpService::SendMediaUpdate(bool /*track_changed*/, bool /*play_state*/, bool /*queue*/) {} +void AvrcpService::SendFolderUpdate(bool /*available_players*/, bool /*addressed_players*/, + bool /*uids*/) {} +void AvrcpService::SendActiveDeviceChanged(const RawAddress& /*address*/) {} +void AvrcpService::SendPlayerSettingsChanged(std::vector /*attributes*/, + std::vector /*values*/) {} +void AvrcpService::ServiceInterfaceImpl::Init( + MediaInterface* /*media_interface*/, VolumeInterface* /*volume_interface*/, + PlayerSettingsInterface* /*player_settings_interface*/) {} +void AvrcpService::ServiceInterfaceImpl::RegisterBipServer(int /*psm*/) {} void AvrcpService::ServiceInterfaceImpl::UnregisterBipServer() {} -bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(const RawAddress& bdaddr) { return true; } -bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(const RawAddress& bdaddr) { return true; } -void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus(const RawAddress& bdaddr, - bool connected) {} +bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(const RawAddress& /*bdaddr*/) { + return true; +} +bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(const RawAddress& /*bdaddr*/) { + return true; +} +void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus(const RawAddress& /*bdaddr*/, + bool /*connected*/) {} bool AvrcpService::ServiceInterfaceImpl::Cleanup() { return true; } AvrcpService* AvrcpService::Get() { @@ -62,7 +67,7 @@ AvrcpService* AvrcpService::Get() { return instance_; } -void AvrcpService::RegisterVolChanged(const RawAddress& bdaddr) { VolChanged++; } +void AvrcpService::RegisterVolChanged(const RawAddress& /*bdaddr*/) { VolChanged++; } } // namespace avrcp } // namespace bluetooth @@ -71,24 +76,25 @@ const RawAddress kDeviceAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); const uint8_t kRcHandle = 123; } // namespace -void btif_av_clear_remote_suspend_flag(const A2dpType local_a2dp_type) {} -bool btif_av_is_connected(const A2dpType local_a2dp_type) { return true; } +void btif_av_clear_remote_suspend_flag(const A2dpType /*local_a2dp_type*/) {} +bool btif_av_is_connected(const A2dpType /*local_a2dp_type*/) { return true; } bool btif_av_is_sink_enabled(void) { return true; } RawAddress btif_av_sink_active_peer(void) { return RawAddress(); } RawAddress btif_av_source_active_peer(void) { return RawAddress(); } -bool btif_av_stream_started_ready(const A2dpType local_a2dp_type) { return false; } -bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event, char* p_params, - int param_len, tBTIF_COPY_CBACK* p_copy_cback) { +bool btif_av_stream_started_ready(const A2dpType /*local_a2dp_type*/) { return false; } +bt_status_t btif_transfer_context(tBTIF_CBACK* /*p_cback*/, uint16_t /*event*/, char* /*p_params*/, + int /*param_len*/, tBTIF_COPY_CBACK* /*p_copy_cback*/) { return BT_STATUS_SUCCESS; } bool btif_av_src_sink_coexist_enabled() { return true; } -bool btif_av_is_connected_addr(const RawAddress& peer_address, const A2dpType local_a2dp_type) { +bool btif_av_is_connected_addr(const RawAddress& /*peer_address*/, + const A2dpType /*local_a2dp_type*/) { return true; } -bool btif_av_peer_is_connected_sink(const RawAddress& peer_address) { return false; } -bool btif_av_peer_is_connected_source(const RawAddress& peer_address) { return true; } -bool btif_av_peer_is_sink(const RawAddress& peer_address) { return false; } -bool btif_av_peer_is_source(const RawAddress& peer_address) { return true; } +bool btif_av_peer_is_connected_sink(const RawAddress& /*peer_address*/) { return false; } +bool btif_av_peer_is_connected_source(const RawAddress& /*peer_address*/) { return true; } +bool btif_av_peer_is_sink(const RawAddress& /*peer_address*/) { return false; } +bool btif_av_peer_is_source(const RawAddress& /*peer_address*/) { return true; } bool btif_av_both_enable(void) { return true; } static bluetooth::common::MessageLoopThread jni_thread("bt_jni_thread"); @@ -100,7 +106,9 @@ bt_status_t do_in_jni_thread(base::OnceClosure task) { return BT_STATUS_SUCCESS; } bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; } -bool interop_match_addr(const interop_feature_t feature, const RawAddress* addr) { return false; } +bool interop_match_addr(const interop_feature_t /*feature*/, const RawAddress* /*addr*/) { + return false; +} /** * Test class to test selected functionality in hci/src/hci_layer.cc @@ -213,7 +221,7 @@ protected: void TearDown() override { jni_thread.ShutDown(); - bt_rc_ctrl_callbacks->getrcfeatures_cb = [](const RawAddress& bd_addr, int features) {}; + bt_rc_ctrl_callbacks->getrcfeatures_cb = [](const RawAddress& /*bd_addr*/, int /*features*/) {}; btrc_ctrl_callbacks = default_btrc_ctrl_callbacks; BtifRcTest::TearDown(); } @@ -258,8 +266,8 @@ protected: void TearDown() override { jni_thread.ShutDown(); - bt_rc_ctrl_callbacks->connection_state_cb = [](bool rc_state, bool bt_state, - const RawAddress& bd_addr) {}; + bt_rc_ctrl_callbacks->connection_state_cb = [](bool /*rc_state*/, bool /*bt_state*/, + const RawAddress& /*bd_addr*/) {}; BtifRcTest::TearDown(); } }; @@ -307,8 +315,8 @@ protected: void TearDown() override { jni_thread.ShutDown(); - bt_rc_ctrl_callbacks->connection_state_cb = [](bool rc_state, bool bt_state, - const RawAddress& bd_addr) {}; + bt_rc_ctrl_callbacks->connection_state_cb = [](bool /*rc_state*/, bool /*bt_state*/, + const RawAddress& /*bd_addr*/) {}; BtifRcTest::TearDown(); } std::future g_btrc_connection_state_future; @@ -395,16 +403,16 @@ protected: BtifRcTest::SetUp(); init_ctrl(&btrc_ctrl_callbacks); jni_thread.StartUp(); - btrc_ctrl_callbacks.track_changed_cb = [](const RawAddress& bd_addr, uint8_t num_attr, - btrc_element_attr_val_t* p_attrs) { + btrc_ctrl_callbacks.track_changed_cb = [](const RawAddress& bd_addr, uint8_t /*num_attr*/, + btrc_element_attr_val_t* /*p_attrs*/) { btif_rc_cb.rc_multi_cb[0].rc_addr = bd_addr; }; } void TearDown() override { jni_thread.ShutDown(); - btrc_ctrl_callbacks.track_changed_cb = [](const RawAddress& bd_addr, uint8_t num_attr, - btrc_element_attr_val_t* p_attrs) {}; + btrc_ctrl_callbacks.track_changed_cb = [](const RawAddress& /*bd_addr*/, uint8_t /*num_attr*/, + btrc_element_attr_val_t* /*p_attrs*/) {}; BtifRcTest::TearDown(); } }; -- GitLab From 87eff145fa4dbec6bfdcf8ebb358c9ed3b9120e8 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 7 Oct 2024 20:30:47 +0000 Subject: [PATCH 199/875] system/gd/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I31226aedc376d74da5f036413d8db00422a40048 --- system/gd/Android.bp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/system/gd/Android.bp b/system/gd/Android.bp index d09e184f923..9501a6e6965 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -244,7 +244,6 @@ cc_library { cflags: [ "-DFUZZ_TARGET", "-DUSE_FAKE_TIMERS", - "-Wno-unused-parameter", ], static_libs: [ "bluetooth_flags_c_lib", @@ -686,7 +685,6 @@ cc_fuzz { cc: ["android-bluetooth-security@google.com"], componentid: 27441, }, - cflags: ["-Wno-unused-parameter"], } cc_fuzz { @@ -696,7 +694,6 @@ cc_fuzz { ":BluetoothHalFuzzSources", "hci/fuzz/hci_layer_fuzz_test.cc", ], - cflags: ["-Wno-unused-parameter"], } cc_fuzz { @@ -709,7 +706,6 @@ cc_fuzz { cc: ["android-bluetooth-security@google.com"], componentid: 27441, }, - cflags: ["-Wno-unused-parameter"], } cc_benchmark { -- GitLab From 84e3abe2a7e33fa16f159c19f5f01b917c44c8dd Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 7 Oct 2024 20:46:56 +0000 Subject: [PATCH 200/875] system/stack/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I104fb6a6b0695cd9ccd71a60e4ef60902af64b20 --- system/stack/Android.bp | 18 ---- system/stack/fuzzers/avrc_fuzzer.cc | 1 + system/stack/fuzzers/bnep_fuzzer.cc | 1 + system/stack/fuzzers/gatt_fuzzer.cc | 1 + system/stack/fuzzers/l2cap_fuzzer.cc | 10 +- system/stack/fuzzers/rfcomm_fuzzer.cc | 1 + system/stack/fuzzers/sdp_fuzzer.cc | 1 + system/stack/fuzzers/smp_fuzzer.cc | 1 + system/stack/test/a2dp/a2dp_aac_unittest.cc | 22 ++--- system/stack/test/a2dp/a2dp_opus_unittest.cc | 14 +-- system/stack/test/a2dp/a2dp_sbc_unittest.cc | 22 ++--- .../test/a2dp/a2dp_vendor_ldac_unittest.cc | 4 +- system/stack/test/a2dp/misc_fake.cc | 6 +- system/stack/test/common/mock_btm_layer.cc | 6 +- system/stack/test/common/mock_l2cap_layer.cc | 8 +- .../stack/test/common/mock_stack_avdt_msg.cc | 11 ++- system/stack/test/eatt/eatt_test.cc | 44 +++++---- system/stack/test/gatt/gatt_sr_test.cc | 92 ++++++++++--------- system/stack/test/gatt/mock_gatt_utils_ref.cc | 1 + system/stack/test/gatt/stack_gatt_test.cc | 31 ++++--- .../test/gatt_connection_manager_test.cc | 9 +- system/stack/test/stack_avdtp_test.cc | 11 ++- system/stack/test/stack_smp_test.cc | 24 ++--- system/test/stub/osi.cc | 1 + 24 files changed, 178 insertions(+), 162 deletions(-) diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 20f12e4c23e..f106a3c4558 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -364,9 +364,6 @@ cc_defaults { "bluetooth_cflags", "bluetooth_flatbuffer_bundler_defaults", ], - cflags: [ - "-Wno-unused-parameter", - ], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", @@ -957,7 +954,6 @@ cc_test { cfi: false, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } // Bluetooth stack smp unit tests for target @@ -1041,8 +1037,6 @@ cc_test { ], }, }, - // header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } // Bluetooth stack advertise data parsing unit tests for target @@ -1115,7 +1109,6 @@ cc_test { cfi: false, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1183,7 +1176,6 @@ cc_test { misc_undefined: ["bounds"], }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1254,7 +1246,6 @@ cc_test { misc_undefined: ["bounds"], }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1265,7 +1256,6 @@ cc_test { ], cflags: [ "-DUNIT_TESTS", - "-Wno-unused-parameter", ], test_suites: ["general-tests"], host_supported: true, @@ -1407,7 +1397,6 @@ cc_test { misc_undefined: ["bounds"], }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } // gatt sr hash test @@ -1474,7 +1463,6 @@ cc_test { }, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } // Iso manager unit tests @@ -1614,7 +1602,6 @@ cc_test { cfi: false, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1870,7 +1857,6 @@ cc_test { }, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1943,7 +1929,6 @@ cc_test { }, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -2044,7 +2029,6 @@ cc_test { }, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -2139,7 +2123,6 @@ cc_test { }, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -2229,7 +2212,6 @@ cc_test { }, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { diff --git a/system/stack/fuzzers/avrc_fuzzer.cc b/system/stack/fuzzers/avrc_fuzzer.cc index 03267249fd5..1592b707fd5 100644 --- a/system/stack/fuzzers/avrc_fuzzer.cc +++ b/system/stack/fuzzers/avrc_fuzzer.cc @@ -36,6 +36,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/fuzzers/bnep_fuzzer.cc b/system/stack/fuzzers/bnep_fuzzer.cc index 4ad6bffb0b5..79a70556e48 100644 --- a/system/stack/fuzzers/bnep_fuzzer.cc +++ b/system/stack/fuzzers/bnep_fuzzer.cc @@ -33,6 +33,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" using bluetooth::Uuid; diff --git a/system/stack/fuzzers/gatt_fuzzer.cc b/system/stack/fuzzers/gatt_fuzzer.cc index 3aa0f8ce01e..3a9fb812762 100644 --- a/system/stack/fuzzers/gatt_fuzzer.cc +++ b/system/stack/fuzzers/gatt_fuzzer.cc @@ -35,6 +35,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" using bluetooth::Uuid; bt_status_t do_in_main_thread(base::OnceCallback) { diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc index f9fff7ff80a..74b3590a45a 100644 --- a/system/stack/fuzzers/l2cap_fuzzer.cc +++ b/system/stack/fuzzers/l2cap_fuzzer.cc @@ -73,8 +73,8 @@ bluetooth::common::PostableContext* get_main() { return nullptr; } namespace bluetooth { namespace os { -uint32_t GetSystemPropertyUint32Base(const std::string& property, uint32_t default_value, - int base) { +uint32_t GetSystemPropertyUint32Base(const std::string& /*property*/, uint32_t default_value, + int /*base*/) { return default_value; } } // namespace os @@ -100,15 +100,15 @@ namespace { class FakeBtStack { public: FakeBtStack() { - test::mock::stack_acl::acl_create_le_connection.body = [](const RawAddress& bd_addr) { + test::mock::stack_acl::acl_create_le_connection.body = [](const RawAddress& /*bd_addr*/) { return true; }; - test::mock::stack_acl::acl_send_data_packet_br_edr.body = [](const RawAddress& bd_addr, + test::mock::stack_acl::acl_send_data_packet_br_edr.body = [](const RawAddress& /*bd_addr*/, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); osi_free(hdr); }; - test::mock::stack_acl::acl_send_data_packet_ble.body = [](const RawAddress& bd_addr, + test::mock::stack_acl::acl_send_data_packet_ble.body = [](const RawAddress& /*bd_addr*/, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); osi_free(hdr); diff --git a/system/stack/fuzzers/rfcomm_fuzzer.cc b/system/stack/fuzzers/rfcomm_fuzzer.cc index 238354d6424..3f3afbfe402 100644 --- a/system/stack/fuzzers/rfcomm_fuzzer.cc +++ b/system/stack/fuzzers/rfcomm_fuzzer.cc @@ -40,6 +40,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" namespace bluetooth { namespace hal { diff --git a/system/stack/fuzzers/sdp_fuzzer.cc b/system/stack/fuzzers/sdp_fuzzer.cc index 8fbcb8f7d8c..bd5b6f77c20 100644 --- a/system/stack/fuzzers/sdp_fuzzer.cc +++ b/system/stack/fuzzers/sdp_fuzzer.cc @@ -33,6 +33,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" namespace { diff --git a/system/stack/fuzzers/smp_fuzzer.cc b/system/stack/fuzzers/smp_fuzzer.cc index e8f3ba8d914..a99010254a9 100644 --- a/system/stack/fuzzers/smp_fuzzer.cc +++ b/system/stack/fuzzers/smp_fuzzer.cc @@ -35,6 +35,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" bluetooth::common::MessageLoopThread* main_thread_ptr = nullptr; diff --git a/system/stack/test/a2dp/a2dp_aac_unittest.cc b/system/stack/test/a2dp/a2dp_aac_unittest.cc index 4ad50da2410..7c35eaeb37d 100644 --- a/system/stack/test/a2dp/a2dp_aac_unittest.cc +++ b/system/stack/test/a2dp/a2dp_aac_unittest.cc @@ -142,9 +142,9 @@ protected: TEST_F(A2dpAacTest, a2dp_source_read_underflow) { static int enqueue_cb_invoked = 0; - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { return 0; }; + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) -> uint32_t { return 0; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { enqueue_cb_invoked += 1; osi_free(p_buf); return false; @@ -161,9 +161,9 @@ TEST_F(A2dpAacTest, a2dp_source_read_underflow) { TEST_F(A2dpAacTest, a2dp_enqueue_cb_is_invoked) { static int enqueue_cb_invoked = 0; - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { return len; }; + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { enqueue_cb_invoked += 1; osi_free(p_buf); return false; @@ -178,7 +178,7 @@ TEST_F(A2dpAacTest, a2dp_enqueue_cb_is_invoked) { } TEST_F(A2dpAacTest, decoded_data_cb_not_invoked_when_empty_packet) { - auto data_cb = +[](uint8_t* p_buf, uint32_t len) { FAIL(); }; + auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) { FAIL(); }; InitializeDecoder(data_cb); std::vector data; BT_HDR* packet = AllocateL2capPacket(data); @@ -190,7 +190,7 @@ TEST_F(A2dpAacTest, decoded_data_cb_invoked) { static int data_cb_invoked = 0; static int enqueue_cb_invoked = 0; - auto data_cb = +[](uint8_t* p_buf, uint32_t len) { data_cb_invoked += 1; }; + auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) { data_cb_invoked += 1; }; InitializeDecoder(data_cb); @@ -201,7 +201,7 @@ TEST_F(A2dpAacTest, decoded_data_cb_invoked) { return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { enqueue_cb_invoked += 1; packet = p_buf; return false; @@ -234,11 +234,11 @@ TEST_F(A2dpAacTest, sink_supports_aac) { } TEST_F(A2dpAacTest, effective_mtu_when_peer_supports_3mbps) { - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { log::assert_that(kAacReadSize == len, "assert failed: kAacReadSize == len"); return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { osi_free(p_buf); return false; }; @@ -247,11 +247,11 @@ TEST_F(A2dpAacTest, effective_mtu_when_peer_supports_3mbps) { } TEST_F(A2dpAacTest, effective_mtu_when_peer_does_not_support_3mbps) { - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { log::assert_that(kAacReadSize == len, "assert failed: kAacReadSize == len"); return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { osi_free(p_buf); return false; }; diff --git a/system/stack/test/a2dp/a2dp_opus_unittest.cc b/system/stack/test/a2dp/a2dp_opus_unittest.cc index b0d79f3ecc2..eb517fd9a84 100644 --- a/system/stack/test/a2dp/a2dp_opus_unittest.cc +++ b/system/stack/test/a2dp/a2dp_opus_unittest.cc @@ -133,11 +133,11 @@ protected: TEST_F(A2dpOpusTest, a2dp_source_read_underflow) { promise = {}; - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) -> uint32_t { // underflow return 0; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { promise.set_value(); osi_free(p_buf); return false; @@ -154,11 +154,11 @@ TEST_F(A2dpOpusTest, a2dp_source_read_underflow) { TEST_F(A2dpOpusTest, a2dp_enqueue_cb_is_invoked) { promise = {}; - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { log::assert_that(GetReadSize() == len, "assert failed: GetReadSize() == len"); return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { static bool first_invocation = true; if (first_invocation) { promise.set_value(); @@ -177,7 +177,7 @@ TEST_F(A2dpOpusTest, a2dp_enqueue_cb_is_invoked) { } TEST_F(A2dpOpusTest, decoded_data_cb_not_invoked_when_empty_packet) { - auto data_cb = +[](uint8_t* p_buf, uint32_t len) { FAIL(); }; + auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) { FAIL(); }; InitializeDecoder(data_cb); std::vector data; BT_HDR* packet = AllocateL2capPacket(data); @@ -187,7 +187,7 @@ TEST_F(A2dpOpusTest, decoded_data_cb_not_invoked_when_empty_packet) { TEST_F(A2dpOpusTest, decoded_data_cb_invoked) { promise = {}; - auto data_cb = +[](uint8_t* p_buf, uint32_t len) {}; + auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) {}; InitializeDecoder(data_cb); auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { @@ -196,7 +196,7 @@ TEST_F(A2dpOpusTest, decoded_data_cb_invoked) { counter += len; return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t /*len*/) -> bool { static bool first_invocation = true; if (first_invocation) { packet = reinterpret_cast(osi_malloc(sizeof(*p_buf) + p_buf->len + 1)); diff --git a/system/stack/test/a2dp/a2dp_sbc_unittest.cc b/system/stack/test/a2dp/a2dp_sbc_unittest.cc index 89e76bd7a3a..950a6100ddc 100644 --- a/system/stack/test/a2dp/a2dp_sbc_unittest.cc +++ b/system/stack/test/a2dp/a2dp_sbc_unittest.cc @@ -141,11 +141,11 @@ protected: TEST_F(A2dpSbcTest, a2dp_source_read_underflow) { promise = {}; - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) -> uint32_t { // underflow return 0; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { promise.set_value(); osi_free(p_buf); return false; @@ -162,11 +162,11 @@ TEST_F(A2dpSbcTest, a2dp_source_read_underflow) { TEST_F(A2dpSbcTest, a2dp_enqueue_cb_is_invoked) { promise = {}; - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { log::assert_that(kSbcReadSize == len, "assert failed: kSbcReadSize == len"); return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { static bool first_invocation = true; if (first_invocation) { promise.set_value(); @@ -185,7 +185,7 @@ TEST_F(A2dpSbcTest, a2dp_enqueue_cb_is_invoked) { } TEST_F(A2dpSbcTest, decoded_data_cb_not_invoked_when_empty_packet) { - auto data_cb = +[](uint8_t* p_buf, uint32_t len) { FAIL(); }; + auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) { FAIL(); }; InitializeDecoder(data_cb); std::vector data; BT_HDR* packet = AllocateL2capPacket(data); @@ -195,7 +195,7 @@ TEST_F(A2dpSbcTest, decoded_data_cb_not_invoked_when_empty_packet) { TEST_F(A2dpSbcTest, decoded_data_cb_invoked) { promise = {}; - auto data_cb = +[](uint8_t* p_buf, uint32_t len) {}; + auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) {}; InitializeDecoder(data_cb); auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { @@ -204,7 +204,7 @@ TEST_F(A2dpSbcTest, decoded_data_cb_invoked) { counter += len; return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t /*len*/) -> bool { static bool first_invocation = true; if (first_invocation) { packet = reinterpret_cast(osi_malloc(sizeof(*p_buf) + p_buf->len + 1)); @@ -244,11 +244,11 @@ TEST_F(A2dpSbcTest, sink_supports_sbc) { } TEST_F(A2dpSbcTest, effective_mtu_when_peer_supports_3mbps) { - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { log::assert_that(kSbcReadSize == len, "assert failed: kSbcReadSize == len"); return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { osi_free(p_buf); return false; }; @@ -257,11 +257,11 @@ TEST_F(A2dpSbcTest, effective_mtu_when_peer_supports_3mbps) { } TEST_F(A2dpSbcTest, effective_mtu_when_peer_does_not_support_3mbps) { - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { log::assert_that(kSbcReadSize == len, "assert failed: kSbcReadSize == len"); return len; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool { osi_free(p_buf); return false; }; diff --git a/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc b/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc index 90b00507f18..d446d808acc 100644 --- a/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc +++ b/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc @@ -124,9 +124,9 @@ protected: TEST_F(A2dpLdacTest, a2dp_source_read_underflow) { static int enqueue_cb_invoked = 0; - auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { return 0; }; + auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) -> uint32_t { return 0; }; - auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool { + auto enqueue_cb = +[](BT_HDR* /*p_buf*/, size_t /*frames_n*/, uint32_t /*len*/) -> bool { enqueue_cb_invoked += 1; return false; }; diff --git a/system/stack/test/a2dp/misc_fake.cc b/system/stack/test/a2dp/misc_fake.cc index 4c583807f09..ee82394629f 100644 --- a/system/stack/test/a2dp/misc_fake.cc +++ b/system/stack/test/a2dp/misc_fake.cc @@ -16,6 +16,6 @@ #include "stack/include/a2dp_vendor_ldac.h" -int A2DP_VendorGetTrackSampleRateLdac(const uint8_t* p_codec_info) { return 0; } -int A2DP_VendorGetTrackBitsPerSampleLdac(const uint8_t* p_codec_info) { return 0; } -int A2DP_VendorGetChannelModeCodeLdac(const uint8_t* p_codec_info) { return 0; } +int A2DP_VendorGetTrackSampleRateLdac(const uint8_t* /*p_codec_info*/) { return 0; } +int A2DP_VendorGetTrackBitsPerSampleLdac(const uint8_t* /*p_codec_info*/) { return 0; } +int A2DP_VendorGetChannelModeCodeLdac(const uint8_t* /*p_codec_info*/) { return 0; } diff --git a/system/stack/test/common/mock_btm_layer.cc b/system/stack/test/common/mock_btm_layer.cc index acfb6357a62..129b58ce183 100644 --- a/system/stack/test/common/mock_btm_layer.cc +++ b/system/stack/test/common/mock_btm_layer.cc @@ -33,9 +33,11 @@ void bluetooth::manager::SetMockSecurityInternalInterface( btm_security_internal_interface = mock_btm_security_internal_interface; } -uint16_t BTM_GetMaxPacketSize(const RawAddress& addr) { return RFCOMM_DEFAULT_MTU; } +uint16_t BTM_GetMaxPacketSize(const RawAddress& /*addr*/) { return RFCOMM_DEFAULT_MTU; } -bool BTM_IsAclConnectionUp(const RawAddress& remote_bda, tBT_TRANSPORT transport) { return true; } +bool BTM_IsAclConnectionUp(const RawAddress& /*remote_bda*/, tBT_TRANSPORT /*transport*/) { + return true; +} struct btm_client_interface_t btm_client_interface = { .peer = diff --git a/system/stack/test/common/mock_l2cap_layer.cc b/system/stack/test/common/mock_l2cap_layer.cc index c2c6ab18a00..b61b80c5675 100644 --- a/system/stack/test/common/mock_l2cap_layer.cc +++ b/system/stack/test/common/mock_l2cap_layer.cc @@ -32,11 +32,11 @@ void bluetooth::l2cap::SetMockInterface(MockL2capInterface* mock_l2cap_interface l2cap_interface = mock_l2cap_interface; } -tL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) { return nullptr; } +tL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* /*p_lcb*/, uint16_t /*local_cid*/) { return nullptr; } uint16_t L2CA_Register(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, bool enable_snoop, - tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu, uint16_t required_remote_mtu, - uint16_t sec_level) { + tL2CAP_ERTM_INFO* p_ertm_info, uint16_t /*my_mtu*/, + uint16_t /*required_remote_mtu*/, uint16_t /*sec_level*/) { bluetooth::log::verbose("psm={}, enable_snoop={}", psm, enable_snoop); return l2cap_interface->Register(psm, p_cb_info, enable_snoop, p_ertm_info); } @@ -62,7 +62,7 @@ tL2CAP_DW_RESULT L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) { } uint16_t L2CA_RegisterLECoc(uint16_t psm, const tL2CAP_APPL_INFO& cb_info, uint16_t sec_level, - tL2CAP_LE_CFG_INFO cfg) { + tL2CAP_LE_CFG_INFO /*cfg*/) { return l2cap_interface->RegisterLECoc(psm, cb_info, sec_level); } diff --git a/system/stack/test/common/mock_stack_avdt_msg.cc b/system/stack/test/common/mock_stack_avdt_msg.cc index 76ff6ac8c46..22a5afce902 100644 --- a/system/stack/test/common/mock_stack_avdt_msg.cc +++ b/system/stack/test/common/mock_stack_avdt_msg.cc @@ -30,7 +30,7 @@ static std::vector _rsp_sig_ids{}; -void avdt_msg_send_rsp(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) { +void avdt_msg_send_rsp(AvdtpCcb* /*p_ccb*/, uint8_t sig_id, tAVDT_MSG* /*p_params*/) { inc_func_call_count(__func__); _rsp_sig_ids.push_back(sig_id); } @@ -41,15 +41,16 @@ void mock_avdt_msg_send_rsp_clear_history(void) { _rsp_sig_ids.clear(); } uint8_t mock_avdt_msg_send_rsp_get_sig_id_at(size_t nth) { return _rsp_sig_ids[nth]; } -void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf) { inc_func_call_count(__func__); } +void avdt_msg_ind(AvdtpCcb* /*p_ccb*/, BT_HDR* /*p_buf*/) { inc_func_call_count(__func__); } -void avdt_msg_send_rej(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) { +void avdt_msg_send_rej(AvdtpCcb* /*p_ccb*/, uint8_t /*sig_id*/, tAVDT_MSG* /*p_params*/) { inc_func_call_count(__func__); } static std::vector _cmd_sig_ids{}; -void avdt_msg_send_cmd(AvdtpCcb* p_ccb, void* p_scb, uint8_t sig_id, tAVDT_MSG* p_params) { +void avdt_msg_send_cmd(AvdtpCcb* /*p_ccb*/, void* /*p_scb*/, uint8_t sig_id, + tAVDT_MSG* /*p_params*/) { inc_func_call_count(__func__); _cmd_sig_ids.push_back(sig_id); } @@ -60,7 +61,7 @@ void mock_avdt_msg_send_cmd_clear_history(void) { _cmd_sig_ids.clear(); } uint8_t mock_avdt_msg_send_cmd_get_sig_id_at(size_t nth) { return _cmd_sig_ids[nth]; } -bool avdt_msg_send(AvdtpCcb* p_ccb, BT_HDR* p_msg) { +bool avdt_msg_send(AvdtpCcb* /*p_ccb*/, BT_HDR* /*p_msg*/) { inc_func_call_count(__func__); return true; } diff --git a/system/stack/test/eatt/eatt_test.cc b/system/stack/test/eatt/eatt_test.cc index 0965fc59877..437a2f13ef3 100644 --- a/system/stack/test/eatt/eatt_test.cc +++ b/system/stack/test/eatt/eatt_test.cc @@ -59,10 +59,10 @@ extern struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_; /* Needed for testing context */ static tGATT_TCB test_tcb; -void btif_storage_add_eatt_supported(const RawAddress& addr) { return; } -void gatt_consolidate(const RawAddress& identity_addr, const RawAddress& rpa) {} -void gatt_data_process(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf) { return; } -tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& bda, tBT_TRANSPORT transport) { +void btif_storage_add_eatt_supported(const RawAddress& /*addr*/) { return; } +void gatt_consolidate(const RawAddress& /*identity_addr*/, const RawAddress& /*rpa*/) {} +void gatt_data_process(tGATT_TCB& /*tcb*/, uint16_t /*cid*/, BT_HDR* /*p_buf*/) { return; } +tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& /*bda*/, tBT_TRANSPORT /*transport*/) { log::info(""); return &test_tcb; } @@ -80,7 +80,7 @@ protected: std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK); return true; }); - EXPECT_CALL(gatt_interface_, GetEattSupport).WillRepeatedly([](const RawAddress& addr) { + EXPECT_CALL(gatt_interface_, GetEattSupport).WillRepeatedly([](const RawAddress& /*addr*/) { return true; }); @@ -137,14 +137,14 @@ protected: ON_CALL(gatt_interface_, ClientReadSupportedFeatures) .WillByDefault( - [&eatt_supp_feat_cb](const RawAddress& addr, + [&eatt_supp_feat_cb](const RawAddress& /*addr*/, base::OnceCallback cb) { eatt_supp_feat_cb = std::move(cb); return true; }); // Return false to trigger supported features request - ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& addr) { + ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) { return false; }); @@ -297,7 +297,8 @@ TEST_F(EattTest, IncomingEattConnectionByUnknownDevice) { std::vector incoming_cids{71, 72, 73, 74, 75}; ON_CALL(btm_api_interface_, IsEncrypted) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return true; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; }); EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectCreditBasedRsp(test_address, 1, incoming_cids, tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_CONN_OK, _)) @@ -312,14 +313,15 @@ TEST_F(EattTest, IncomingEattConnectionByUnknownDevice) { TEST_F(EattTest, IncomingEattConnectionByKnownDevice) { hci_role_ = HCI_ROLE_PERIPHERAL; ON_CALL(btm_api_interface_, IsEncrypted) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return true; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; }); ON_CALL(gatt_interface_, ClientReadSupportedFeatures) .WillByDefault([](const RawAddress& addr, base::OnceCallback cb) { std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK); return true; }); - ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& addr) { + ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) { return true; }); @@ -342,16 +344,18 @@ TEST_F(EattTest, IncomingEattConnectionByKnownDevice) { TEST_F(EattTest, IncomingEattConnectionByKnownDeviceEncryptionOff) { hci_role_ = HCI_ROLE_PERIPHERAL; ON_CALL(btm_api_interface_, IsEncrypted) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return false; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return false; }); ON_CALL(btm_api_interface_, IsLinkKeyKnown) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return true; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; }); ON_CALL(gatt_interface_, ClientReadSupportedFeatures) .WillByDefault([](const RawAddress& addr, base::OnceCallback cb) { std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK); return true; }); - ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& addr) { + ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) { return true; }); @@ -374,9 +378,11 @@ TEST_F(EattTest, IncomingEattConnectionByUnknownDeviceEncryptionOff) { std::vector incoming_cids{71, 72, 73, 74, 75}; ON_CALL(btm_api_interface_, IsEncrypted) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return false; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return false; }); ON_CALL(btm_api_interface_, IsLinkKeyKnown) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return false; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return false; }); EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectCreditBasedRsp( test_address, 1, _, @@ -393,7 +399,8 @@ TEST_F(EattTest, ReconnectInitiatedByRemoteSucceed) { std::vector incoming_cids{71, 72, 73, 74, 75}; ON_CALL(btm_api_interface_, IsEncrypted) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return true; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; }); EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectCreditBasedRsp(test_address, 1, incoming_cids, @@ -408,7 +415,8 @@ TEST_F(EattTest, ReconnectInitiatedByRemoteSucceed) { TEST_F(EattTest, ConnectInitiatedWhenRemoteConnects) { ON_CALL(btm_api_interface_, IsEncrypted) - .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) { return true; }); + .WillByDefault( + [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; }); std::vector incoming_cids{71, 72, 73, 74}; ConnectDeviceBothSides(1, incoming_cids); @@ -432,7 +440,7 @@ TEST_F(EattTest, ConnectFailedEattNotSupported) { std::move(cb).Run(addr, 0); return true; }); - ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& addr) { + ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) { return false; }); diff --git a/system/stack/test/gatt/gatt_sr_test.cc b/system/stack/test/gatt/gatt_sr_test.cc index 72707e1900c..7992f876ea3 100644 --- a/system/stack/test/gatt/gatt_sr_test.cc +++ b/system/stack/test/gatt/gatt_sr_test.cc @@ -53,67 +53,77 @@ TestMutables test_state_; } // namespace namespace connection_manager { -bool background_connect_remove(uint8_t app_id, const RawAddress& address) { return false; } -bool direct_connect_remove(uint8_t app_id, const RawAddress& address, bool connection_timeout) { +bool background_connect_remove(uint8_t /*app_id*/, const RawAddress& /*address*/) { return false; } +bool direct_connect_remove(uint8_t /*app_id*/, const RawAddress& /*address*/, + bool /*connection_timeout*/) { return false; } -bool is_background_connection(const RawAddress& address) { return false; } +bool is_background_connection(const RawAddress& /*address*/) { return false; } } // namespace connection_manager -BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code, tGATT_SR_MSG* p_msg, - uint16_t payload_size) { +BT_HDR* attp_build_sr_msg(tGATT_TCB& /*tcb*/, uint8_t op_code, tGATT_SR_MSG* /*p_msg*/, + uint16_t /*payload_size*/) { test_state_.attp_build_sr_msg.op_code_ = op_code; return nullptr; } -tGATT_STATUS attp_send_cl_confirmation_msg(tGATT_TCB& tcb, uint16_t cid) { return GATT_SUCCESS; } -tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, - tGATT_CL_MSG* p_msg) { +tGATT_STATUS attp_send_cl_confirmation_msg(tGATT_TCB& /*tcb*/, uint16_t /*cid*/) { return GATT_SUCCESS; } -tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_msg) { return GATT_SUCCESS; } - -void gatt_act_discovery(tGATT_CLCB* p_clcb) {} -bool gatt_disconnect(tGATT_TCB* p_tcb) { return false; } -void gatt_cancel_connect(const RawAddress& bd_addr, tBT_TRANSPORT transport) {} -tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* p_tcb) { return GATT_CH_CLOSE; } -tGATT_STATUS gatts_db_read_attr_value_by_type(tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, - uint8_t op_code, BT_HDR* p_rsp, uint16_t s_handle, - uint16_t e_handle, const Uuid& type, uint16_t* p_len, - tGATT_SEC_FLAG sec_flag, uint8_t key_size, - uint32_t trans_id, uint16_t* p_cur_handle) { +tGATT_STATUS attp_send_cl_msg(tGATT_TCB& /*tcb*/, tGATT_CLCB* /*p_clcb*/, uint8_t /*op_code*/, + tGATT_CL_MSG* /*p_msg*/) { return GATT_SUCCESS; } -void gatt_set_ch_state(tGATT_TCB* p_tcb, tGATT_CH_STATE ch_state) {} -Uuid* gatts_get_service_uuid(tGATT_SVC_DB* p_db) { return nullptr; } -tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle, uint16_t val_len, - uint8_t* p_val) { +tGATT_STATUS attp_send_sr_msg(tGATT_TCB& /*tcb*/, uint16_t /*cid*/, BT_HDR* /*p_msg*/) { return GATT_SUCCESS; } -tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long, uint16_t handle, - tGATT_SEC_FLAG sec_flag, uint8_t key_size) { + +void gatt_act_discovery(tGATT_CLCB* /*p_clcb*/) {} +bool gatt_disconnect(tGATT_TCB* /*p_tcb*/) { return false; } +void gatt_cancel_connect(const RawAddress& /*bd_addr*/, tBT_TRANSPORT /*transport*/) {} +tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* /*p_tcb*/) { return GATT_CH_CLOSE; } +tGATT_STATUS gatts_db_read_attr_value_by_type(tGATT_TCB& /*tcb*/, uint16_t /*cid*/, + tGATT_SVC_DB* /*p_db*/, uint8_t /*op_code*/, + BT_HDR* /*p_rsp*/, uint16_t /*s_handle*/, + uint16_t /*e_handle*/, const Uuid& /*type*/, + uint16_t* /*p_len*/, tGATT_SEC_FLAG /*sec_flag*/, + uint8_t /*key_size*/, uint32_t /*trans_id*/, + uint16_t* /*p_cur_handle*/) { + return GATT_SUCCESS; +} +void gatt_set_ch_state(tGATT_TCB* /*p_tcb*/, tGATT_CH_STATE /*ch_state*/) {} +Uuid* gatts_get_service_uuid(tGATT_SVC_DB* /*p_db*/) { return nullptr; } +tGATT_STATUS GATTS_HandleValueIndication(uint16_t /*conn_id*/, uint16_t /*attr_handle*/, + uint16_t /*val_len*/, uint8_t* /*p_val*/) { + return GATT_SUCCESS; +} +tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* /*p_db*/, bool /*is_long*/, + uint16_t /*handle*/, tGATT_SEC_FLAG /*sec_flag*/, + uint8_t /*key_size*/) { return GATT_SUCCESS; } -tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB& tcb, uint16_t cid, tGATT_SVC_DB* p_db, - uint8_t op_code, uint16_t handle, uint16_t offset, - uint8_t* p_value, uint16_t* p_len, uint16_t mtu, - tGATT_SEC_FLAG sec_flag, uint8_t key_size, - uint32_t trans_id) { +tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB& /*tcb*/, uint16_t /*cid*/, + tGATT_SVC_DB* /*p_db*/, uint8_t /*op_code*/, + uint16_t /*handle*/, uint16_t /*offset*/, + uint8_t* /*p_value*/, uint16_t* /*p_len*/, + uint16_t /*mtu*/, tGATT_SEC_FLAG /*sec_flag*/, + uint8_t /*key_size*/, uint32_t /*trans_id*/) { return GATT_SUCCESS; } -tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, - uint16_t offset, uint8_t* p_data, uint16_t len, - tGATT_SEC_FLAG sec_flag, uint8_t key_size) { +tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* /*p_db*/, uint8_t /*op_code*/, + uint16_t /*handle*/, uint16_t /*offset*/, + uint8_t* /*p_data*/, uint16_t /*len*/, + tGATT_SEC_FLAG /*sec_flag*/, uint8_t /*key_size*/) { test_state_.gatts_write_attr_perm_check.access_count_++; return test_state_.gatts_write_attr_perm_check.return_status_; } -void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb, bool is_add, - bool check_acl_link) {} +void gatt_update_app_use_link_flag(tGATT_IF /*gatt_if*/, tGATT_TCB* /*p_tcb*/, bool /*is_add*/, + bool /*check_acl_link*/) {} bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; } -void l2cble_set_fixed_channel_tx_data_length(const RawAddress& remote_bda, uint16_t fix_cid, - uint16_t tx_mtu) {} -void L2CA_SetLeFixedChannelTxDataLength(const RawAddress& remote_bda, uint16_t fix_cid, - uint16_t tx_mtu) {} +void l2cble_set_fixed_channel_tx_data_length(const RawAddress& /*remote_bda*/, uint16_t /*fix_cid*/, + uint16_t /*tx_mtu*/) {} +void L2CA_SetLeFixedChannelTxDataLength(const RawAddress& /*remote_bda*/, uint16_t /*fix_cid*/, + uint16_t /*tx_mtu*/) {} void ApplicationRequestCallback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA* p_data) { test_state_.application_request_callback.conn_id_ = conn_id; @@ -122,8 +132,8 @@ void ApplicationRequestCallback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_ test_state_.application_request_callback.data_ = *p_data; } -bool gatt_sr_is_cl_change_aware(tGATT_TCB& tcb) { return false; } -void gatt_sr_init_cl_status(tGATT_TCB& p_tcb) {} +bool gatt_sr_is_cl_change_aware(tGATT_TCB& /*tcb*/) { return false; } +void gatt_sr_init_cl_status(tGATT_TCB& /*p_tcb*/) {} void gatt_sr_update_cl_status(tGATT_TCB& p_tcb, bool chg_aware) { p_tcb.is_robust_cache_change_aware = chg_aware; } diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc index 564a2e555a6..f79db0ac3d8 100644 --- a/system/stack/test/gatt/mock_gatt_utils_ref.cc +++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc @@ -20,6 +20,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" /** stack/gatt/connection_manager.cc */ namespace connection_manager { diff --git a/system/stack/test/gatt/stack_gatt_test.cc b/system/stack/test/gatt/stack_gatt_test.cc index 2a6b243d43e..0a5c40d9208 100644 --- a/system/stack/test/gatt/stack_gatt_test.cc +++ b/system/stack/test/gatt/stack_gatt_test.cc @@ -68,20 +68,23 @@ size_t actual_sizeof_tGATT_REG() { sizeof(uint8_t) + sizeof(bool); } -void tGATT_DISC_RES_CB(uint16_t conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES* p_data) {} -void tGATT_DISC_CMPL_CB(uint16_t conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status) {} -void tGATT_CMPL_CBACK(uint16_t conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, - tGATT_CL_COMPLETE* p_data) {} -void tGATT_CONN_CBACK(tGATT_IF gatt_if, const RawAddress& bda, uint16_t conn_id, bool connected, - tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport) {} -void tGATT_REQ_CBACK(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, - tGATTS_DATA* p_data) {} -void tGATT_CONGESTION_CBACK(uint16_t conn_id, bool congested) {} -void tGATT_ENC_CMPL_CB(tGATT_IF gatt_if, const RawAddress& bda) {} -void tGATT_PHY_UPDATE_CB(tGATT_IF gatt_if, uint16_t conn_id, uint8_t tx_phy, uint8_t rx_phy, - tGATT_STATUS status) {} -void tGATT_CONN_UPDATE_CB(tGATT_IF gatt_if, uint16_t conn_id, uint16_t interval, uint16_t latency, - uint16_t timeout, tGATT_STATUS status) {} +void tGATT_DISC_RES_CB(uint16_t /*conn_id*/, tGATT_DISC_TYPE /*disc_type*/, + tGATT_DISC_RES* /*p_data*/) {} +void tGATT_DISC_CMPL_CB(uint16_t /*conn_id*/, tGATT_DISC_TYPE /*disc_type*/, + tGATT_STATUS /*status*/) {} +void tGATT_CMPL_CBACK(uint16_t /*conn_id*/, tGATTC_OPTYPE /*op*/, tGATT_STATUS /*status*/, + tGATT_CL_COMPLETE* /*p_data*/) {} +void tGATT_CONN_CBACK(tGATT_IF /*gatt_if*/, const RawAddress& /*bda*/, uint16_t /*conn_id*/, + bool /*connected*/, tGATT_DISCONN_REASON /*reason*/, + tBT_TRANSPORT /*transport*/) {} +void tGATT_REQ_CBACK(uint16_t /*conn_id*/, uint32_t /*trans_id*/, tGATTS_REQ_TYPE /*type*/, + tGATTS_DATA* /*p_data*/) {} +void tGATT_CONGESTION_CBACK(uint16_t /*conn_id*/, bool /*congested*/) {} +void tGATT_ENC_CMPL_CB(tGATT_IF /*gatt_if*/, const RawAddress& /*bda*/) {} +void tGATT_PHY_UPDATE_CB(tGATT_IF /*gatt_if*/, uint16_t /*conn_id*/, uint8_t /*tx_phy*/, + uint8_t /*rx_phy*/, tGATT_STATUS /*status*/) {} +void tGATT_CONN_UPDATE_CB(tGATT_IF /*gatt_if*/, uint16_t /*conn_id*/, uint16_t /*interval*/, + uint16_t /*latency*/, uint16_t /*timeout*/, tGATT_STATUS /*status*/) {} tGATT_CBACK gatt_callbacks = { .p_conn_cb = tGATT_CONN_CBACK, diff --git a/system/stack/test/gatt_connection_manager_test.cc b/system/stack/test/gatt_connection_manager_test.cc index e7912106083..e5a85967102 100644 --- a/system/stack/test/gatt_connection_manager_test.cc +++ b/system/stack/test/gatt_connection_manager_test.cc @@ -69,15 +69,16 @@ void BTM_BleTargetAnnouncementObserve(bool enable, tBTM_INQ_RESULTS_CB* p_result localAcceptlistMock->EnableTargetedAnnouncements(enable, p_results_cb); } -void BTM_LogHistory(const std::string& tag, const RawAddress& bd_addr, const std::string& msg) {} +void BTM_LogHistory(const std::string& /*tag*/, const RawAddress& /*bd_addr*/, + const std::string& /*msg*/) {} namespace bluetooth { namespace shim { -void set_target_announcements_filter(bool enable) {} +void set_target_announcements_filter(bool /*enable*/) {} } // namespace shim } // namespace bluetooth -bool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& bd_addr) { return false; } +bool L2CA_ConnectFixedChnl(uint16_t /*fixed_cid*/, const RawAddress& /*bd_addr*/) { return false; } uint16_t BTM_GetHCIConnHandle(RawAddress const&, unsigned char) { return 0xFFFF; } namespace connection_manager { @@ -85,7 +86,7 @@ class BleConnectionManager : public testing::Test { void SetUp() override { localAcceptlistMock = std::make_unique(); auto alarm_mock = AlarmMock::Get(); - ON_CALL(*alarm_mock, AlarmNew(_)).WillByDefault(testing::Invoke([](const char* name) { + ON_CALL(*alarm_mock, AlarmNew(_)).WillByDefault(testing::Invoke([](const char* /*name*/) { // We must return something from alarm_new in tests, if we just return // null, unique_ptr will misbehave. return (alarm_t*)new uint8_t[30]; diff --git a/system/stack/test/stack_avdtp_test.cc b/system/stack/test/stack_avdtp_test.cc index 3ecc82f0505..8c9372ec938 100644 --- a/system/stack/test/stack_avdtp_test.cc +++ b/system/stack/test/stack_avdtp_test.cc @@ -40,19 +40,20 @@ protected: static uint8_t scb_handle_; protected: - static void AvdtConnCallback(uint8_t handle, const RawAddress& bd_addr, uint8_t event, - tAVDT_CTRL* p_data, uint8_t scb_index) { + static void AvdtConnCallback(uint8_t /*handle*/, const RawAddress& /*bd_addr*/, uint8_t event, + tAVDT_CTRL* /*p_data*/, uint8_t /*scb_index*/) { inc_func_call_count(__func__); callback_event_ = event; } - static void StreamCtrlCallback(uint8_t handle, const RawAddress& bd_addr, uint8_t event, - tAVDT_CTRL* p_data, uint8_t scb_index) { + static void StreamCtrlCallback(uint8_t /*handle*/, const RawAddress& /*bd_addr*/, uint8_t event, + tAVDT_CTRL* /*p_data*/, uint8_t /*scb_index*/) { inc_func_call_count(__func__); callback_event_ = event; } - static void AvdtReportCallback(uint8_t handle, AVDT_REPORT_TYPE type, tAVDT_REPORT_DATA* p_data) { + static void AvdtReportCallback(uint8_t /*handle*/, AVDT_REPORT_TYPE /*type*/, + tAVDT_REPORT_DATA* /*p_data*/) { inc_func_call_count(__func__); } diff --git a/system/stack/test/stack_smp_test.cc b/system/stack/test/stack_smp_test.cc index 31a006d2496..c7de45814c0 100644 --- a/system/stack/test/stack_smp_test.cc +++ b/system/stack/test/stack_smp_test.cc @@ -201,16 +201,16 @@ public: TEST_F(SmpCalculateConfirmTest, test_smp_gen_p2_4_confirm_as_central) { // Set local_bda to 0xA1A2A3A4A5A6 test::mock::stack_acl::BTM_ReadConnectionAddr.body = - [](const RawAddress& remote_bda, RawAddress& local_conn_addr, tBLE_ADDR_TYPE* p_addr_type, - bool ota_address) { + [](const RawAddress& /*remote_bda*/, RawAddress& local_conn_addr, + tBLE_ADDR_TYPE* p_addr_type, bool /*ota_address*/) { local_conn_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6}); *p_addr_type = BLE_ADDR_RANDOM; }; // Set remote bda to 0xB1B2B3B4B5B6 test::mock::stack_acl::BTM_ReadRemoteConnectionAddr.body = - [](const RawAddress& pseudo_addr, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, - bool ota_address) { + [](const RawAddress& /*pseudo_addr*/, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, + bool /*ota_address*/) { conn_addr = RawAddress({0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6}); *p_addr_type = BLE_ADDR_PUBLIC; return true; @@ -235,16 +235,16 @@ TEST_F(SmpCalculateConfirmTest, test_smp_gen_p2_4_confirm_as_central) { TEST_F(SmpCalculateConfirmTest, test_aes_128_as_central) { // Set local_bda to 0xA1A2A3A4A5A6 test::mock::stack_acl::BTM_ReadConnectionAddr.body = - [](const RawAddress& remote_bda, RawAddress& local_conn_addr, tBLE_ADDR_TYPE* p_addr_type, - bool ota_address) { + [](const RawAddress& /*remote_bda*/, RawAddress& local_conn_addr, + tBLE_ADDR_TYPE* p_addr_type, bool /*ota_address*/) { local_conn_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6}); *p_addr_type = BLE_ADDR_RANDOM; }; // Set remote bda to 0xB1B2B3B4B5B6 test::mock::stack_acl::BTM_ReadRemoteConnectionAddr.body = - [](const RawAddress& pseudo_addr, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, - bool ota_address) { + [](const RawAddress& /*pseudo_addr*/, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, + bool /*ota_address*/) { conn_addr = RawAddress({0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6}); *p_addr_type = BLE_ADDR_PUBLIC; return true; @@ -280,16 +280,16 @@ TEST_F(SmpCalculateConfirmTest, test_aes_128_as_central) { TEST_F(SmpCalculateConfirmTest, test_smp_calculate_confirm_as_central) { // Set local_bda to 0xA1A2A3A4A5A6 test::mock::stack_acl::BTM_ReadConnectionAddr.body = - [](const RawAddress& remote_bda, RawAddress& local_conn_addr, tBLE_ADDR_TYPE* p_addr_type, - bool ota_address) { + [](const RawAddress& /*remote_bda*/, RawAddress& local_conn_addr, + tBLE_ADDR_TYPE* p_addr_type, bool /*ota_address*/) { local_conn_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6}); *p_addr_type = BLE_ADDR_RANDOM; }; // Set remote bda to 0xB1B2B3B4B5B6 test::mock::stack_acl::BTM_ReadRemoteConnectionAddr.body = - [](const RawAddress& pseudo_addr, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, - bool ota_address) { + [](const RawAddress& /*pseudo_addr*/, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, + bool /*ota_address*/) { conn_addr = RawAddress({0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6}); *p_addr_type = BLE_ADDR_PUBLIC; return true; diff --git a/system/test/stub/osi.cc b/system/test/stub/osi.cc index cae495f2ca1..fcfa858a917 100644 --- a/system/test/stub/osi.cc +++ b/system/test/stub/osi.cc @@ -44,6 +44,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wunused-parameter" OsiObject::OsiObject(void* ptr) : ptr_(ptr) {} -- GitLab From f34fcc41bf3095fac235e082c1251f72c88a0255 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 7 Oct 2024 21:37:54 +0000 Subject: [PATCH 201/875] system/osi/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I4f6606d631127025a487223abf02f5ce0cdaac4f --- system/osi/Android.bp | 7 +++---- system/osi/test/alarm_test.cc | 4 ++-- system/osi/test/fixed_queue_test.cc | 2 +- system/osi/test/wakelock_test.cc | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/system/osi/Android.bp b/system/osi/Android.bp index 04e9a1f8390..aeabc7ad182 100644 --- a/system/osi/Android.bp +++ b/system/osi/Android.bp @@ -104,6 +104,9 @@ cc_test { "fluoride_osi_defaults", "mts_defaults", ], + cflags: [ + "-DLIB_OSI_INTERNAL", + ], host_supported: true, srcs: [ "test/alarm_test.cc", @@ -155,10 +158,6 @@ cc_test { ], }, }, - cflags: [ - "-DLIB_OSI_INTERNAL", - "-Wno-unused-parameter", - ], sanitize: { address: true, cfi: false, diff --git a/system/osi/test/alarm_test.cc b/system/osi/test/alarm_test.cc index a7538a99041..cf98d2dcdc5 100644 --- a/system/osi/test/alarm_test.cc +++ b/system/osi/test/alarm_test.cc @@ -50,12 +50,12 @@ extern int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS; static bool is_wake_lock_acquired = false; -static int acquire_wake_lock_cb(const char* lock_name) { +static int acquire_wake_lock_cb(const char* /*lock_name*/) { is_wake_lock_acquired = true; return BT_STATUS_SUCCESS; } -static int release_wake_lock_cb(const char* lock_name) { +static int release_wake_lock_cb(const char* /*lock_name*/) { is_wake_lock_acquired = false; return BT_STATUS_SUCCESS; } diff --git a/system/osi/test/fixed_queue_test.cc b/system/osi/test/fixed_queue_test.cc index 2efd7a3dc0e..867b8e5d289 100644 --- a/system/osi/test/fixed_queue_test.cc +++ b/system/osi/test/fixed_queue_test.cc @@ -41,7 +41,7 @@ static void fixed_queue_ready(fixed_queue_t* queue, void* /* context */) { future_ready(received_message_future, msg); } -static void test_queue_entry_free_cb(void* data) { +static void test_queue_entry_free_cb(void* /*data*/) { // Don't free the data, because we are testing only whether the callback // is called. test_queue_entry_free_counter++; diff --git a/system/osi/test/wakelock_test.cc b/system/osi/test/wakelock_test.cc index 2596553d66d..6fb00990e68 100644 --- a/system/osi/test/wakelock_test.cc +++ b/system/osi/test/wakelock_test.cc @@ -26,12 +26,12 @@ static bool is_wake_lock_acquired = false; -static int acquire_wake_lock_cb(const char* lock_name) { +static int acquire_wake_lock_cb(const char* /*lock_name*/) { is_wake_lock_acquired = true; return BT_STATUS_SUCCESS; } -static int release_wake_lock_cb(const char* lock_name) { +static int release_wake_lock_cb(const char* /*lock_name*/) { is_wake_lock_acquired = false; return BT_STATUS_SUCCESS; } -- GitLab From d245e0fbd985fcc963b2a0cf8c530659df344a4b Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 7 Oct 2024 22:20:23 +0000 Subject: [PATCH 202/875] system/audio_hal_interface/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I05abbbb8a62cbb8eab1375a94e9b1c1c37745bf8 --- system/audio_hal_interface/Android.bp | 3 - .../audio_hal_interface/a2dp_encoding_host.cc | 34 ++++----- .../hearing_aid_software_encoding_aidl.cc | 4 +- .../aidl/hfp_client_interface_aidl.cc | 15 ++-- .../hearing_aid_software_encoding_host.cc | 6 +- .../hfp_client_interface.cc | 6 +- .../hfp_client_interface_host.cc | 16 ++--- .../hfp_client_interface_unittest.cc | 72 ++++++++++--------- .../le_audio_software_host.cc | 23 +++--- .../le_audio_software_host_transport.cc | 3 +- 10 files changed, 92 insertions(+), 90 deletions(-) diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index af82b6498cb..1e5652c747d 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -77,7 +77,6 @@ cc_library_static { }, host_supported: true, cflags: [ - "-Wno-unused-parameter", "-Wthread-safety", ], apex_available: [ @@ -140,7 +139,6 @@ cc_test { ], cflags: [ "-DUNIT_TESTS", - "-Wno-unused-parameter", ], host_supported: true, test_options: { @@ -381,6 +379,5 @@ cc_test { header_libs: ["libbluetooth_headers"], cflags: [ "-DBUILDCFG", - "-Wno-unused-parameter", ], } diff --git a/system/audio_hal_interface/a2dp_encoding_host.cc b/system/audio_hal_interface/a2dp_encoding_host.cc index 9ec22cbbdd6..e9bb1873399 100644 --- a/system/audio_hal_interface/a2dp_encoding_host.cc +++ b/system/audio_hal_interface/a2dp_encoding_host.cc @@ -216,8 +216,8 @@ void set_remote_delay(uint16_t delay_report) { remote_delay_report_ = delay_repo // Inform audio server about offloading codec; not used for now bool update_codec_offloading_capabilities( - const std::vector& framework_preference, - bool supports_a2dp_hw_offload_v2) { + const std::vector& /*framework_preference*/, + bool /*supports_a2dp_hw_offload_v2*/) { return false; } @@ -231,8 +231,8 @@ static BluetoothAudioPort null_audio_port; static BluetoothAudioPort const* bluetooth_audio_port = &null_audio_port; // Initialize BluetoothAudio HAL: openProvider -bool init(bluetooth::common::MessageLoopThread* message_loop, BluetoothAudioPort const* audio_port, - bool /*offload_enabled*/) { +bool init(bluetooth::common::MessageLoopThread* /*message_loop*/, + BluetoothAudioPort const* audio_port, bool /*offload_enabled*/) { a2dp_uipc = UIPC_Init(); total_bytes_read_ = 0; data_position_ = {}; @@ -273,7 +273,7 @@ void end_session() { a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; } -void set_audio_low_latency_mode_allowed(bool allowed) {} +void set_audio_low_latency_mode_allowed(bool /*allowed*/) {} void ack_stream_started(BluetoothAudioStatus /*ack*/) { a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; @@ -305,12 +305,12 @@ bool is_opus_supported() { return true; } namespace provider { // Lookup the codec info in the list of supported offloaded sink codecs. -std::optional sink_codec_index(const uint8_t* p_codec_info) { +std::optional sink_codec_index(const uint8_t* /*p_codec_info*/) { return std::nullopt; } // Lookup the codec info in the list of supported offloaded source codecs. -std::optional source_codec_index(const uint8_t* p_codec_info) { +std::optional source_codec_index(const uint8_t* /*p_codec_info*/) { return std::nullopt; } @@ -320,17 +320,17 @@ std::optional source_codec_index(const uint8_t* p_codec // BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN..BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX. // Returns nullopt if the codec_index is not assigned or codec extensibility // is not supported or enabled. -std::optional codec_index_str(btav_a2dp_codec_index_t codec_index) { +std::optional codec_index_str(btav_a2dp_codec_index_t /*codec_index*/) { return std::nullopt; } // Return true if the codec is supported for the session type // A2DP_HARDWARE_ENCODING_DATAPATH or A2DP_HARDWARE_DECODING_DATAPATH. -bool supports_codec(btav_a2dp_codec_index_t codec_index) { return false; } +bool supports_codec(btav_a2dp_codec_index_t /*codec_index*/) { return false; } // Return the A2DP capabilities for the selected codec. -bool codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_config) { +bool codec_info(btav_a2dp_codec_index_t /*codec_index*/, uint64_t* /*codec_id*/, + uint8_t* /*codec_info*/, btav_a2dp_codec_config_t* /*codec_config*/) { return false; } @@ -338,8 +338,8 @@ bool codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, uint8_t // The HAL is expected to pick the best audio configuration based on the // discovered remote SEPs. std::optional get_a2dp_configuration( - RawAddress peer_address, std::vector const& remote_seps, - btav_a2dp_codec_config_t const& user_preferences) { + RawAddress /*peer_address*/, std::vector const& /*remote_seps*/, + btav_a2dp_codec_config_t const& /*user_preferences*/) { return std::nullopt; } @@ -350,10 +350,10 @@ std::optional get_a2dp_configuration( // In case any of these checks fails, the corresponding A2DP // status is returned. If the configuration is valid and supported, // A2DP_OK is returned. -tA2DP_STATUS parse_a2dp_configuration(btav_a2dp_codec_index_t codec_index, - const uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_parameters, - std::vector* vendor_specific_parameters) { +tA2DP_STATUS parse_a2dp_configuration(btav_a2dp_codec_index_t /*codec_index*/, + const uint8_t* /*codec_info*/, + btav_a2dp_codec_config_t* /*codec_parameters*/, + std::vector* /*vendor_specific_parameters*/) { return A2DP_FAIL; } diff --git a/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc b/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc index d3bc52f93cd..64f4d3d6e44 100644 --- a/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc @@ -55,7 +55,7 @@ public: total_bytes_read_(0), data_position_({}) {} - BluetoothAudioCtrlAck StartRequest(bool is_low_latency) override { + BluetoothAudioCtrlAck StartRequest(bool /*is_low_latency*/) override { log::info(""); if (stream_cb_.on_resume_(true)) { return BluetoothAudioCtrlAck::SUCCESS_FINISHED; @@ -83,7 +83,7 @@ public: } } - void SetLatencyMode(LatencyMode latency_mode) override {} + void SetLatencyMode(LatencyMode /*latency_mode*/) override {} bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, timespec* data_position) override { diff --git a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc index b35cda1746c..c1a72fa0f26 100644 --- a/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/hfp_client_interface_aidl.cc @@ -176,7 +176,7 @@ void HfpTransport::ResetPendingCmd() { hfp_pending_cmd_ = HFP_CTRL_CMD_NONE; } uint8_t HfpTransport::GetPendingCmd() const { return hfp_pending_cmd_; } // Unimplemented functions -void HfpTransport::LogBytesProcessed(size_t bytes_read) {} +void HfpTransport::LogBytesProcessed(size_t /*bytes_read*/) {} BluetoothAudioCtrlAck HfpTransport::SuspendRequest() { log::info("handling"); @@ -209,16 +209,17 @@ BluetoothAudioCtrlAck HfpTransport::SuspendRequest() { } } -void HfpTransport::SetLatencyMode(LatencyMode latency_mode) {} +void HfpTransport::SetLatencyMode(LatencyMode /*latency_mode*/) {} -void HfpTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) {} +void HfpTransport::SourceMetadataChanged(const source_metadata_v7_t& /*source_metadata*/) {} void HfpTransport::SinkMetadataChanged(const sink_metadata_v7_t&) {} void HfpTransport::ResetPresentationPosition() {} -bool HfpTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns, - uint64_t* total_bytes_read, timespec* data_position) { +bool HfpTransport::GetPresentationPosition(uint64_t* /*remote_delay_report_ns*/, + uint64_t* /*total_bytes_read*/, + timespec* /*data_position*/) { return false; } @@ -230,7 +231,7 @@ HfpDecodingTransport::HfpDecodingTransport(SessionType session_type) HfpDecodingTransport::~HfpDecodingTransport() { delete transport_; } -BluetoothAudioCtrlAck HfpDecodingTransport::StartRequest(bool is_low_latency) { +BluetoothAudioCtrlAck HfpDecodingTransport::StartRequest(bool /*is_low_latency*/) { return transport_->StartRequest(); } @@ -285,7 +286,7 @@ HfpEncodingTransport::HfpEncodingTransport(SessionType session_type) HfpEncodingTransport::~HfpEncodingTransport() { delete transport_; } -BluetoothAudioCtrlAck HfpEncodingTransport::StartRequest(bool is_low_latency) { +BluetoothAudioCtrlAck HfpEncodingTransport::StartRequest(bool /*is_low_latency*/) { return transport_->StartRequest(); } diff --git a/system/audio_hal_interface/hearing_aid_software_encoding_host.cc b/system/audio_hal_interface/hearing_aid_software_encoding_host.cc index a085b650d7a..b56f1f689c2 100644 --- a/system/audio_hal_interface/hearing_aid_software_encoding_host.cc +++ b/system/audio_hal_interface/hearing_aid_software_encoding_host.cc @@ -22,7 +22,7 @@ namespace hearing_aid { bool is_hal_enabled() { return false; } -bool init(StreamCallbacks stream_cb, bluetooth::common::MessageLoopThread* message_loop) { +bool init(StreamCallbacks /*stream_cb*/, bluetooth::common::MessageLoopThread* /*message_loop*/) { return false; } @@ -32,9 +32,9 @@ void start_session() {} void end_session() {} -size_t read(uint8_t* p_buf, uint32_t len) { return 0; } +size_t read(uint8_t* /*p_buf*/, uint32_t /*len*/) { return 0; } -void set_remote_delay(uint16_t delay_report_ms) {} +void set_remote_delay(uint16_t /*delay_report_ms*/) {} } // namespace hearing_aid } // namespace audio diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index 9a61e6722b6..22e6b993730 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -168,7 +168,7 @@ void HfpClientInterface::Decode::StopSession() { } void HfpClientInterface::Decode::UpdateAudioConfigToHal( - const ::hfp::offload_config& offload_config) { + const ::hfp::offload_config& /*offload_config*/) { log::warn( "'UpdateAudioConfigToHal(offload_config)' should not be called on " "HfpClientInterface::Decode"); @@ -335,7 +335,7 @@ void HfpClientInterface::Encode::StopSession() { } void HfpClientInterface::Encode::UpdateAudioConfigToHal( - const ::hfp::offload_config& offload_config) { + const ::hfp::offload_config& /*offload_config*/) { log::warn( "'UpdateAudioConfigToHal(offload_config)' should not be called on " "HfpClientInterface::Encode"); @@ -519,7 +519,7 @@ void HfpClientInterface::Offload::UpdateAudioConfigToHal( offload_config_to_hal_audio_config(offload_config)); } -void HfpClientInterface::Offload::UpdateAudioConfigToHal(const ::hfp::pcm_config& pcm_config) { +void HfpClientInterface::Offload::UpdateAudioConfigToHal(const ::hfp::pcm_config& /*pcm_config*/) { log::warn( "'UpdateAudioConfigToHal(pcm_config)' should not be called on " "HfpClientInterface::Offload"); diff --git a/system/audio_hal_interface/hfp_client_interface_host.cc b/system/audio_hal_interface/hfp_client_interface_host.cc index c48822065d6..6a552ac1de1 100644 --- a/system/audio_hal_interface/hfp_client_interface_host.cc +++ b/system/audio_hal_interface/hfp_client_interface_host.cc @@ -21,25 +21,25 @@ namespace audio { namespace hfp { HfpClientInterface::Decode* HfpClientInterface::GetDecode( - bluetooth::common::MessageLoopThread* message_loop) { + bluetooth::common::MessageLoopThread* /*message_loop*/) { return nullptr; } -bool HfpClientInterface::ReleaseDecode(HfpClientInterface::Decode* decode) { return false; } +bool HfpClientInterface::ReleaseDecode(HfpClientInterface::Decode* /*decode*/) { return false; } HfpClientInterface::Encode* HfpClientInterface::GetEncode( - bluetooth::common::MessageLoopThread* message_loop) { + bluetooth::common::MessageLoopThread* /*message_loop*/) { return nullptr; } -bool HfpClientInterface::ReleaseEncode(HfpClientInterface::Encode* encode) { return false; } +bool HfpClientInterface::ReleaseEncode(HfpClientInterface::Encode* /*encode*/) { return false; } HfpClientInterface::Offload* HfpClientInterface::GetOffload( - bluetooth::common::MessageLoopThread* message_loop) { + bluetooth::common::MessageLoopThread* /*message_loop*/) { return nullptr; } -bool HfpClientInterface::ReleaseOffload(HfpClientInterface::Offload* offload) { return false; } +bool HfpClientInterface::ReleaseOffload(HfpClientInterface::Offload* /*offload*/) { return false; } HfpClientInterface* HfpClientInterface::Get() { return nullptr; } @@ -48,9 +48,9 @@ HfpClientInterface::Offload::GetHfpScoConfig() { return std::unordered_map(); } -size_t HfpClientInterface::Encode::Read(uint8_t* p_buf, uint32_t len) { return 0; } +size_t HfpClientInterface::Encode::Read(uint8_t* /*p_buf*/, uint32_t /*len*/) { return 0; } -size_t HfpClientInterface::Decode::Write(const uint8_t* p_buf, uint32_t len) { return 0; } +size_t HfpClientInterface::Decode::Write(const uint8_t* /*p_buf*/, uint32_t /*len*/) { return 0; } } // namespace hfp } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/hfp_client_interface_unittest.cc b/system/audio_hal_interface/hfp_client_interface_unittest.cc index 64f31265bca..16687920804 100644 --- a/system/audio_hal_interface/hfp_client_interface_unittest.cc +++ b/system/audio_hal_interface/hfp_client_interface_unittest.cc @@ -63,7 +63,7 @@ BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface( : BluetoothAudioClientInterface{sink}, sink_(sink) {} BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() {} -size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, uint32_t len) { +size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* /*p_buf*/, uint32_t len) { sink_client_read_called = true; return len; } @@ -73,33 +73,34 @@ BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface( : BluetoothAudioClientInterface{source}, source_(source) {} BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() {} -size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, uint32_t len) { +size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* /*p_buf*/, uint32_t len) { source_client_write_called = true; return len; } bool BluetoothAudioClientInterface::IsValid() const { return true; } -bool BluetoothAudioClientInterface::SetAllowedLatencyModes(std::vector latency_modes) { +bool BluetoothAudioClientInterface::SetAllowedLatencyModes( + std::vector /*latency_modes*/) { return false; } void BluetoothAudioClientInterface::FlushAudioData() {} -bool BluetoothAudioClientInterface::UpdateAudioConfig(const AudioConfiguration& audio_config) { +bool BluetoothAudioClientInterface::UpdateAudioConfig(const AudioConfiguration& /*audio_config*/) { return false; } int BluetoothAudioClientInterface::StartSession() { return -EINVAL; } -void BluetoothAudioClientInterface::StreamStarted(const BluetoothAudioCtrlAck& ack) {} +void BluetoothAudioClientInterface::StreamStarted(const BluetoothAudioCtrlAck& /*ack*/) {} int BluetoothAudioClientInterface::EndSession() { return -EINVAL; } -void BluetoothAudioClientInterface::StreamSuspended(const BluetoothAudioCtrlAck& ack) {} +void BluetoothAudioClientInterface::StreamSuspended(const BluetoothAudioCtrlAck& /*ack*/) {} std::vector BluetoothAudioClientInterface::GetAudioCapabilities( - SessionType session_type) { + SessionType /*session_type*/) { return std::vector(0); } @@ -107,11 +108,11 @@ std::vector BluetoothAudioClientInterface::GetLeAudioAseConfiguration( std::optional< std::vector>>& - remoteSinkAudioCapabilities, + /*remoteSinkAudioCapabilities*/, std::optional< std::vector>>& - remoteSourceAudioCapabilities, - std::vector& requirements) { + /*remoteSourceAudioCapabilities*/, + std::vector& /*requirements*/) { return std::vector(); } @@ -119,12 +120,12 @@ IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting BluetoothAudioClientInterface::getLeAudioBroadcastConfiguration( const std::optional< std::vector>>& - remoteSinkAudioCapabilities, - const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& requirement) { + /*remoteSinkAudioCapabilities*/, + const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& /*requirement*/) { return IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting(); } -std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) { return os; } +std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& /*ack*/) { return os; } namespace hfp { @@ -138,21 +139,22 @@ BluetoothAudioCtrlAck HfpTransport::StartRequest() { void HfpTransport::StopRequest() {} void HfpTransport::ResetPendingCmd() {} uint8_t HfpTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; } -void HfpTransport::LogBytesProcessed(size_t bytes_read) {} +void HfpTransport::LogBytesProcessed(size_t /*bytes_read*/) {} BluetoothAudioCtrlAck HfpTransport::SuspendRequest() { return BluetoothAudioCtrlAck::SUCCESS_FINISHED; } -void HfpTransport::SetLatencyMode(LatencyMode latency_mode) {} -void HfpTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) {} +void HfpTransport::SetLatencyMode(LatencyMode /*latency_mode*/) {} +void HfpTransport::SourceMetadataChanged(const source_metadata_v7_t& /*source_metadata*/) {} void HfpTransport::SinkMetadataChanged(const sink_metadata_v7_t&) {} void HfpTransport::ResetPresentationPosition() {} -bool HfpTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns, - uint64_t* total_bytes_read, timespec* data_position) { +bool HfpTransport::GetPresentationPosition(uint64_t* /*remote_delay_report_ns*/, + uint64_t* /*total_bytes_read*/, + timespec* /*data_position*/) { return false; } std::unordered_map HfpTransport::GetHfpScoConfig( - SessionType sessionType) { + SessionType /*sessionType*/) { return std::unordered_map{}; } @@ -161,22 +163,22 @@ HfpDecodingTransport::HfpDecodingTransport(SessionType session_type) : IBluetoothSourceTransportInstance(session_type, (AudioConfiguration){}) {} HfpDecodingTransport::~HfpDecodingTransport() {} -BluetoothAudioCtrlAck HfpDecodingTransport::StartRequest(bool is_low_latency) { +BluetoothAudioCtrlAck HfpDecodingTransport::StartRequest(bool /*is_low_latency*/) { return BluetoothAudioCtrlAck::SUCCESS_FINISHED; } BluetoothAudioCtrlAck HfpDecodingTransport::SuspendRequest() { return BluetoothAudioCtrlAck::SUCCESS_FINISHED; } -void HfpDecodingTransport::SetLatencyMode(LatencyMode latency_mode) {} -bool HfpDecodingTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns, - uint64_t* total_bytes_written, - timespec* data_position) { +void HfpDecodingTransport::SetLatencyMode(LatencyMode /*latency_mode*/) {} +bool HfpDecodingTransport::GetPresentationPosition(uint64_t* /*remote_delay_report_ns*/, + uint64_t* /*total_bytes_written*/, + timespec* /*data_position*/) { return false; } -void HfpDecodingTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) {} -void HfpDecodingTransport::SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) {} +void HfpDecodingTransport::SourceMetadataChanged(const source_metadata_v7_t& /*source_metadata*/) {} +void HfpDecodingTransport::SinkMetadataChanged(const sink_metadata_v7_t& /*sink_metadata*/) {} void HfpDecodingTransport::ResetPresentationPosition() {} -void HfpDecodingTransport::LogBytesWritten(size_t bytes_written) {} +void HfpDecodingTransport::LogBytesWritten(size_t /*bytes_written*/) {} uint8_t HfpDecodingTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; } void HfpDecodingTransport::ResetPendingCmd() {} void HfpDecodingTransport::StopRequest() {} @@ -185,24 +187,24 @@ bool HfpDecodingTransport::IsStreamActive() { return decoding_transport_is_strea HfpEncodingTransport::HfpEncodingTransport(SessionType session_type) : IBluetoothSinkTransportInstance(session_type, (AudioConfiguration){}) {} HfpEncodingTransport::~HfpEncodingTransport() {} -BluetoothAudioCtrlAck HfpEncodingTransport::StartRequest(bool is_low_latency) { +BluetoothAudioCtrlAck HfpEncodingTransport::StartRequest(bool /*is_low_latency*/) { return BluetoothAudioCtrlAck::SUCCESS_FINISHED; } BluetoothAudioCtrlAck HfpEncodingTransport::SuspendRequest() { return BluetoothAudioCtrlAck::SUCCESS_FINISHED; } void HfpEncodingTransport::StopRequest() {} -void HfpEncodingTransport::SetLatencyMode(LatencyMode latency_mode) {} -bool HfpEncodingTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns, - uint64_t* total_bytes_written, - timespec* data_position) { +void HfpEncodingTransport::SetLatencyMode(LatencyMode /*latency_mode*/) {} +bool HfpEncodingTransport::GetPresentationPosition(uint64_t* /*remote_delay_report_ns*/, + uint64_t* /*total_bytes_written*/, + timespec* /*data_position*/) { return false; } -void HfpEncodingTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) {} -void HfpEncodingTransport::SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) {} +void HfpEncodingTransport::SourceMetadataChanged(const source_metadata_v7_t& /*source_metadata*/) {} +void HfpEncodingTransport::SinkMetadataChanged(const sink_metadata_v7_t& /*sink_metadata*/) {} void HfpEncodingTransport::ResetPresentationPosition() {} -void HfpEncodingTransport::LogBytesRead(size_t bytes_written) {} +void HfpEncodingTransport::LogBytesRead(size_t /*bytes_written*/) {} uint8_t HfpEncodingTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; } void HfpEncodingTransport::ResetPendingCmd() {} bool HfpEncodingTransport::IsStreamActive() { return encoding_transport_is_stream_active_ret; } diff --git a/system/audio_hal_interface/le_audio_software_host.cc b/system/audio_hal_interface/le_audio_software_host.cc index cc8e561bfac..28f2592a6c9 100644 --- a/system/audio_hal_interface/le_audio_software_host.cc +++ b/system/audio_hal_interface/le_audio_software_host.cc @@ -305,10 +305,10 @@ void LeAudioClientInterface::Sink::CancelStreamingRequest() { } void LeAudioClientInterface::Sink::UpdateAudioConfigToHal( - const ::le_audio::offload_config& offload_config) {} + const ::le_audio::offload_config& /*offload_config*/) {} void LeAudioClientInterface::Sink::UpdateBroadcastAudioConfigToHal( - ::le_audio::broadcast_offload_config const& config) {} + ::le_audio::broadcast_offload_config const& /*config*/) {} void LeAudioClientInterface::Sink::SuspendedForReconfiguration() { log::info(""); @@ -329,16 +329,17 @@ size_t LeAudioClientInterface::Sink::Read(uint8_t* p_buf, uint32_t len) { std::optional<::bluetooth::le_audio::set_configurations::AudioSetConfiguration> LeAudioClientInterface::Sink::GetUnicastConfig( - const ::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements& requirements) - const { + const ::bluetooth::le_audio::CodecManager:: + UnicastConfigurationRequirements& /*requirements*/) const { return std::nullopt; } std::optional<::bluetooth::le_audio::broadcaster::BroadcastConfiguration> LeAudioClientInterface::Sink::GetBroadcastConfig( - const std::vector>& - subgroup_quality, - const std::optional>& pacs) const { + const std::vector>& /*subgroup_quality*/, + const std::optional>& /*pacs*/) + const { return std::nullopt; } @@ -456,7 +457,7 @@ void LeAudioClientInterface::Source::CancelStreamingRequest() { } void LeAudioClientInterface::Source::UpdateAudioConfigToHal( - const ::le_audio::offload_config& offload_config) {} + const ::le_audio::offload_config& /*offload_config*/) {} void LeAudioClientInterface::Source::SuspendedForReconfiguration() { log::info(""); @@ -471,7 +472,7 @@ size_t LeAudioClientInterface::Source::Write(const uint8_t* p_buf, uint32_t len) } LeAudioClientInterface::Sink* LeAudioClientInterface::GetSink( - StreamCallbacks stream_cb, bluetooth::common::MessageLoopThread* message_loop, + StreamCallbacks stream_cb, bluetooth::common::MessageLoopThread* /*message_loop*/, bool is_broadcasting_session_type) { if (is_broadcasting_session_type && !LeAudioHalVerifier::SupportsLeAudioBroadcast()) { log::warn("No support for broadcasting Le Audio"); @@ -517,7 +518,7 @@ bool LeAudioClientInterface::ReleaseSink(LeAudioClientInterface::Sink* sink) { } LeAudioClientInterface::Source* LeAudioClientInterface::GetSource( - StreamCallbacks stream_cb, bluetooth::common::MessageLoopThread* message_loop) { + StreamCallbacks stream_cb, bluetooth::common::MessageLoopThread* /*message_loop*/) { if (source_ == nullptr) { source_ = new Source(); } else { @@ -567,7 +568,7 @@ LeAudioClientInterface* LeAudioClientInterface::Get() { return LeAudioClientInterface::interface; } -void LeAudioClientInterface::SetAllowedDsaModes(DsaModes dsa_modes) { return; } +void LeAudioClientInterface::SetAllowedDsaModes(DsaModes /*dsa_modes*/) { return; } } // namespace le_audio } // namespace audio diff --git a/system/audio_hal_interface/le_audio_software_host_transport.cc b/system/audio_hal_interface/le_audio_software_host_transport.cc index e3eb36a06af..16796ec3038 100644 --- a/system/audio_hal_interface/le_audio_software_host_transport.cc +++ b/system/audio_hal_interface/le_audio_software_host_transport.cc @@ -267,7 +267,8 @@ bool LeAudioSourceTransport::GetPresentationPosition(uint64_t* remote_delay_repo data_position); } -void LeAudioSourceTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) {} +void LeAudioSourceTransport::SourceMetadataChanged( + const source_metadata_v7_t& /*source_metadata*/) {} void LeAudioSourceTransport::SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) { transport_->SinkMetadataChanged(sink_metadata); -- GitLab From 8b5c129cc59a2c456c72c2335191d34f80f02980 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 7 Oct 2024 23:43:37 +0000 Subject: [PATCH 203/875] system/device/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I4ecec1e87d37bbecea8976053f0198a7a6ec863e --- system/device/Android.bp | 1 - system/device/test/device_iot_config_test.cc | 391 ++++++++++--------- 2 files changed, 204 insertions(+), 188 deletions(-) diff --git a/system/device/Android.bp b/system/device/Android.bp index f4b06790fc1..4753441a666 100644 --- a/system/device/Android.bp +++ b/system/device/Android.bp @@ -111,5 +111,4 @@ cc_test { "server_configurable_flags", ], header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } diff --git a/system/device/test/device_iot_config_test.cc b/system/device/test/device_iot_config_test.cc index 676fad4888e..58bc3a34259 100644 --- a/system/device/test/device_iot_config_test.cc +++ b/system/device/test/device_iot_config_test.cc @@ -41,19 +41,19 @@ using namespace testing; extern module_t device_iot_config_module; -bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event, char* p_params, - int param_len, tBTIF_COPY_CBACK* p_copy_cback) { +bt_status_t btif_transfer_context(tBTIF_CBACK* /*p_cback*/, uint16_t /*event*/, char* /*p_params*/, + int /*param_len*/, tBTIF_COPY_CBACK* /*p_copy_cback*/) { inc_func_call_count(__func__); return BT_STATUS_SUCCESS; } struct alarm_t { - alarm_t(const char* name) {} + alarm_t(const char* /*name*/) {} int any_value; }; struct future_t { - future_t(void* value) {} + future_t(void* /*value*/) {} void* value; }; @@ -64,23 +64,24 @@ std::string true_val = "true"; class DeviceIotConfigModuleTest : public testing::Test { protected: void SetUp() override { - test::mock::osi_alarm::alarm_new.body = [&](const char* name) -> alarm_t* { + test::mock::osi_alarm::alarm_new.body = [&](const char* /*name*/) -> alarm_t* { return &placeholder_alarm; }; test::mock::osi_properties::osi_property_get_bool.body = - [&](const char* key, bool default_value) -> int { return false; }; + [&](const char* /*key*/, bool /*default_value*/) -> int { return false; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) { return; }; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, + void* /*data*/) { return; }; - test::mock::osi_alarm::alarm_free.body = [](alarm_t* alarm) {}; + test::mock::osi_alarm::alarm_free.body = [](alarm_t* /*alarm*/) {}; - test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* alarm) -> bool { + test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { return false; }; - test::mock::osi_future::future_new_immediate.body = [&](void* value) -> future_t* { + test::mock::osi_future::future_new_immediate.body = [&](void* /*value*/) -> future_t* { return &placeholder_future; }; @@ -89,27 +90,27 @@ protected: }; test::mock::osi_config::config_new.body = - [&](const char* filename) -> std::unique_ptr { + [&](const char* /*filename*/) -> std::unique_ptr { return std::make_unique(); }; test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return def_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, int def_value) { return def_value; }; - test::mock::osi_config::config_set_int.body = [&](config_t* config, const std::string& section, - const std::string& key, - int value) { return; }; + test::mock::osi_config::config_set_int.body = + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + int /*value*/) { return; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return def_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, const std::string* def_value) { return def_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, - const std::string& value) { return; }; + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + const std::string& /*value*/) { return; }; - test::mock::osi_allocator::osi_free.body = [&](void* ptr) {}; + test::mock::osi_allocator::osi_free.body = [&](void* /*ptr*/) {}; reset_mock_function_count_map(); } @@ -138,9 +139,9 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ config_t* config_new_empty_return_value = NULL; test::mock::osi_properties::osi_property_get_bool.body = - [&](const char* key, bool default_value) -> int { return is_factory_reset; }; + [&](const char* /*key*/, bool /*default_value*/) -> int { return is_factory_reset; }; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -193,7 +194,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_no_config, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(nullptr); }; @@ -223,7 +224,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -242,12 +243,14 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ std::string config_get_string_return_value(TIME_STRING_FORMAT); test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return config_get_int_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + int /*def_value*/) { return config_get_int_return_value; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return &config_get_string_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + const std::string* /*def_value*/) { return &config_get_string_return_value; }; device_iot_config_module_init(); @@ -294,12 +297,14 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ std::string config_get_string_return_value(TIME_STRING_FORMAT); test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return config_get_int_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + int /*def_value*/) { return config_get_int_return_value; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return &config_get_string_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + const std::string* /*def_value*/) { return &config_get_string_return_value; }; device_iot_config_module_init(); @@ -324,7 +329,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -342,8 +347,9 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ std::string config_get_string_return_value(TIME_STRING_FORMAT); test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return &config_get_string_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + const std::string* /*def_value*/) { return &config_get_string_return_value; }; device_iot_config_module_init(); @@ -368,7 +374,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -387,12 +393,14 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ std::string config_get_string_return_value(TIME_STRING_FORMAT); test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return config_get_int_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + int /*def_value*/) { return config_get_int_return_value; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return &config_get_string_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + const std::string* /*def_value*/) { return &config_get_string_return_value; }; device_iot_config_module_init(); @@ -418,7 +426,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -437,12 +445,14 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, std::string config_get_string_return_value(TIME_STRING_FORMAT); test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return config_get_int_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + int /*def_value*/) { return config_get_int_return_value; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return &config_get_string_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + const std::string* /*def_value*/) { return &config_get_string_return_value; }; int file_fd = -1; int backup_fd = -1; @@ -493,7 +503,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -512,12 +522,14 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, std::string config_get_string_return_value(TIME_STRING_FORMAT); test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return config_get_int_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + int /*def_value*/) { return config_get_int_return_value; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return &config_get_string_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + const std::string* /*def_value*/) { return &config_get_string_return_value; }; int file_fd = -1; int backup_fd = -1; @@ -568,7 +580,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -586,12 +598,13 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, int config_get_int_return_value = DEVICE_IOT_INFO_CURRENT_VERSION; test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return config_get_int_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + int /*def_value*/) { return config_get_int_return_value; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return nullptr; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, const std::string* /*def_value*/) { return nullptr; }; device_iot_config_module_init(); @@ -616,7 +629,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; - test::mock::osi_config::config_new.body = [&](const char* filename) { + test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr(config_new_return_value); }; @@ -635,14 +648,16 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ std::string config_get_string_return_value(TIME_STRING_FORMAT); test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return config_get_int_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + int /*def_value*/) { return config_get_int_return_value; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return &config_get_string_return_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, + const std::string* /*def_value*/) { return &config_get_string_return_value; }; - test::mock::osi_alarm::alarm_new.body = [&](const char* name) { return nullptr; }; + test::mock::osi_alarm::alarm_new.body = [&](const char* /*name*/) { return nullptr; }; device_iot_config_module_init(); @@ -690,7 +705,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_shutd std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; - test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* alarm) -> bool { + test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { return return_value; }; @@ -736,7 +751,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_clean std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; - test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* alarm) -> bool { + test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { return return_value; }; @@ -781,23 +796,24 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_clean class DeviceIotConfigTest : public testing::Test { protected: void SetUp() override { - test::mock::osi_alarm::alarm_new.body = [&](const char* name) -> alarm_t* { + test::mock::osi_alarm::alarm_new.body = [&](const char* /*name*/) -> alarm_t* { return &placeholder_alarm; }; test::mock::osi_properties::osi_property_get_bool.body = - [&](const char* key, bool default_value) -> int { return false; }; + [&](const char* /*key*/, bool /*default_value*/) -> int { return false; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) { return; }; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, + void* /*data*/) { return; }; - test::mock::osi_alarm::alarm_free.body = [](alarm_t* alarm) {}; + test::mock::osi_alarm::alarm_free.body = [](alarm_t* /*alarm*/) {}; - test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* alarm) -> bool { + test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { return false; }; - test::mock::osi_future::future_new_immediate.body = [&](void* value) -> future_t* { + test::mock::osi_future::future_new_immediate.body = [&](void* /*value*/) -> future_t* { return &placeholder_future; }; @@ -806,27 +822,27 @@ protected: }; test::mock::osi_config::config_new.body = - [&](const char* filename) -> std::unique_ptr { + [&](const char* /*filename*/) -> std::unique_ptr { return std::make_unique(); }; test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return def_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, int def_value) { return def_value; }; - test::mock::osi_config::config_set_int.body = [&](config_t* config, const std::string& section, - const std::string& key, - int value) { return; }; + test::mock::osi_config::config_set_int.body = + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + int /*value*/) { return; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return def_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, const std::string* def_value) { return def_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, - const std::string& value) { return; }; + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + const std::string& /*value*/) { return; }; - test::mock::osi_allocator::osi_free.body = [&](void* ptr) {}; + test::mock::osi_allocator::osi_free.body = [&](void* /*ptr*/) {}; device_iot_config_module_init(); device_iot_config_module_start_up(); @@ -915,7 +931,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_has_section, std::string actual_section, expected_section = "abc"; bool return_value = false; - test::mock::osi_config::config_has_section.body = [&](const config_t& config, + test::mock::osi_config::config_has_section.body = [&](const config_t& /*config*/, const std::string& section) { actual_section = section; return return_value; @@ -949,7 +965,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_exist, bool return_value = false; test::mock::osi_config::config_has_key.body = - [&](const config_t& config, const std::string& section, const std::string& key) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key) { actual_section = section; actual_key = key; return return_value; @@ -986,7 +1002,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_has_key_value, const std::string* return_value = NULL; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, + [&](const config_t& /*config*/, const std::string& section, const std::string& key, const std::string* def_value) { actual_section = section; actual_key = key; @@ -1072,15 +1088,15 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_int, int int_value = 0, new_value = 0xff; test::mock::osi_config::config_has_key.body = - [&](const config_t& config, const std::string& section, const std::string& key) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key) { actual_section = section; actual_key = key; return return_value; }; test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return new_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, int /*def_value*/) { return new_value; }; { reset_mock_function_count_map(); @@ -1120,15 +1136,15 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_get_int, int int_value = 0, new_value = 0xff; test::mock::osi_config::config_has_key.body = - [&](const config_t& config, const std::string& section, const std::string& key) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key) { actual_section = section; actual_key = key; return return_value; }; test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return new_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, int /*def_value*/) { return new_value; }; { reset_mock_function_count_map(); @@ -1168,19 +1184,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_int, int int_value = 123456789; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return &string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -1225,19 +1241,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_int, int int_value = 123456789; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return &string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -1276,7 +1292,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_int_add_one, std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; int int_value = 0, get_default_value, set_value; - test::mock::osi_config::config_get_int.body = [&](const config_t& config, + test::mock::osi_config::config_get_int.body = [&](const config_t& /*config*/, const std::string& section, const std::string& key, int def_value) { actual_section = section; @@ -1285,12 +1301,12 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_int_add_one, return int_value; }; - test::mock::osi_config::config_set_int.body = [&](config_t* config, const std::string& section, - const std::string& key, - int val) { set_value = val; }; + test::mock::osi_config::config_set_int.body = + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + int val) { set_value = val; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -1385,7 +1401,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_int_add_one, expected_key = "def"; int int_value = 0, get_default_value, set_value; - test::mock::osi_config::config_get_int.body = [&](const config_t& config, + test::mock::osi_config::config_get_int.body = [&](const config_t& /*config*/, const std::string& section, const std::string& key, int def_value) { actual_section = section; @@ -1394,12 +1410,12 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_int_add_one, return int_value; }; - test::mock::osi_config::config_set_int.body = [&](config_t* config, const std::string& section, - const std::string& key, - int val) { set_value = val; }; + test::mock::osi_config::config_set_int.body = + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + int val) { set_value = val; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -1495,8 +1511,8 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_hex, std::string* get_string_return_value = NULL; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; @@ -1656,8 +1672,8 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_get_hex, std::string* get_string_return_value = NULL; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; @@ -1813,19 +1829,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_hex, int int_value, byte_num; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -1964,19 +1980,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_hex, int byte_num = 1; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -2117,19 +2133,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_hex_if_gr int byte_num = 1; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -2198,7 +2214,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_str, const std::string* return_value = NULL; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, + [&](const config_t& /*config*/, const std::string& section, const std::string& key, const std::string* def_value) { actual_section = section; actual_key = key; @@ -2257,19 +2273,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_str, std::string str_value; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -2322,19 +2338,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_str, std::string str_value; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; { reset_mock_function_count_map(); @@ -2382,7 +2398,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_bin, const std::string* return_value = NULL; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, + [&](const config_t& /*config*/, const std::string& section, const std::string& key, const std::string* def_value) { actual_section = section; actual_key = key; @@ -2489,7 +2505,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_bin_length, const std::string* return_value = NULL; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, + [&](const config_t& /*config*/, const std::string& section, const std::string& key, const std::string* def_value) { actual_section = section; actual_key = key; @@ -2569,19 +2585,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_bin, std::string str_value; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; test::mock::osi_allocator::osi_calloc.body = [&](size_t size) { return new char[size]; }; @@ -2644,7 +2660,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_bin, { reset_mock_function_count_map(); - test::mock::osi_allocator::osi_calloc.body = [&](size_t size) { return nullptr; }; + test::mock::osi_allocator::osi_calloc.body = [&](size_t /*size*/) { return nullptr; }; uint8_t input_value[] = {0x01, 0x02, 0x03}; size_t length = sizeof(input_value); @@ -2677,19 +2693,19 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_bin, std::string str_value; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { + [&](const config_t& /*config*/, const std::string& section, const std::string& key, + const std::string* /*def_value*/) { actual_section = section; actual_key = key; return get_string_return_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, const std::string& value) { new_string_value = value; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) {}; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, void* /*data*/) {}; test::mock::osi_allocator::osi_calloc.body = [&](size_t size) { return new char[size]; }; @@ -2752,7 +2768,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_bin, { reset_mock_function_count_map(); - test::mock::osi_allocator::osi_calloc.body = [&](size_t size) { return nullptr; }; + test::mock::osi_allocator::osi_calloc.body = [&](size_t /*size*/) { return nullptr; }; uint8_t input_value[] = {0x01, 0x02, 0x03}; size_t length = sizeof(input_value); @@ -2779,12 +2795,12 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_remove, std::string actual_section, expected_section = "00:00:00:00:00:00"; bool return_value; - test::mock::osi_config::config_remove_key.body = [&](config_t* config, const std::string& section, - const std::string& key) { - actual_section = section; - actual_key = key; - return return_value; - }; + test::mock::osi_config::config_remove_key.body = + [&](config_t* /*config*/, const std::string& section, const std::string& key) { + actual_section = section; + actual_key = key; + return return_value; + }; { reset_mock_function_count_map(); @@ -2828,7 +2844,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_flush, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { bool return_value; - test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* alarm) -> bool { + test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { return return_value; }; @@ -2866,14 +2882,14 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_clear, config_t* config_new_empty_return_value; bool config_save_return_value; - test::mock::osi_alarm::alarm_cancel.body = [&](alarm_t* alarm) {}; + test::mock::osi_alarm::alarm_cancel.body = [&](alarm_t* /*alarm*/) {}; test::mock::osi_config::config_new_empty.body = [&]() { return std::unique_ptr(config_new_empty_return_value); }; - test::mock::osi_config::config_save.body = [&](const config_t& config, - const std::string& filename) -> bool { + test::mock::osi_config::config_save.body = [&](const config_t& /*config*/, + const std::string& /*filename*/) -> bool { return config_save_return_value; }; @@ -3083,7 +3099,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_compare_key, TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_write, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { test::mock::osi_config::config_save.body = - [&](const config_t& config, const std::string& filename) -> bool { return true; }; + [&](const config_t& /*config*/, const std::string& /*filename*/) -> bool { return true; }; { reset_mock_function_count_map(); @@ -3141,7 +3157,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_is_factory_reset, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { bool return_value; test::mock::osi_properties::osi_property_get_bool.body = - [&](const char* key, bool default_value) -> bool { return return_value; }; + [&](const char* /*key*/, bool /*default_value*/) -> bool { return return_value; }; { return_value = false; @@ -3187,20 +3203,21 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_debug_iot_config_delete_files class DeviceIotConfigDisabledTest : public testing::Test { protected: void SetUp() override { - test::mock::osi_alarm::alarm_new.body = [&](const char* name) -> alarm_t* { + test::mock::osi_alarm::alarm_new.body = [&](const char* /*name*/) -> alarm_t* { return &placeholder_alarm; }; - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) { return; }; + test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, + alarm_callback_t /*cb*/, + void* /*data*/) { return; }; - test::mock::osi_alarm::alarm_free.body = [](alarm_t* alarm) {}; + test::mock::osi_alarm::alarm_free.body = [](alarm_t* /*alarm*/) {}; - test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* alarm) -> bool { + test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { return false; }; - test::mock::osi_future::future_new_immediate.body = [&](void* value) -> future_t* { + test::mock::osi_future::future_new_immediate.body = [&](void* /*value*/) -> future_t* { return &placeholder_future; }; @@ -3209,27 +3226,27 @@ protected: }; test::mock::osi_config::config_new.body = - [&](const char* filename) -> std::unique_ptr { + [&](const char* /*filename*/) -> std::unique_ptr { return std::make_unique(); }; test::mock::osi_config::config_get_int.body = - [&](const config_t& config, const std::string& section, const std::string& key, - int def_value) { return def_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, int def_value) { return def_value; }; - test::mock::osi_config::config_set_int.body = [&](config_t* config, const std::string& section, - const std::string& key, - int value) { return; }; + test::mock::osi_config::config_set_int.body = + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + int /*value*/) { return; }; test::mock::osi_config::config_get_string.body = - [&](const config_t& config, const std::string& section, const std::string& key, - const std::string* def_value) { return def_value; }; + [&](const config_t& /*config*/, const std::string& /*section*/, + const std::string& /*key*/, const std::string* def_value) { return def_value; }; test::mock::osi_config::config_set_string.body = - [&](config_t* config, const std::string& section, const std::string& key, - const std::string& value) { return; }; + [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, + const std::string& /*value*/) { return; }; - test::mock::osi_allocator::osi_free.body = [&](void* ptr) {}; + test::mock::osi_allocator::osi_free.body = [&](void* /*ptr*/) {}; device_iot_config_module_init(); device_iot_config_module_start_up(); -- GitLab From 68290871e2d76acfb3dfe505d9f4a19a6368cbd0 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 8 Oct 2024 00:16:01 +0000 Subject: [PATCH 204/875] system/profile/avrcp/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I4a9c08d8dd56989b8ace17bd437e7c4df326fb21 --- system/packet/tests/packet_test_helper.h | 2 +- system/profile/avrcp/Android.bp | 6 ------ system/profile/avrcp/avrcp_sdp_records.cc | 6 +++--- system/profile/avrcp/connection_handler.cc | 11 ++++++----- system/profile/avrcp/device.cc | 10 +++++----- .../avrcp/tests/avrcp_connection_handler_test.cc | 4 ++-- 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/system/packet/tests/packet_test_helper.h b/system/packet/tests/packet_test_helper.h index e91979317ee..a9956cc6a2a 100644 --- a/system/packet/tests/packet_test_helper.h +++ b/system/packet/tests/packet_test_helper.h @@ -195,7 +195,7 @@ public: } private: - void wholeEntry(size_t f, AttributeEntry&& entry) { + void wholeEntry(size_t /*f*/, AttributeEntry&& entry) { _control_set.insert(entry); _order_control.push_back(entry); if (_builder->size() != expected_size()) { diff --git a/system/profile/avrcp/Android.bp b/system/profile/avrcp/Android.bp index 7420ac56073..133d2a47129 100644 --- a/system/profile/avrcp/Android.bp +++ b/system/profile/avrcp/Android.bp @@ -43,7 +43,6 @@ cc_library_static { ], min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -91,10 +90,6 @@ cc_test { sanitize: { cfi: false, }, - - cflags: [ - "-Wno-unused-parameter", - ], header_libs: ["libbluetooth_headers"], } @@ -143,5 +138,4 @@ cc_fuzz { enabled: false, }, }, - cflags: ["-Wno-unused-parameter"], } diff --git a/system/profile/avrcp/avrcp_sdp_records.cc b/system/profile/avrcp/avrcp_sdp_records.cc index b58f0474220..57d90ce60be 100644 --- a/system/profile/avrcp/avrcp_sdp_records.cc +++ b/system/profile/avrcp/avrcp_sdp_records.cc @@ -178,8 +178,8 @@ uint16_t ControlAvrcSdpRecordHelper::UpdateRecord(const uint16_t new_categories) return result ? AVRC_SUCCESS : AVRC_FAIL; } -uint16_t ControlAvrcSdpRecordHelper::EnableCovertArt(uint16_t cover_art_psm, - const uint16_t request_id) { +uint16_t ControlAvrcSdpRecordHelper::EnableCovertArt(uint16_t /*cover_art_psm*/, + const uint16_t /*request_id*/) { log::warn( "Enabling cover art support dynamically is not supported for service " "UUID {:x}", @@ -187,7 +187,7 @@ uint16_t ControlAvrcSdpRecordHelper::EnableCovertArt(uint16_t cover_art_psm, return AVRC_FAIL; } -uint16_t ControlAvrcSdpRecordHelper::DisableCovertArt(const uint16_t request_id) { +uint16_t ControlAvrcSdpRecordHelper::DisableCovertArt(const uint16_t /*request_id*/) { log::warn( "Disabling cover art support dynamically is not supported for service " "UUID {:x}", diff --git a/system/profile/avrcp/connection_handler.cc b/system/profile/avrcp/connection_handler.cc index 3d6a67c964e..b25e7938a50 100644 --- a/system/profile/avrcp/connection_handler.cc +++ b/system/profile/avrcp/connection_handler.cc @@ -138,7 +138,7 @@ bool ConnectionHandler::ConnectDevice(const RawAddress& bdaddr) { } auto connection_lambda = [](ConnectionHandler* instance_, const RawAddress& bdaddr, - tSDP_STATUS status, uint16_t version, uint16_t features) { + tSDP_STATUS status, uint16_t /*version*/, uint16_t features) { log::info("SDP Completed features=0x{:x}", features); if (status != tSDP_STATUS::SDP_SUCCESS || !(features & BTA_AV_FEAT_RCCT)) { log::error( @@ -371,8 +371,8 @@ void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event, uint16_ connection_cb_.Run(newDevice); log::info("Performing SDP on connected device. address={}", *peer_addr); - auto sdp_lambda = [](ConnectionHandler* instance_, uint8_t handle, tSDP_STATUS status, - uint16_t version, uint16_t features) { + auto sdp_lambda = [](ConnectionHandler* instance_, uint8_t handle, tSDP_STATUS /*status*/, + uint16_t /*version*/, uint16_t features) { if (instance_->device_map_.find(handle) == instance_->device_map_.end()) { log::warn("No device found for handle: 0x{:x}", handle); return; @@ -652,8 +652,9 @@ bool ConnectionHandler::SdpLookupAudioRole(uint16_t handle) { weak_ptr_factory_.GetWeakPtr(), handle)); } -void ConnectionHandler::SdpLookupAudioRoleCb(uint16_t handle, bool found, tA2DP_Service* p_service, - const RawAddress& peer_address) { +void ConnectionHandler::SdpLookupAudioRoleCb(uint16_t handle, bool found, + tA2DP_Service* /*p_service*/, + const RawAddress& /*peer_address*/) { if (device_map_.find(handle) == device_map_.end()) { log::warn("No device found for handle: {}", loghex(handle)); return; diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index 1851e88d346..f334ab659de 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -1114,7 +1114,7 @@ void Device::HandleGetTotalNumberOfItems(uint8_t label, } } -void Device::GetTotalNumberOfItemsMediaPlayersResponse(uint8_t label, uint16_t curr_player, +void Device::GetTotalNumberOfItemsMediaPlayersResponse(uint8_t label, uint16_t /*curr_player*/, std::vector list) { log::verbose("num_items={}", list.size()); @@ -1131,7 +1131,7 @@ void Device::GetTotalNumberOfItemsVFSResponse(uint8_t label, std::vector list) { log::verbose("num_items={}", list.size()); @@ -1179,7 +1179,7 @@ void Device::HandleChangePath(uint8_t label, std::shared_ptr base::Bind(&Device::ChangePathResponse, weak_ptr_factory_.GetWeakPtr(), label, pkt)); } -void Device::ChangePathResponse(uint8_t label, std::shared_ptr pkt, +void Device::ChangePathResponse(uint8_t label, std::shared_ptr /*pkt*/, std::vector list) { // TODO (apanicke): Reconstruct the VFS ID's here. Right now it gets // reconstructed in GetFolderItemsVFS @@ -1557,7 +1557,7 @@ void Device::SendMediaUpdate(bool metadata, bool play_status, bool queue) { } } -void Device::SendFolderUpdate(bool available_players, bool addressed_player, bool uids) { +void Device::SendFolderUpdate(bool available_players, bool addressed_player, bool /*uids*/) { log::assert_that(media_interface_ != nullptr, "assert failed: media_interface_ != nullptr"); log::verbose(""); @@ -1664,7 +1664,7 @@ void Device::PlayerSettingChangedNotificationResponse(uint8_t label, bool interi } void Device::HandleNowPlayingNotificationResponse(uint8_t label, bool interim, - std::string curr_song_id, + std::string /*curr_song_id*/, std::vector song_list) { if (interim) { now_playing_changed_ = Notification(true, label); diff --git a/system/profile/avrcp/tests/avrcp_connection_handler_test.cc b/system/profile/avrcp/tests/avrcp_connection_handler_test.cc index cd1ecbae759..73334576f14 100644 --- a/system/profile/avrcp/tests/avrcp_connection_handler_test.cc +++ b/system/profile/avrcp/tests/avrcp_connection_handler_test.cc @@ -41,8 +41,8 @@ using ::testing::SaveArgPointee; using ::testing::SetArgPointee; using ::testing::StrictMock; -bool btif_av_peer_is_connected_sink(const RawAddress& peer_address) { return true; } -bool btif_av_peer_is_connected_source(const RawAddress& peer_address) { return false; } +bool btif_av_peer_is_connected_sink(const RawAddress& /*peer_address*/) { return true; } +bool btif_av_peer_is_connected_source(const RawAddress& /*peer_address*/) { return false; } bool btif_av_both_enable(void) { return false; } namespace bluetooth { -- GitLab From f097560a199d023a337c3bbaf1abace0e6d958cb Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 8 Oct 2024 00:39:44 +0000 Subject: [PATCH 205/875] system/bta/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I38b5703e475860493876ef1d326a3e7bad2978a3 --- system/bta/Android.bp | 16 -- system/bta/ag/bta_ag_act.cc | 4 +- system/bta/ag/bta_ag_cmd.cc | 9 +- system/bta/ag/bta_ag_sco.cc | 2 +- system/bta/ag/bta_ag_sdp.cc | 2 +- system/bta/ar/bta_ar.cc | 3 +- system/bta/av/bta_av_aact.cc | 7 +- system/bta/av/bta_av_main.cc | 2 +- system/bta/csis/csis_client.cc | 22 ++- system/bta/csis/csis_client_test.cc | 45 ++--- system/bta/csis/csis_types.h | 2 +- system/bta/gatt/bta_gattc_utils.cc | 2 +- system/bta/gatt/bta_gatts_act.cc | 8 +- system/bta/has/has_client.cc | 29 +-- system/bta/has/has_client_test.cc | 42 ++-- system/bta/hearing_aid/hearing_aid.cc | 25 +-- system/bta/hf_client/bta_hf_client_at.cc | 2 +- system/bta/hh/bta_hh_act.cc | 2 +- system/bta/hh/bta_hh_le.cc | 26 +-- .../audio_hal_client/audio_hal_client.h | 2 +- .../audio_hal_client/audio_hal_client_test.cc | 22 ++- .../audio_hal_client/audio_sink_hal_client.cc | 4 +- .../audio_source_hal_client.cc | 4 +- .../bta/le_audio/broadcaster/broadcaster.cc | 18 +- .../le_audio/broadcaster/broadcaster_test.cc | 8 +- .../le_audio/broadcaster/broadcaster_types.cc | 2 +- .../broadcaster/mock_state_machine.cc | 8 +- .../le_audio/broadcaster/mock_state_machine.h | 2 +- .../broadcaster/state_machine_test.cc | 100 +++++----- system/bta/le_audio/client.cc | 22 ++- system/bta/le_audio/codec_manager_test.cc | 22 ++- system/bta/le_audio/devices.cc | 2 +- system/bta/le_audio/devices_test.cc | 16 +- system/bta/le_audio/le_audio_client_test.cc | 185 +++++++++--------- .../bta/le_audio/metrics_collector_linux.cc | 14 +- system/bta/le_audio/mock_codec_interface.cc | 2 +- system/bta/le_audio/state_machine.cc | 27 +-- system/bta/le_audio/state_machine_test.cc | 40 ++-- system/bta/ras/ras_client.cc | 10 +- system/bta/test/bta_ag_sco_test.cc | 2 +- system/bta/test/bta_ag_test.cc | 13 +- system/bta/test/bta_av_test.cc | 2 +- system/bta/test/bta_dip_test.cc | 4 +- system/bta/test/bta_disc_test.cc | 48 ++--- system/bta/test/bta_dm_test.cc | 32 +-- system/bta/test/bta_sec_test.cc | 8 +- system/bta/test/bta_test_fixtures.h | 11 +- system/bta/test/common/btm_api_mock.cc | 2 +- system/bta/vc/device.cc | 5 +- system/bta/vc/devices_test.cc | 136 ++++++------- system/bta/vc/vc.cc | 20 +- system/bta/vc/vc_test.cc | 99 +++++----- 52 files changed, 583 insertions(+), 559 deletions(-) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 319b5dbbf2b..271b008ca0f 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -133,7 +133,6 @@ cc_library_static { "vc/vc.cc", ], cflags: [ - "-Wno-unused-parameter", /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ "-fvisibility=default", ], @@ -204,7 +203,6 @@ cc_library_static { "sys/utl.cc", ], cflags: [ - "-Wno-unused-parameter", /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ "-fvisibility=default", ], @@ -333,7 +331,6 @@ cc_test { ], cflags: [ "-Wno-macro-redefined", - "-Wno-unused-parameter", ], target: { android: { @@ -399,7 +396,6 @@ cc_test { "libcom.android.sysprop.bluetooth.wrapped", "libgmock", ], - cflags: ["-Wno-unused-parameter"], } // bta unit tests for target @@ -448,7 +444,6 @@ cc_test { "libosi", "libstatslog_bt", ], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -513,7 +508,6 @@ cc_test { ], }, }, - cflags: ["-Wno-unused-parameter"], } // csis unit tests for host @@ -576,7 +570,6 @@ cc_test { undefined: true, }, }, - cflags: ["-Wno-unused-parameter"], } // groups unit tests for host @@ -623,7 +616,6 @@ cc_test { undefined: true, }, }, - cflags: ["-Wno-unused-parameter"], } // bta unit tests for host @@ -676,7 +668,6 @@ cc_test { sanitize: { cfi: false, }, - cflags: ["-Wno-unused-parameter"], } genrule { @@ -835,7 +826,6 @@ cc_test { cfi: false, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -945,7 +935,6 @@ cc_test { cfi: false, }, header_libs: ["libbluetooth_headers"], - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1064,7 +1053,6 @@ cc_test { undefined: true, }, }, - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1131,7 +1119,6 @@ cc_test { undefined: true, }, }, - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1209,7 +1196,6 @@ cc_test { undefined: true, }, }, - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1270,7 +1256,6 @@ cc_test { undefined: true, }, }, - cflags: ["-Wno-unused-parameter"], } cc_test { @@ -1349,7 +1334,6 @@ cc_test { undefined: true, }, }, - cflags: ["-Wno-unused-parameter"], } cc_test { diff --git a/system/bta/ag/bta_ag_act.cc b/system/bta/ag/bta_ag_act.cc index 716ca771863..32b19fc9703 100644 --- a/system/bta/ag/bta_ag_act.cc +++ b/system/bta/ag/bta_ag_act.cc @@ -145,7 +145,7 @@ void bta_ag_register(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { * Returns void * ******************************************************************************/ -void bta_ag_deregister(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { +void bta_ag_deregister(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /*data*/) { /* set dealloc */ p_scb->dealloc = true; @@ -169,7 +169,7 @@ void bta_ag_deregister(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { * Returns void * ******************************************************************************/ -void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { +void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /*data*/) { /* set dealloc */ p_scb->dealloc = true; diff --git a/system/bta/ag/bta_ag_cmd.cc b/system/bta/ag/bta_ag_cmd.cc index 31c978c9fef..27ff562fb45 100644 --- a/system/bta/ag/bta_ag_cmd.cc +++ b/system/bta/ag/bta_ag_cmd.cc @@ -456,7 +456,7 @@ static uint8_t bta_ag_parse_chld(tBTA_AG_SCB* /* p_scb */, char* p_s) { * Returns Returns bitmap of supported codecs. * ******************************************************************************/ -static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB* p_scb, char* p_s, char* p_end) { +static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB* /*p_scb*/, char* p_s, char* p_end) { tBTA_AG_PEER_CODEC retval = BTM_SCO_CODEC_NONE; tBTA_AG_UUID_CODEC uuid_codec; char* p; @@ -1891,7 +1891,8 @@ void bta_ag_send_bcs(tBTA_AG_SCB* p_scb) { * Returns true if we can, false if not * ******************************************************************************/ -bool bta_ag_is_sco_open_allowed(tBTA_AG_SCB* p_scb, const std::string event) { +bool bta_ag_is_sco_open_allowed([[maybe_unused]] tBTA_AG_SCB* p_scb, + [[maybe_unused]] const std::string event) { #ifdef __ANDROID__ /* Do not open SCO if 1. the dual mode audio system property is enabled, 2. LEA is active, and 3. LEA is preferred for DUPLEX */ @@ -1952,7 +1953,7 @@ void bta_ag_send_ring(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) { * Returns void * ******************************************************************************/ -void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) { +void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* /*p_data*/) { tBTA_AG_UUID_CODEC codec_uuid; if (p_scb->codec_fallback) { if (p_scb->peer_codecs & BTM_SCO_CODEC_MSBC) { @@ -1977,7 +1978,7 @@ void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) { * Returns void * ******************************************************************************/ -void bta_ag_send_qac(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) { +void bta_ag_send_qac(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* /*p_data*/) { if (!get_swb_codec_status(bluetooth::headset::BTHF_SWB_CODEC_VENDOR_APTX, &p_scb->peer_addr)) { log::verbose("send +QAC codecs unsupported"); bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_QAC, SWB_CODECS_UNSUPPORTED, 0); diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index eb858adcc98..4a7a58393ab 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -1555,7 +1555,7 @@ void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) { * Returns void * ******************************************************************************/ -void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA* p_data) { +void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA* /*p_data*/) { bta_ag_cb.sco.is_local = false; log::verbose("eSCO {}, state {}", diff --git a/system/bta/ag/bta_ag_sdp.cc b/system/bta/ag/bta_ag_sdp.cc index cafbfb22f34..038b3fffdfa 100644 --- a/system/bta/ag/bta_ag_sdp.cc +++ b/system/bta/ag/bta_ag_sdp.cc @@ -542,6 +542,6 @@ void bta_ag_do_disc(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) { * Returns void * ******************************************************************************/ -void bta_ag_free_db(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { +void bta_ag_free_db(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /*data*/) { osi_free_and_reset((void**)&p_scb->p_disc_db); } diff --git a/system/bta/ar/bta_ar.cc b/system/bta/ar/bta_ar.cc index 6d82b2b78c3..4602930ec9b 100644 --- a/system/bta/ar/bta_ar.cc +++ b/system/bta/ar/bta_ar.cc @@ -160,7 +160,8 @@ void bta_ar_dereg_avdt() { * Returns void * ******************************************************************************/ -void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr, uint8_t scb_index) {} +void bta_ar_avdt_conn(tBTA_SYS_ID /*sys_id*/, const RawAddress& /*bd_addr*/, + uint8_t /*scb_index*/) {} /******************************************************************************* * diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index 739fd2b3861..4adc3e2d6fa 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -440,7 +440,8 @@ void bta_av_proc_stream_evt(uint8_t handle, const RawAddress& bd_addr, uint8_t e * Returns void * ******************************************************************************/ -void bta_av_sink_data_cback(uint8_t handle, BT_HDR* p_pkt, uint32_t time_stamp, uint8_t m_pt) { +void bta_av_sink_data_cback(uint8_t handle, BT_HDR* p_pkt, uint32_t /*time_stamp*/, + uint8_t /*m_pt*/) { int index = 0; tBTA_AV_SCB* p_scb; log::verbose( @@ -2702,7 +2703,7 @@ void bta_av_rcfg_connect(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* /* p_data */) { * Returns void * ******************************************************************************/ -void bta_av_rcfg_discntd(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { +void bta_av_rcfg_discntd(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* /*p_data*/) { log::error("num_recfg={} conn_lcb=0x{:x} peer_addr={}", p_scb->num_recfg, bta_av_cb.conn_lcb, p_scb->PeerAddress()); @@ -3164,7 +3165,7 @@ void bta_av_vendor_offload_stop() { * Returns void * ******************************************************************************/ -void bta_av_offload_req(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { +void bta_av_offload_req(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* /*p_data*/) { tBTA_AV_STATUS status = BTA_AV_FAIL_RESOURCES; tBT_A2DP_OFFLOAD offload_start; diff --git a/system/bta/av/bta_av_main.cc b/system/bta/av/bta_av_main.cc index f1463fc93bf..d8573d7f028 100644 --- a/system/bta/av/bta_av_main.cc +++ b/system/bta/av/bta_av_main.cc @@ -1026,7 +1026,7 @@ static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, uint8_t num_sco_li * Returns true, if role switch is done * ******************************************************************************/ -bool bta_av_switch_if_needed(tBTA_AV_SCB* p_scb) { +bool bta_av_switch_if_needed(tBTA_AV_SCB* /*p_scb*/) { // TODO: A workaround for devices that are connected first, become // Central, and block follow-up role changes - b/72122792 . return false; diff --git a/system/bta/csis/csis_client.cc b/system/bta/csis/csis_client.cc index 1359a0d3f1c..92ff4c71a32 100644 --- a/system/bta/csis/csis_client.cc +++ b/system/bta/csis/csis_client.cc @@ -201,7 +201,9 @@ public: AssignCsisGroup(address, group_id, false, Uuid::kEmpty); } - void OnGroupRemovedCb(const bluetooth::Uuid& uuid, int group_id) { RemoveCsisGroup(group_id); } + void OnGroupRemovedCb(const bluetooth::Uuid& /*uuid*/, int group_id) { + RemoveCsisGroup(group_id); + } void OnGroupMemberRemovedCb(const RawAddress& address, int group_id) { log::debug("{}, group_id: {}", address, group_id); @@ -336,7 +338,8 @@ public: NotifyGroupStatus(group_id, false, status, std::move(cb)); } - void OnGattCsisWriteLockRsp(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, void* data) { + void OnGattCsisWriteLockRsp(tCONN_ID conn_id, tGATT_STATUS status, uint16_t /*handle*/, + void* data) { auto device = FindDeviceByConnId(conn_id); if (device == nullptr) { log::error("Device not there for conn_id: 0x{:04x}", conn_id); @@ -433,8 +436,8 @@ public: BtaGattQueue::WriteCharacteristic( device->conn_id, csis_instance->svc_data.lock_handle.val_hdl, value, GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* data) { if (instance) { instance->OnGattCsisWriteLockRsp(conn_id, status, handle, data); } @@ -913,7 +916,7 @@ private: } } - void OnGattWriteCcc(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, void* user_data) { + void OnGattWriteCcc(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, void* /*user_data*/) { auto device = FindDeviceByConnId(conn_id); if (device == nullptr) { log::info("unknown conn_id= 0x{:04x}", conn_id); @@ -991,7 +994,7 @@ private: csis_group->SetTargetLockState(CsisLockState::CSIS_STATE_UNSET); } - void OnCsisLockNotifications(std::shared_ptr& device, + void OnCsisLockNotifications(std::shared_ptr& /*device*/, std::shared_ptr& csis_instance, uint16_t len, const uint8_t* value) { if (len != 1) { @@ -2144,8 +2147,8 @@ private: UINT16_TO_STREAM(value_ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); BtaGattQueue::WriteDescriptor( conn_id, ccc_handle, std::move(value), GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* user_data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* user_data) { if (instance) { instance->OnGattWriteCcc(conn_id, status, handle, user_data); } @@ -2153,7 +2156,8 @@ private: nullptr); } - void DisableGattNotification(tCONN_ID conn_id, const RawAddress& address, uint16_t value_handle) { + void DisableGattNotification(tCONN_ID /*conn_id*/, const RawAddress& address, + uint16_t value_handle) { if (value_handle != GAP_INVALID_HANDLE) { tGATT_STATUS register_status = BTA_GATTC_DeregisterForNotifications(gatt_if_, address, value_handle); diff --git a/system/bta/csis/csis_client_test.cc b/system/bta/csis/csis_client_test.cc index 3306263a8a5..fa61fa1c1fe 100644 --- a/system/bta/csis/csis_client_test.cc +++ b/system/bta/csis/csis_client_test.cc @@ -39,10 +39,10 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -bool gatt_cl_read_sirk_req(const RawAddress& peer_bda, +bool gatt_cl_read_sirk_req(const RawAddress& /*peer_bda*/, base::OnceCallback - cb) { + /*cb*/) { return true; } @@ -419,7 +419,7 @@ protected: // default action for WriteDescriptor function call ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _)) .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, + 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); @@ -481,8 +481,8 @@ protected: EXPECT_CALL(*callbacks, OnDeviceAvailable(address, _, _, _, _)).Times(AtLeast(1)); EXPECT_CALL(gatt_interface, Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, true)) - .WillOnce(Invoke([this, conn_id](tGATT_IF client_if, const RawAddress& remote_bda, - bool is_direct, bool opportunistic) { + .WillOnce(Invoke([this, conn_id](tGATT_IF /*client_if*/, const RawAddress& remote_bda, + bool /*is_direct*/, bool /*opportunistic*/) { InjectConnectedEvent(remote_bda, conn_id); GetSearchCompleteEvent(conn_id); })); @@ -560,7 +560,7 @@ protected: auto WriteDescriptorCbGenerator = [](tGATT_STATUS status, uint16_t ccc_handle) { return [status, ccc_handle](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, void* cb_data) -> void { if (cb) { if (ccc_handle) { @@ -823,7 +823,8 @@ TEST_F(CsisClientCallbackTest, test_on_group_lock_changed_group_not_found) { CsisClient::Get()->LockGroup( 2, true, base::BindOnce( - [](bool* callback_called, int group_id, bool locked, CsisGroupLockStatus status) { + [](bool* callback_called, int group_id, bool /*locked*/, + CsisGroupLockStatus status) { if ((group_id == 2) && (status == CsisGroupLockStatus::FAILED_INVALID_GROUP)) { *callback_called = true; } @@ -1200,7 +1201,7 @@ TEST_F(CsisMultiClientTest, test_lock_multiple_instances) { EXPECT_CALL(*csis_lock_callback_mock, CsisGroupLockCb(1, true, CsisGroupLockStatus::SUCCESS)); ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, + 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); @@ -1226,7 +1227,7 @@ TEST_F(CsisMultiClientTest, test_unlock_multiple_instances) { ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, + 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); @@ -1258,7 +1259,7 @@ TEST_F(CsisMultiClientTest, test_disconnect_locked_multiple_instances) { EXPECT_CALL(*csis_lock_callback_mock, CsisGroupLockCb(1, true, CsisGroupLockStatus::SUCCESS)); ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, + 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); @@ -1400,19 +1401,19 @@ TEST_F(CsisClientTest, test_database_out_of_sync) { // Simulated database changed on the remote side. ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) - .WillByDefault( - Invoke([this](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { - auto* svc = gatt::FindService(services_map[conn_id], handle); - if (svc == nullptr) { - return; - } + .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle, + std::vector value, tGATT_WRITE_TYPE /*write_type*/, + GATT_WRITE_OP_CB cb, void* cb_data) { + auto* svc = gatt::FindService(services_map[conn_id], handle); + if (svc == nullptr) { + return; + } - tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC; - if (cb) { - cb(conn_id, status, handle, value.size(), value.data(), cb_data); - } - })); + tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC; + if (cb) { + cb(conn_id, status, handle, value.size(), value.data(), cb_data); + } + })); ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return()); EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _)); diff --git a/system/bta/csis/csis_types.h b/system/bta/csis/csis_types.h index 22dcc00bd2e..091470099e4 100644 --- a/system/bta/csis/csis_types.h +++ b/system/bta/csis/csis_types.h @@ -95,7 +95,7 @@ public: uint16_t service_handle = GAP_INVALID_HANDLE; bool is_gatt_service_valid = false; - GattServiceDevice(const RawAddress& addr, bool first_connection) : addr(addr) {} + GattServiceDevice(const RawAddress& addr, bool /*first_connection*/) : addr(addr) {} GattServiceDevice() : GattServiceDevice(RawAddress::kEmpty, false) {} diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc index 36e05ba8b50..606566827a3 100644 --- a/system/bta/gatt/bta_gattc_utils.cc +++ b/system/bta/gatt/bta_gattc_utils.cc @@ -598,7 +598,7 @@ bool bta_gattc_check_notif_registry(tBTA_GATTC_RCB* p_clreg, tBTA_GATTC_SERV* p_ * Returns None. * ******************************************************************************/ -void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV* p_srcb, tCONN_ID conn_id, +void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV* /*p_srcb*/, tCONN_ID conn_id, uint16_t start_handle, uint16_t end_handle) { RawAddress remote_bda; tGATT_IF gatt_if; diff --git a/system/bta/gatt/bta_gatts_act.cc b/system/bta/gatt/bta_gatts_act.cc index 78bfb8bfcf3..c9c4427f511 100644 --- a/system/bta/gatt/bta_gatts_act.cc +++ b/system/bta/gatt/bta_gatts_act.cc @@ -87,7 +87,7 @@ tGATT_APPL_INFO bta_gatts_nv_cback = {bta_gatts_nv_save_cback, bta_gatts_nv_srv_ * Returns none. * ******************************************************************************/ -static void bta_gatts_nv_save_cback(bool is_add, tGATTS_HNDL_RANGE* p_hndl_range) {} +static void bta_gatts_nv_save_cback(bool /*is_add*/, tGATTS_HNDL_RANGE* /*p_hndl_range*/) {} /******************************************************************************* * @@ -100,8 +100,8 @@ static void bta_gatts_nv_save_cback(bool is_add, tGATTS_HNDL_RANGE* p_hndl_range * Returns none. * ******************************************************************************/ -static bool bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ* p_req, - tGATTS_SRV_CHG_RSP* p_rsp) { +static bool bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD /*cmd*/, tGATTS_SRV_CHG_REQ* /*p_req*/, + tGATTS_SRV_CHG_RSP* /*p_rsp*/) { return false; } @@ -285,7 +285,7 @@ void bta_gatts_deregister(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) { * Returns none. * ******************************************************************************/ -void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB* p_srvc_cb, tBTA_GATTS_DATA* p_msg) { +void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB* p_srvc_cb, tBTA_GATTS_DATA* /*p_msg*/) { tBTA_GATTS_RCB* p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx]; tBTA_GATTS cb_data; diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 8b4ebbe7ccf..fddb26cd65e 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -471,8 +471,8 @@ public: EnqueueCtpOp(operation); BtaGattQueue::WriteCharacteristic( device->conn_id, device->cp_handle, operation.ToCharacteristicValue(), GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* user_data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t /*handle*/, uint16_t /*len*/, + const uint8_t* /*value*/, void* user_data) { if (instance) { instance->OnHasPresetNameGetStatus(conn_id, status, user_data); } @@ -571,8 +571,8 @@ public: EnqueueCtpOp(operation); BtaGattQueue::WriteCharacteristic( device.conn_id, device.cp_handle, operation.ToCharacteristicValue(), GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* user_data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t /*handle*/, uint16_t /*len*/, + const uint8_t* /*value*/, void* user_data) { if (instance) { instance->OnHasPresetIndexOperation(conn_id, status, user_data); } @@ -731,8 +731,8 @@ public: EnqueueCtpOp(operation); BtaGattQueue::WriteCharacteristic( device.conn_id, device.cp_handle, operation.ToCharacteristicValue(), GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* user_data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t /*handle*/, uint16_t /*len*/, + const uint8_t* /*value*/, void* user_data) { if (instance) { instance->OnHasActivePresetCycleStatus(conn_id, status, user_data); } @@ -791,8 +791,8 @@ public: EnqueueCtpOp(operation); BtaGattQueue::WriteCharacteristic( device.conn_id, device.cp_handle, operation.ToCharacteristicValue(), GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* user_data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t /*handle*/, uint16_t /*len*/, + const uint8_t* /*value*/, void* user_data) { if (instance) { instance->OnHasPresetNameSetStatus(conn_id, status, user_data); } @@ -981,7 +981,7 @@ public: dprintf(fd, "%s", stream.str().c_str()); } - void OnGroupOpCoordinatorTimeout(void* p) { + void OnGroupOpCoordinatorTimeout(void* /*p*/) { log::error( "Coordinated operation timeout: not all the devices notified their " "state change on time."); @@ -1137,7 +1137,7 @@ private: void OnHasFeaturesValue(std::variant conn_id_device_variant, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, - void* user_data = nullptr) { + void* /*user_data*/ = nullptr) { log::debug(""); auto device = GetDevice(conn_id_device_variant); @@ -1533,7 +1533,7 @@ private: void OnHasActivePresetValue(std::variant conn_id_device_variant, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* user_data = nullptr) { + const uint8_t* value, void* /*user_data*/ = nullptr) { log::debug(""); auto device = GetDevice(conn_id_device_variant); @@ -1753,7 +1753,8 @@ private: return true; } - bool StartInitialHasDetailsReadAndValidation(const gatt::Service& service, HasDevice* device) { + bool StartInitialHasDetailsReadAndValidation(const gatt::Service& /*service*/, + HasDevice* device) { // Validate service structure if (device->features_handle == GAP_INVALID_HANDLE) { /* Missing key characteristic */ @@ -2129,8 +2130,8 @@ private: UINT16_TO_STREAM(value_ptr, ccc_val); BtaGattQueue::WriteDescriptor( conn_id, ccc_handle, std::move(value), GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t value_handle, uint16_t len, - const uint8_t* value, void* data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t value_handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* data) { if (instance) { instance->OnGattWriteCcc(conn_id, status, value_handle, data); } diff --git a/system/bta/has/has_client_test.cc b/system/bta/has/has_client_test.cc index df98b10a427..9be5c92a695 100644 --- a/system/bta/has/has_client_test.cc +++ b/system/bta/has/has_client_test.cc @@ -45,7 +45,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -bool gatt_profile_get_eatt_support(const RawAddress& addr) { return true; } +bool gatt_profile_get_eatt_support(const RawAddress& /*addr*/) { return true; } void osi_property_set_bool(const char* key, bool value); namespace bluetooth { @@ -292,8 +292,8 @@ protected: WriteCharacteristic(conn_id, HasDbBuilder::kPresetsCtpValHdl, _, GATT_WRITE, _, _)) .WillByDefault(Invoke([this, address](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, - void* cb_data) { + tGATT_WRITE_TYPE /*write_type*/, + GATT_WRITE_OP_CB cb, void* cb_data) { auto pp = value.data(); auto len = value.size(); uint8_t op, index, num_of_indices; @@ -634,9 +634,9 @@ protected: ON_CALL(btm_interface, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(true))); ON_CALL(btm_interface, SetEncryption(_, _, _, _, _)) - .WillByDefault(Invoke([this](const RawAddress& bd_addr, tBT_TRANSPORT transport, - tBTM_SEC_CALLBACK* p_callback, void* p_ref_data, - tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { + .WillByDefault(Invoke([this](const RawAddress& bd_addr, tBT_TRANSPORT /*transport*/, + tBTM_SEC_CALLBACK* /*p_callback*/, void* /*p_ref_data*/, + tBTM_BLE_SEC_ACT /*sec_act*/) -> tBTM_STATUS { InjectEncryptionEvent(bd_addr); return tBTM_STATUS::BTM_SUCCESS; })); @@ -695,7 +695,7 @@ protected: /* default action for WriteDescriptor function call */ ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _)) .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, + 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); @@ -704,8 +704,8 @@ protected: /* 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) { + .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)); } @@ -3023,19 +3023,19 @@ TEST_F(HasClientTest, test_connect_database_out_of_sync) { TestConnect(test_address); ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) - .WillByDefault( - Invoke([this](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { - auto* svc = gatt::FindService(services_map[conn_id], handle); - if (svc == nullptr) { - return; - } + .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle, + std::vector value, tGATT_WRITE_TYPE /*write_type*/, + GATT_WRITE_OP_CB cb, void* cb_data) { + auto* svc = gatt::FindService(services_map[conn_id], handle); + if (svc == nullptr) { + return; + } - tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC; - if (cb) { - cb(conn_id, status, handle, value.size(), value.data(), cb_data); - } - })); + tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC; + if (cb) { + cb(conn_id, status, handle, value.size(), value.data(), cb_data); + } + })); ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return()); EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _)); diff --git a/system/bta/hearing_aid/hearing_aid.cc b/system/bta/hearing_aid/hearing_aid.cc index 796a8d20563..cb5974793d9 100644 --- a/system/bta/hearing_aid/hearing_aid.cc +++ b/system/bta/hearing_aid/hearing_aid.cc @@ -224,7 +224,7 @@ public: }; static void write_rpt_ctl_cfg_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) { + uint16_t len, const uint8_t* /*value*/, void* /*data*/) { if (status != GATT_SUCCESS) { log::error("handle= {}, conn_id={}, status= 0x{:x}, length={}", handle, conn_id, static_cast(status), len); @@ -465,8 +465,8 @@ public: int GetDeviceCount() { return hearingDevices.size(); } - void OnGattConnected(tGATT_STATUS status, tCONN_ID conn_id, tGATT_IF client_if, - RawAddress address, tBT_TRANSPORT transport, uint16_t mtu) { + void OnGattConnected(tGATT_STATUS status, tCONN_ID conn_id, tGATT_IF /*client_if*/, + RawAddress address, tBT_TRANSPORT /*transport*/, uint16_t /*mtu*/) { HearingDevice* hearingDevice = hearingDevices.FindByAddress(address); if (!hearingDevice) { /* When Hearing Aid is quickly disabled and enabled in settings, this case @@ -882,8 +882,8 @@ public: device->command_acked = true; } - void OnReadOnlyPropertiesRead(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, uint8_t* value, void* data) { + void OnReadOnlyPropertiesRead(tCONN_ID conn_id, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t len, uint8_t* value, void* /*data*/) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { log::error("unknown device: conn_id=0x{:x}", conn_id); @@ -989,13 +989,13 @@ public: } } - void OnAudioStatus(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) { + void OnAudioStatus(tCONN_ID /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t len, uint8_t* value, void* /*data*/) { log::info("{}", base::HexEncode(value, len)); } - void OnPsmRead(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) { + void OnPsmRead(tCONN_ID conn_id, tGATT_STATUS status, uint16_t /*handle*/, uint16_t len, + uint8_t* value, void* /*data*/) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { log::error("unknown device: conn_id=0x{:x}", conn_id); @@ -1278,7 +1278,8 @@ public: } static void StartAudioCtrlCallbackStatic(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) { + uint16_t /*len*/, const uint8_t* /*value*/, + void* /*data*/) { if (status != GATT_SUCCESS) { log::error("handle={}, conn_id={}, status=0x{:x}", handle, conn_id, static_cast(status)); @@ -1553,7 +1554,7 @@ public: } } - void GapCallback(uint16_t gap_handle, uint16_t event, tGAP_CB_DATA* data) { + void GapCallback(uint16_t gap_handle, uint16_t event, tGAP_CB_DATA* /*data*/) { HearingDevice* hearingDevice = hearingDevices.FindByGapHandle(gap_handle); if (!hearingDevice) { log::error("unknown device: gap_handle={} event=0x{:x}", gap_handle, event); @@ -1768,7 +1769,7 @@ public: DoDisconnectAudioStop(); } - void OnGattDisconnected(tCONN_ID conn_id, tGATT_IF client_if, RawAddress remote_bda) { + void OnGattDisconnected(tCONN_ID conn_id, tGATT_IF /*client_if*/, RawAddress remote_bda) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { log::error("unknown device: conn_id=0x{:x} bd_addr={}", conn_id, remote_bda); diff --git a/system/bta/hf_client/bta_hf_client_at.cc b/system/bta/hf_client/bta_hf_client_at.cc index f3494e215a5..9be68cab973 100644 --- a/system/bta/hf_client/bta_hf_client_at.cc +++ b/system/bta/hf_client/bta_hf_client_at.cc @@ -1466,7 +1466,7 @@ static char* bta_hf_client_parse_rejectlisted(tBTA_HF_CLIENT_CB* client_cb, char return buffer; } -static char* bta_hf_client_skip_unknown(tBTA_HF_CLIENT_CB* client_cb, char* buffer) { +static char* bta_hf_client_skip_unknown(tBTA_HF_CLIENT_CB* /*client_cb*/, char* buffer) { char* start; char* tmp; diff --git a/system/bta/hh/bta_hh_act.cc b/system/bta/hh/bta_hh_act.cc index c2ba60c2799..118a4b72f4f 100644 --- a/system/bta/hh/bta_hh_act.cc +++ b/system/bta/hh/bta_hh_act.cc @@ -636,7 +636,7 @@ void bta_hh_open_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { * Returns void * ******************************************************************************/ -void bta_hh_data_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { +void bta_hh_data_act(tBTA_HH_DEV_CB* /*p_cb*/, const tBTA_HH_DATA* p_data) { BT_HDR* pdata = p_data->hid_cback.p_data; uint8_t* p_rpt = (uint8_t*)(pdata + 1) + pdata->offset; diff --git a/system/bta/hh/bta_hh_le.cc b/system/bta/hh/bta_hh_le.cc index fc980e01cf3..92fffab8a68 100644 --- a/system/bta/hh/bta_hh_le.cc +++ b/system/bta/hh/bta_hh_le.cc @@ -656,7 +656,7 @@ static bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB* p_cb, uint16_t char_handle, uint static bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb); static void write_rpt_clt_cfg_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) { + uint16_t /*len*/, const uint8_t* /*value*/, void* data) { tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; const gatt::Characteristic* characteristic = BTA_GATTC_GetOwningCharacteristic(conn_id, handle); if (characteristic == nullptr) { @@ -756,8 +756,8 @@ void bta_hh_le_service_parsed(tBTA_HH_DEV_CB* p_dev_cb, tGATT_STATUS status) { } } -static void write_proto_mode_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) { +static void write_proto_mode_cb(tCONN_ID /*conn_id*/, tGATT_STATUS status, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* data) { tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; bta_hh_le_service_parsed(p_dev_cb, status); } @@ -813,7 +813,7 @@ static bool bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB* p_cb, tBTA_HH_PROTO_MODE * application with the protocol mode. * ******************************************************************************/ -static void get_protocol_mode_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, +static void get_protocol_mode_cb(tCONN_ID /*conn_id*/, tGATT_STATUS status, uint16_t /*handle*/, uint16_t len, uint8_t* value, void* data) { tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; tBTA_HH_HSDATA hs_data; @@ -1238,8 +1238,8 @@ static void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB* p_cb, tBTA_HH_STATUS status } } -static void read_hid_info_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) { +static void read_hid_info_cb(tCONN_ID /*conn_id*/, tGATT_STATUS status, uint16_t /*handle*/, + uint16_t len, uint8_t* value, void* data) { if (status != GATT_SUCCESS) { log::error("error:{}", status); return; @@ -1273,7 +1273,7 @@ void bta_hh_le_save_report_map(tBTA_HH_DEV_CB* p_dev_cb, uint16_t len, uint8_t* } } -static void read_hid_report_map_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, +static void read_hid_report_map_cb(tCONN_ID /*conn_id*/, tGATT_STATUS status, uint16_t /*handle*/, uint16_t len, uint8_t* value, void* data) { if (status != GATT_SUCCESS) { log::error("error reading characteristic:{}", status); @@ -1284,7 +1284,7 @@ static void read_hid_report_map_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16 bta_hh_le_save_report_map(p_dev_cb, len, value); } -static void read_ext_rpt_ref_desc_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, +static void read_ext_rpt_ref_desc_cb(tCONN_ID /*conn_id*/, tGATT_STATUS status, uint16_t /*handle*/, uint16_t len, uint8_t* value, void* data) { if (status != GATT_SUCCESS) { log::error("error:{}", status); @@ -1346,7 +1346,7 @@ static void read_report_ref_desc_cb(tCONN_ID conn_id, tGATT_STATUS status, uint1 bta_hh_le_save_report_ref(p_dev_cb, p_rpt, rpt_type, rpt_id); } -static void read_pref_conn_params_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, +static void read_pref_conn_params_cb(tCONN_ID /*conn_id*/, tGATT_STATUS status, uint16_t /*handle*/, uint16_t len, uint8_t* value, void* data) { if (status != GATT_SUCCESS) { log::error("error:{}", status); @@ -1875,8 +1875,8 @@ static void bta_hh_le_get_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type, uin BtaGattQueue::ReadCharacteristic(p_cb->conn_id, p_rpt->char_inst_id, read_report_cb, p_cb); } -static void write_report_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) { +static void write_report_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, + uint16_t /*len*/, const uint8_t* /*value*/, void* data) { tBTA_HH_CBDATA cback_data; tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; uint16_t cb_evt = p_dev_cb->w4_evt; @@ -2283,8 +2283,8 @@ static void bta_hh_process_cache_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_CACHE_ENT } } -static bool bta_hh_le_iso_data_callback(const RawAddress& addr, uint16_t cis_conn_hdl, - uint8_t* data, uint16_t size, uint32_t timestamp) { +static bool bta_hh_le_iso_data_callback(const RawAddress& addr, uint16_t /*cis_conn_hdl*/, + uint8_t* data, uint16_t size, uint32_t /*timestamp*/) { if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) { log::warn("DSA not supported"); return false; diff --git a/system/bta/le_audio/audio_hal_client/audio_hal_client.h b/system/bta/le_audio/audio_hal_client/audio_hal_client.h index decfe5e0b34..899bf171c51 100644 --- a/system/bta/le_audio/audio_hal_client/audio_hal_client.h +++ b/system/bta/le_audio/audio_hal_client/audio_hal_client.h @@ -154,7 +154,7 @@ public: virtual bool Start(const LeAudioCodecConfiguration& codecConfiguration, Callbacks* audioReceiver, DsaModes dsa_modes = {DsaMode::DISABLED}) = 0; virtual void Stop() = 0; - virtual size_t SendData(uint8_t* data, uint16_t size) { return 0; } + virtual size_t SendData(uint8_t* /*data*/, uint16_t /*size*/) { return 0; } virtual void ConfirmStreamingRequest() = 0; virtual void CancelStreamingRequest() = 0; virtual void UpdateRemoteDelay(uint16_t remote_delay_ms) = 0; diff --git a/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc b/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc index dac6c9dbd16..9efe7863c36 100644 --- a/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc +++ b/system/bta/le_audio/audio_hal_client/audio_hal_client_test.cc @@ -166,22 +166,24 @@ LeAudioClientInterface::Source* LeAudioClientInterface::GetSource( return interface_mock->GetSource(stream_cb, message_loop); } -bool LeAudioClientInterface::ReleaseSink(LeAudioClientInterface::Sink* sink) { return true; } -bool LeAudioClientInterface::ReleaseSource(LeAudioClientInterface::Source* source) { return true; } +bool LeAudioClientInterface::ReleaseSink(LeAudioClientInterface::Sink* /*sink*/) { return true; } +bool LeAudioClientInterface::ReleaseSource(LeAudioClientInterface::Source* /*source*/) { + return true; +} -void LeAudioClientInterface::SetAllowedDsaModes(DsaModes dsa_modes) { return; } +void LeAudioClientInterface::SetAllowedDsaModes(DsaModes /*dsa_modes*/) { return; } void LeAudioClientInterface::Sink::Cleanup() {} -void LeAudioClientInterface::Sink::SetPcmParameters(const PcmParameters& params) {} -void LeAudioClientInterface::Sink::SetRemoteDelay(uint16_t delay_report_ms) {} +void LeAudioClientInterface::Sink::SetPcmParameters(const PcmParameters& /*params*/) {} +void LeAudioClientInterface::Sink::SetRemoteDelay(uint16_t /*delay_report_ms*/) {} void LeAudioClientInterface::Sink::StartSession() {} void LeAudioClientInterface::Sink::StopSession() {} void LeAudioClientInterface::Sink::ConfirmStreamingRequest() {} void LeAudioClientInterface::Sink::CancelStreamingRequest() {} void LeAudioClientInterface::Sink::UpdateAudioConfigToHal( - const ::bluetooth::le_audio::offload_config& config) {} + const ::bluetooth::le_audio::offload_config& /*config*/) {} void LeAudioClientInterface::Sink::UpdateBroadcastAudioConfigToHal( - const ::bluetooth::le_audio::broadcast_offload_config& config) {} + const ::bluetooth::le_audio::broadcast_offload_config& /*config*/) {} std::optional<::le_audio::broadcaster::BroadcastConfiguration> LeAudioClientInterface::Sink::GetBroadcastConfig( const std::vector>& quality, @@ -198,14 +200,14 @@ void LeAudioClientInterface::Sink::SuspendedForReconfiguration() {} void LeAudioClientInterface::Sink::ReconfigurationComplete() {} void LeAudioClientInterface::Source::Cleanup() {} -void LeAudioClientInterface::Source::SetPcmParameters(const PcmParameters& params) {} -void LeAudioClientInterface::Source::SetRemoteDelay(uint16_t delay_report_ms) {} +void LeAudioClientInterface::Source::SetPcmParameters(const PcmParameters& /*params*/) {} +void LeAudioClientInterface::Source::SetRemoteDelay(uint16_t /*delay_report_ms*/) {} void LeAudioClientInterface::Source::StartSession() {} void LeAudioClientInterface::Source::StopSession() {} void LeAudioClientInterface::Source::ConfirmStreamingRequest() {} void LeAudioClientInterface::Source::CancelStreamingRequest() {} void LeAudioClientInterface::Source::UpdateAudioConfigToHal( - const ::bluetooth::le_audio::offload_config& config) {} + const ::bluetooth::le_audio::offload_config& /*config*/) {} void LeAudioClientInterface::Source::SuspendedForReconfiguration() {} void LeAudioClientInterface::Source::ReconfigurationComplete() {} diff --git a/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc index 01eb27415d5..8f05b7248be 100644 --- a/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc +++ b/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc @@ -122,7 +122,7 @@ void SinkImpl::Release() { } } -bool SinkImpl::OnResumeReq(bool start_media_task) { +bool SinkImpl::OnResumeReq(bool /*start_media_task*/) { if (audioSinkCallbacks_ == nullptr) { log::error("audioSinkCallbacks_ not set"); return false; @@ -319,7 +319,7 @@ std::unique_ptr LeAudioSinkAudioHalClient::AcquireUni return std::move(impl); } -void LeAudioSinkAudioHalClient::DebugDump(int fd) { +void LeAudioSinkAudioHalClient::DebugDump(int /*fd*/) { /* TODO: Add some statistic for LeAudioSink Audio HAL interface */ } } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc index d6e4e9b537c..b721d4546da 100644 --- a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc +++ b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc @@ -120,7 +120,7 @@ bool SourceImpl::Acquire() { .on_metadata_update_ = std::bind(&SourceImpl::OnMetadataUpdateReq, this, std::placeholders::_1, std::placeholders::_2), .on_sink_metadata_update_ = - [](const sink_metadata_v7_t& sink_metadata) { + [](const sink_metadata_v7_t& /*sink_metadata*/) { // TODO: update microphone configuration based on sink metadata return true; }, @@ -174,7 +174,7 @@ void SourceImpl::Release() { } } -bool SourceImpl::OnResumeReq(bool start_media_task) { +bool SourceImpl::OnResumeReq(bool /*start_media_task*/) { std::lock_guard guard(audioSourceCallbacksMutex_); if (audioSourceCallbacks_ == nullptr) { log::error("audioSourceCallbacks_ not set"); diff --git a/system/bta/le_audio/broadcaster/broadcaster.cc b/system/bta/le_audio/broadcaster/broadcaster.cc index 2b4aed49813..a7b05339b1d 100644 --- a/system/bta/le_audio/broadcaster/broadcaster.cc +++ b/system/bta/le_audio/broadcaster/broadcaster.cc @@ -1041,7 +1041,7 @@ private: } void OnStateMachineEvent(uint32_t broadcast_id, BroadcastStateMachine::State state, - const void* data) override { + const void* /*data*/) override { log::info("broadcast_id={} state={}", broadcast_id, ToString(state)); switch (state) { @@ -1095,7 +1095,8 @@ private: broadcast_id, static_cast(state)); } - void OnOwnAddressResponse(uint32_t broadcast_id, uint8_t addr_type, RawAddress addr) override { + void OnOwnAddressResponse(uint32_t /*broadcast_id*/, uint8_t /*addr_type*/, + RawAddress /*addr*/) override { /* Not used currently */ } @@ -1165,17 +1166,18 @@ private: } } - void OnScanResponseDataSet(uint8_t advertiser_id, uint8_t status) { + void OnScanResponseDataSet(uint8_t advertiser_id, uint8_t /*status*/) { log::warn("Not being used, ignored OnScanResponseDataSet callback advertiser_id:{}", advertiser_id); } - void OnAdvertisingParametersUpdated(uint8_t advertiser_id, int8_t tx_power, uint8_t status) { + void OnAdvertisingParametersUpdated(uint8_t advertiser_id, int8_t /*tx_power*/, + uint8_t /*status*/) { log::warn("Not being used, ignored OnAdvertisingParametersUpdated callback advertiser_id:{}", advertiser_id); } - void OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id, uint8_t status) { + void OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id, uint8_t /*status*/) { log::warn( "Not being used, ignored OnPeriodicAdvertisingParametersUpdated " "callback advertiser_id:{}", @@ -1205,12 +1207,12 @@ private: } } - void OnPeriodicAdvertisingEnabled(uint8_t advertiser_id, bool enable, uint8_t status) { + void OnPeriodicAdvertisingEnabled(uint8_t advertiser_id, bool /*enable*/, uint8_t /*status*/) { log::warn("Not being used, ignored OnPeriodicAdvertisingEnabled callback advertiser_id:{}", advertiser_id); } - void OnOwnAddressRead(uint8_t advertiser_id, uint8_t address_type, RawAddress address) { + void OnOwnAddressRead(uint8_t advertiser_id, uint8_t /*address_type*/, RawAddress /*address*/) { log::warn("Not being used, ignored OnOwnAddressRead callback advertiser_id:{}", advertiser_id); } @@ -1360,7 +1362,7 @@ private: virtual void OnAudioMetadataUpdate( const std::vector source_metadata, - DsaMode dsa_mode) override { + DsaMode /*dsa_mode*/) override { log::info(""); if (!instance) { return; diff --git a/system/bta/le_audio/broadcaster/broadcaster_test.cc b/system/bta/le_audio/broadcaster/broadcaster_test.cc index 75e693d8029..1145b93a4a5 100644 --- a/system/bta/le_audio/broadcaster/broadcaster_test.cc +++ b/system/bta/le_audio/broadcaster/broadcaster_test.cc @@ -91,7 +91,7 @@ void btsnd_hcic_ble_rand(base::Callback cb) { generator_cb = cb std::atomic num_async_tasks; bluetooth::common::MessageLoopThread message_loop_thread("test message loop"); bluetooth::common::MessageLoopThread* get_main_thread() { return &message_loop_thread; } -void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) {} +void invoke_switch_buffer_size_cb(bool /*is_low_latency_buffer_size*/) {} bt_status_t do_in_main_thread(base::OnceClosure task) { // Wrap the task with task counter so we could later know if there are @@ -282,7 +282,7 @@ protected: } }; - test::mock::osi_alarm::alarm_set_on_mloop.body = [](alarm_t* alarm, uint64_t interval_ms, + test::mock::osi_alarm::alarm_set_on_mloop.body = [](alarm_t* alarm, uint64_t /*interval_ms*/, alarm_callback_t cb, void* data) { alarm->cb = cb; alarm->data = data; @@ -757,7 +757,7 @@ TEST_F(BroadcasterTest, UpdateMetadata) { }); EXPECT_CALL(*MockBroadcastStateMachine::GetLastInstance(), UpdatePublicBroadcastAnnouncement) - .WillOnce([&](uint32_t broadcast_id, const std::string& broadcast_name, + .WillOnce([&](uint32_t /*broadcast_id*/, const std::string& broadcast_name, const bluetooth::le_audio::PublicBroadcastAnnouncementData& announcement) { expected_broadcast_name = broadcast_name; expected_public_meta = types::LeAudioLtvMap(announcement.metadata).RawPacket(); @@ -1211,7 +1211,7 @@ TEST_F(BroadcasterTest, AudioActiveState) { ON_CALL(*sm, UpdatePublicBroadcastAnnouncement(broadcast_id, _, _)) .WillByDefault( - [&](uint32_t broadcast_id, const std::string& broadcast_name, + [&](uint32_t /*broadcast_id*/, const std::string& /*broadcast_name*/, const bluetooth::le_audio::PublicBroadcastAnnouncementData& announcement) { pb_announcement = announcement; updated_public_meta = types::LeAudioLtvMap(announcement.metadata).RawPacket(); diff --git a/system/bta/le_audio/broadcaster/broadcaster_types.cc b/system/bta/le_audio/broadcaster/broadcaster_types.cc index 718327f612f..de55101fc21 100644 --- a/system/bta/le_audio/broadcaster/broadcaster_types.cc +++ b/system/bta/le_audio/broadcaster/broadcaster_types.cc @@ -50,7 +50,7 @@ static void EmitHeader(const BasicAudioAnnouncementData& announcement_data, static void EmitCodecConfiguration(const BasicAudioAnnouncementCodecConfig& config, std::vector& data, - const BasicAudioAnnouncementCodecConfig* lower_lvl_config) { + const BasicAudioAnnouncementCodecConfig* /*lower_lvl_config*/) { size_t old_size = data.size(); // Add 5 for full, or 1 for short Codec ID diff --git a/system/bta/le_audio/broadcaster/mock_state_machine.cc b/system/bta/le_audio/broadcaster/mock_state_machine.cc index 8bcba137cd5..253ffc3d8d5 100644 --- a/system/bta/le_audio/broadcaster/mock_state_machine.cc +++ b/system/bta/le_audio/broadcaster/mock_state_machine.cc @@ -52,11 +52,13 @@ std::ostream& operator<<(std::ostream& os, const BroadcastStateMachine::State& s return os; } -std::ostream& operator<<(std::ostream& os, const BigConfig& config) { return os; } +std::ostream& operator<<(std::ostream& os, const BigConfig& /*config*/) { return os; } -std::ostream& operator<<(std::ostream& os, const BroadcastStateMachineConfig& config) { return os; } +std::ostream& operator<<(std::ostream& os, const BroadcastStateMachineConfig& /*config*/) { + return os; +} -std::ostream& operator<<(std::ostream& os, const BroadcastStateMachine& machine) { return os; } +std::ostream& operator<<(std::ostream& os, const BroadcastStateMachine& /*machine*/) { return os; } } // namespace broadcaster } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/broadcaster/mock_state_machine.h b/system/bta/le_audio/broadcaster/mock_state_machine.h index f0445fb27ac..ebafbed3985 100644 --- a/system/bta/le_audio/broadcaster/mock_state_machine.h +++ b/system/bta/le_audio/broadcaster/mock_state_machine.h @@ -37,7 +37,7 @@ public: ON_CALL(*this, ProcessMessage) .WillByDefault( [this](bluetooth::le_audio::broadcaster::BroadcastStateMachine::Message event, - const void* data) { + const void* /*data*/) { const void* sent_data = nullptr; switch (event) { case Message::START: diff --git a/system/bta/le_audio/broadcaster/state_machine_test.cc b/system/bta/le_audio/broadcaster/state_machine_test.cc index 2dca7c5bee4..d8a51aa417b 100644 --- a/system/bta/le_audio/broadcaster/state_machine_test.cc +++ b/system/bta/le_audio/broadcaster/state_machine_test.cc @@ -51,7 +51,7 @@ using testing::Test; // Disables most likely false-positives from base::SplitString() extern "C" const char* __asan_default_options() { return "detect_container_overflow=0"; } -void btsnd_hcic_ble_rand(base::Callback cb) {} +void btsnd_hcic_ble_rand(base::Callback /*cb*/) {} namespace bluetooth::le_audio { namespace broadcaster { @@ -121,14 +121,15 @@ protected: BroadcastStateMachine::Initialize(sm_callbacks_.get(), adv_callbacks_.get()); ON_CALL(*mock_ble_advertising_manager_, StartAdvertisingSet) - .WillByDefault([this](uint8_t client_id, int reg_id, - ::BleAdvertiserInterface::IdTxPowerStatusCallback register_cb, - ::AdvertiseParameters params, std::vector advertise_data, - std::vector scan_response_data, - ::PeriodicAdvertisingParameters periodic_params, - std::vector periodic_data, uint16_t duration, - uint8_t maxExtAdvEvents, - ::BleAdvertiserInterface::IdStatusCallback timeout_cb) { + .WillByDefault([this](uint8_t /*client_id*/, int /*reg_id*/, + ::BleAdvertiserInterface::IdTxPowerStatusCallback /*register_cb*/, + ::AdvertiseParameters /*params*/, + std::vector /*advertise_data*/, + std::vector /*scan_response_data*/, + ::PeriodicAdvertisingParameters /*periodic_params*/, + std::vector /*periodic_data*/, uint16_t /*duration*/, + uint8_t /*maxExtAdvEvents*/, + ::BleAdvertiserInterface::IdStatusCallback /*timeout_cb*/) { static uint8_t advertiser_id = 1; uint8_t tx_power = 32; uint8_t status = 0; @@ -139,32 +140,34 @@ protected: ON_CALL(*mock_ble_advertising_manager_, Enable) .WillByDefault([this](uint8_t advertiser_id, bool enable, - ::BleAdvertiserInterface::StatusCallback cb, uint16_t duration, - uint8_t maxExtAdvEvents, - ::BleAdvertiserInterface::StatusCallback timeout_cb) { + ::BleAdvertiserInterface::StatusCallback /*cb*/, + uint16_t /*duration*/, uint8_t /*maxExtAdvEvents*/, + ::BleAdvertiserInterface::StatusCallback /*timeout_cb*/) { uint8_t status = 0; this->adv_callbacks_->OnAdvertisingEnabled(advertiser_id, enable, status); }); ON_CALL(*mock_ble_advertising_manager_, GetOwnAddress) - .WillByDefault([](uint8_t inst_id, ::BleAdvertiserInterface::GetAddressCallback cb) { - uint8_t address_type = 0x02; - RawAddress address; - const uint8_t addr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - address.FromOctets(addr); - cb.Run(address_type, address); - }); + .WillByDefault( + [](uint8_t /*inst_id*/, ::BleAdvertiserInterface::GetAddressCallback cb) { + uint8_t address_type = 0x02; + RawAddress address; + const uint8_t addr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + address.FromOctets(addr); + cb.Run(address_type, address); + }); ON_CALL(*mock_ble_advertising_manager_, SetData) - .WillByDefault([this](int advertiser_id, bool set_scan_rsp, std::vector data, - ::BleAdvertiserInterface::StatusCallback cb) { + .WillByDefault([this](int advertiser_id, bool /*set_scan_rsp*/, + std::vector /*data*/, + ::BleAdvertiserInterface::StatusCallback /*cb*/) { uint8_t status = 0; this->adv_callbacks_->OnAdvertisingDataSet(advertiser_id, status); }); ON_CALL(*mock_ble_advertising_manager_, SetPeriodicAdvertisingData) - .WillByDefault([this](int advertiser_id, std::vector data, - ::BleAdvertiserInterface::StatusCallback cb) { + .WillByDefault([this](int advertiser_id, std::vector /*data*/, + ::BleAdvertiserInterface::StatusCallback /*cb*/) { uint8_t status = 0; this->adv_callbacks_->OnPeriodicAdvertisingDataSet(advertiser_id, status); }); @@ -191,7 +194,7 @@ protected: }); ON_CALL(*(adv_callbacks_.get()), OnAdvertisingSetStarted) - .WillByDefault([this](int reg_id, uint8_t advertiser_id, int8_t tx_power, + .WillByDefault([this](int /*reg_id*/, uint8_t advertiser_id, int8_t tx_power, uint8_t status) { pending_broadcasts_.back()->OnCreateAnnouncement(advertiser_id, tx_power, status); }); @@ -266,7 +269,7 @@ protected: }); ON_CALL(*mock_iso_manager_, SetupIsoDataPath) - .WillByDefault([this](uint16_t conn_handle, iso_data_path_params p) { + .WillByDefault([this](uint16_t conn_handle, iso_data_path_params /*p*/) { // Get the big_id encoded in conn_handle's MSB uint8_t big_id = conn_handle >> 8; auto bit = std::find_if(broadcasts_.begin(), broadcasts_.end(), @@ -280,7 +283,7 @@ protected: }); ON_CALL(*mock_iso_manager_, RemoveIsoDataPath) - .WillByDefault([this](uint16_t conn_handle, uint8_t iso_direction) { + .WillByDefault([this](uint16_t conn_handle, uint8_t /*iso_direction*/) { // Get the big_id encoded in conn_handle's MSB uint8_t big_id = conn_handle >> 8; auto bit = std::find_if(broadcasts_.begin(), broadcasts_.end(), @@ -366,14 +369,15 @@ protected: TEST_F(StateMachineTest, CreateInstanceFailed) { EXPECT_CALL(*mock_ble_advertising_manager_, StartAdvertisingSet) - .WillOnce([this](uint8_t client_id, int reg_id, - ::BleAdvertiserInterface::IdTxPowerStatusCallback register_cb, - ::AdvertiseParameters params, std::vector advertise_data, - std::vector scan_response_data, - ::PeriodicAdvertisingParameters periodic_params, - std::vector periodic_data, uint16_t duration, - uint8_t maxExtAdvEvents, - ::BleAdvertiserInterface::IdStatusCallback timeout_cb) { + .WillOnce([this](uint8_t /*client_id*/, int /*reg_id*/, + ::BleAdvertiserInterface::IdTxPowerStatusCallback /*register_cb*/, + ::AdvertiseParameters /*params*/, + std::vector /*advertise_data*/, + std::vector /*scan_response_data*/, + ::PeriodicAdvertisingParameters /*periodic_params*/, + std::vector /*periodic_data*/, uint16_t /*duration*/, + uint8_t /*maxExtAdvEvents*/, + ::BleAdvertiserInterface::IdStatusCallback /*timeout_cb*/) { uint8_t advertiser_id = 1; uint8_t tx_power = 0; uint8_t status = 1; @@ -853,7 +857,7 @@ TEST_F(StateMachineTest, OnSetupIsoDataPathError) { ASSERT_EQ(broadcasts_[broadcast_id]->GetState(), BroadcastStateMachine::State::CONFIGURED); EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath) - .WillOnce([this](uint16_t conn_handle, iso_data_path_params p) { + .WillOnce([this](uint16_t conn_handle, iso_data_path_params /*p*/) { // Get the big_id encoded in conn_handle's MSB uint8_t big_id = conn_handle >> 8; auto bit = std::find_if(broadcasts_.begin(), broadcasts_.end(), @@ -865,7 +869,7 @@ TEST_F(StateMachineTest, OnSetupIsoDataPathError) { } bit->second->OnSetupIsoDataPath(0, conn_handle); }) - .WillOnce([this](uint16_t conn_handle, iso_data_path_params p) { + .WillOnce([this](uint16_t conn_handle, iso_data_path_params /*p*/) { // Get the big_id encoded in conn_handle's MSB uint8_t big_id = conn_handle >> 8; auto bit = std::find_if(broadcasts_.begin(), broadcasts_.end(), @@ -886,7 +890,7 @@ TEST_F(StateMachineTest, OnSetupIsoDataPathError) { // And still be able to start again ON_CALL(*mock_iso_manager_, SetupIsoDataPath) - .WillByDefault([this](uint16_t conn_handle, iso_data_path_params p) { + .WillByDefault([this](uint16_t conn_handle, iso_data_path_params /*p*/) { // Get the big_id encoded in conn_handle's MSB uint8_t big_id = conn_handle >> 8; auto bit = std::find_if(broadcasts_.begin(), broadcasts_.end(), @@ -912,7 +916,7 @@ TEST_F(StateMachineTest, OnRemoveIsoDataPathError) { ASSERT_EQ(broadcasts_[broadcast_id]->GetState(), BroadcastStateMachine::State::STREAMING); EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath) - .WillOnce([this](uint16_t conn_handle, uint8_t iso_direction) { + .WillOnce([this](uint16_t conn_handle, uint8_t /*iso_direction*/) { // Get the big_id encoded in conn_handle's MSB uint8_t big_id = conn_handle >> 8; auto bit = std::find_if(broadcasts_.begin(), broadcasts_.end(), @@ -924,7 +928,7 @@ TEST_F(StateMachineTest, OnRemoveIsoDataPathError) { } bit->second->OnRemoveIsoDataPath(0, conn_handle); }) - .WillOnce([this](uint16_t conn_handle, uint8_t iso_direction) { + .WillOnce([this](uint16_t conn_handle, uint8_t /*iso_direction*/) { // Get the big_id encoded in conn_handle's MSB uint8_t big_id = conn_handle >> 8; auto bit = std::find_if(broadcasts_.begin(), broadcasts_.end(), @@ -1027,14 +1031,14 @@ TEST_F(StateMachineTest, AnnouncementTest) { EXPECT_CALL(*mock_ble_advertising_manager_, StartAdvertisingSet) .WillOnce([this, &p_data, &a_data, &adv_params]( - uint8_t client_id, int reg_id, - ::BleAdvertiserInterface::IdTxPowerStatusCallback register_cb, + uint8_t /*client_id*/, int /*reg_id*/, + ::BleAdvertiserInterface::IdTxPowerStatusCallback /*register_cb*/, ::AdvertiseParameters params, std::vector advertise_data, - std::vector scan_response_data, - ::PeriodicAdvertisingParameters periodic_params, - std::vector periodic_data, uint16_t duration, - uint8_t maxExtAdvEvents, - ::BleAdvertiserInterface::IdStatusCallback timeout_cb) { + std::vector /*scan_response_data*/, + ::PeriodicAdvertisingParameters /*periodic_params*/, + std::vector periodic_data, uint16_t /*duration*/, + uint8_t /*maxExtAdvEvents*/, + ::BleAdvertiserInterface::IdStatusCallback /*timeout_cb*/) { uint8_t advertiser_id = 1; uint8_t tx_power = 0; uint8_t status = 0; @@ -1087,8 +1091,8 @@ TEST_F(StateMachineTest, GetMetadataBeforeGettingAddress) { /* Address should be already known after notifying callback recipients */ EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(_, BroadcastStateMachine::State::CONFIGURED, _)) - .WillOnce([this](uint32_t broadcast_id, BroadcastStateMachine::State state, - const void* data) { + .WillOnce([this](uint32_t broadcast_id, BroadcastStateMachine::State /*state*/, + const void* /*data*/) { RawAddress test_address; RawAddress::FromString("00:00:00:00:00:00", test_address); diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index a0568998e2e..20eb101f097 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -2057,8 +2057,8 @@ public: } } - void OnGattReadRsp(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hdl, uint16_t len, - uint8_t* value, void* data) { + void OnGattReadRsp(tCONN_ID conn_id, tGATT_STATUS /*status*/, uint16_t hdl, uint16_t len, + uint8_t* value, void* /*data*/) { LeAudioCharValueHandle(conn_id, hdl, len, value); } @@ -2099,7 +2099,7 @@ public: } } - void OnGattConnected(tGATT_STATUS status, tCONN_ID conn_id, tGATT_IF client_if, + void OnGattConnected(tGATT_STATUS status, tCONN_ID conn_id, tGATT_IF /*client_if*/, RawAddress address, tBT_TRANSPORT transport, uint16_t mtu) { LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address); @@ -2476,7 +2476,7 @@ public: std::chrono::milliseconds(kCsisGroupMemberDelayMs)); } - void OnGattDisconnected(tCONN_ID conn_id, tGATT_IF client_if, RawAddress address, + void OnGattDisconnected(tCONN_ID conn_id, tGATT_IF /*client_if*/, RawAddress address, tGATT_DISCONN_REASON reason) { LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id); @@ -2598,8 +2598,8 @@ public: BtaGattQueue::WriteDescriptor( conn_id, ccc_handle, std::move(value), GATT_WRITE, - [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) { + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* data) { if (instance) { instance->OnGattWriteCcc(conn_id, status, handle, data); } @@ -3095,7 +3095,7 @@ public: bluetooth::le_audio::uuid::kCapServiceUuid); } - void OnGattWriteCcc(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hdl, void* data) { + void OnGattWriteCcc(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hdl, void* /*data*/) { LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id); std::vector::iterator ase_it; @@ -4880,7 +4880,7 @@ public: return remote_metadata; } - bool ReconfigureOrUpdateRemoteForPTS(LeAudioDeviceGroup* group, int remote_direction) { + bool ReconfigureOrUpdateRemoteForPTS(LeAudioDeviceGroup* group, int /*remote_direction*/) { log::info("{}", group->group_id_); // Use common audio stream contexts exposed by the PTS auto override_contexts = AudioContexts(0xFFFF); @@ -6000,8 +6000,10 @@ public: instance->OnGroupMemberRemovedCb(address, group_id); } } - void OnGroupRemoved(const bluetooth::Uuid& uuid, int group_id) { /* to implement if needed */ } - void OnGroupAddFromStorage(const RawAddress& address, const bluetooth::Uuid& uuid, int group_id) { + void OnGroupRemoved(const bluetooth::Uuid& /*uuid*/, + int /*group_id*/) { /* to implement if needed */ } + void OnGroupAddFromStorage(const RawAddress& /*address*/, const bluetooth::Uuid& /*uuid*/, + int /*group_id*/) { /* to implement if needed */ } }; diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc index 13d9afc2188..469241ad976 100644 --- a/system/bta/le_audio/codec_manager_test.cc +++ b/system/bta/le_audio/codec_manager_test.cc @@ -132,7 +132,7 @@ std::unique_ptr LeAudioSourceAudioHalClient::Acquir return std::move(owned_mock_broadcast_le_audio_source_hal_client_); } -void LeAudioSourceAudioHalClient::DebugDump(int fd) {} +void LeAudioSourceAudioHalClient::DebugDump(int /*fd*/) {} class MockLeAudioSinkHalClient; MockLeAudioSinkHalClient* mock_le_audio_sink_hal_client_; @@ -511,8 +511,9 @@ TEST_F(CodecManagerTestAdsp, test_capabilities_none) { codec_manager->Start(offloading_preference); bool has_null_config = false; - auto match_first_config = [&](const CodecManager::UnicastConfigurationRequirements& requirements, - const set_configurations::AudioSetConfigurations* confs) + auto match_first_config = + [&](const CodecManager::UnicastConfigurationRequirements& /*requirements*/, + const set_configurations::AudioSetConfigurations* confs) -> std::unique_ptr { // Don't expect the matcher being called on nullptr if (confs == nullptr) { @@ -559,7 +560,7 @@ TEST_F(CodecManagerTestAdsp, test_capabilities) { size_t available_configs_size = 0; auto match_first_config = [&available_configs_size]( - const CodecManager::UnicastConfigurationRequirements& requirements, + const CodecManager::UnicastConfigurationRequirements& /*requirements*/, const set_configurations::AudioSetConfigurations* confs) -> std::unique_ptr { if (confs && confs->size()) { @@ -990,7 +991,7 @@ TEST_F(CodecManagerTestHost, test_dual_bidir_swb_supported) { bool got_null_cfgs_container = false; auto ptr = codec_manager->GetCodecConfig( {.audio_context_type = context}, - [&](const CodecManager::UnicastConfigurationRequirements& requirements, + [&](const CodecManager::UnicastConfigurationRequirements& /*requirements*/, const set_configurations::AudioSetConfigurations* confs) -> std::unique_ptr { if (confs == nullptr) { @@ -1040,7 +1041,7 @@ TEST_F(CodecManagerTestAdsp, test_dual_bidir_swb_supported) { bool got_null_cfgs_container = false; auto ptr = codec_manager->GetCodecConfig( {.audio_context_type = context}, - [&](const CodecManager::UnicastConfigurationRequirements& requirements, + [&](const CodecManager::UnicastConfigurationRequirements& /*requirements*/, const set_configurations::AudioSetConfigurations* confs) -> std::unique_ptr { if (confs == nullptr) { @@ -1072,7 +1073,7 @@ TEST_F(CodecManagerTestHostNoSwb, test_dual_bidir_swb_not_supported) { bool got_null_cfgs_container = false; auto ptr = codec_manager->GetCodecConfig( {.audio_context_type = context}, - [&](const CodecManager::UnicastConfigurationRequirements& requirements, + [&](const CodecManager::UnicastConfigurationRequirements& /*requirements*/, const set_configurations::AudioSetConfigurations* confs) -> std::unique_ptr { if (confs == nullptr) { @@ -1121,7 +1122,7 @@ TEST_F(CodecManagerTestAdspNoSwb, test_dual_bidir_swb_not_supported) { bool got_null_cfgs_container = false; auto ptr = codec_manager->GetCodecConfig( {.audio_context_type = context}, - [&](const CodecManager::UnicastConfigurationRequirements& requirements, + [&](const CodecManager::UnicastConfigurationRequirements& /*requirements*/, const set_configurations::AudioSetConfigurations* confs) -> std::unique_ptr { if (confs == nullptr) { @@ -1149,8 +1150,9 @@ TEST_F(CodecManagerTestHost, test_dont_update_broadcast_offloader) { bool was_called = false; codec_manager->UpdateBroadcastConnHandle( - {0x0001, 0x0002}, - [&](const bluetooth::le_audio::broadcast_offload_config& config) { was_called = true; }); + {0x0001, 0x0002}, [&](const bluetooth::le_audio::broadcast_offload_config& /*config*/) { + was_called = true; + }); // Expect no call for HOST encoding ASSERT_FALSE(was_called); diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc index 28b9be0eede..d0b9b528afa 100644 --- a/system/bta/le_audio/devices.cc +++ b/system/bta/le_audio/devices.cc @@ -1296,7 +1296,7 @@ LeAudioDevice* LeAudioDevices::FindByCisConnHdl(uint8_t cig_id, uint16_t conn_hd } void LeAudioDevices::SetInitialGroupAutoconnectState(int group_id, int gatt_if, - tBTM_BLE_CONN_TYPE reconnection_mode, + tBTM_BLE_CONN_TYPE /*reconnection_mode*/, bool current_dev_autoconnect_flag) { if (!current_dev_autoconnect_flag) { /* If current device autoconnect flag is false, check if there is other diff --git a/system/bta/le_audio/devices_test.cc b/system/bta/le_audio/devices_test.cc index d9845b2deb4..1ad0684ce6e 100644 --- a/system/bta/le_audio/devices_test.cc +++ b/system/bta/le_audio/devices_test.cc @@ -39,7 +39,9 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -tACL_CONN* btm_bda_to_acl(const RawAddress& bda, tBT_TRANSPORT transport) { return nullptr; } +tACL_CONN* btm_bda_to_acl(const RawAddress& /*bda*/, tBT_TRANSPORT /*transport*/) { + return nullptr; +} namespace bluetooth { namespace le_audio { @@ -523,12 +525,12 @@ protected: MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_); ON_CALL(mock_csis_client_module_, Get()).WillByDefault(Return(&mock_csis_client_module_)); ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); - ON_CALL(mock_csis_client_module_, GetDeviceList(_)).WillByDefault(Invoke([this](int group_id) { - return addresses_; - })); - ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Invoke([this](int group_id) { - return desired_group_size_ > 0 ? desired_group_size_ : (int)(addresses_.size()); - })); + ON_CALL(mock_csis_client_module_, GetDeviceList(_)) + .WillByDefault(Invoke([this](int /*group_id*/) { return addresses_; })); + ON_CALL(mock_csis_client_module_, GetDesiredSize(_)) + .WillByDefault(Invoke([this](int /*group_id*/) { + return desired_group_size_ > 0 ? desired_group_size_ : (int)(addresses_.size()); + })); SetUpMockCodecManager(codec_location); } diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 9b9498aa0f0..28ca1826fc8 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -135,7 +135,7 @@ bt_status_t do_in_main_thread(base::OnceClosure task) { return BT_STATUS_SUCCESS; } -bt_status_t do_in_main_thread_delayed(base::OnceClosure task, std::chrono::microseconds delay) { +bt_status_t do_in_main_thread_delayed(base::OnceClosure task, std::chrono::microseconds /*delay*/) { /* For testing purpose it is ok to just skip delay */ return do_in_main_thread(std::move(task)); } @@ -164,8 +164,8 @@ static void cleanup_message_loop_thread() { message_loop_thread.ShutDown(); } -void invoke_switch_codec_cb(bool is_low_latency_buffer_size) {} -void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) {} +void invoke_switch_codec_cb(bool /*is_low_latency_buffer_size*/) {} +void invoke_switch_buffer_size_cb(bool /*is_low_latency_buffer_size*/) {} const std::string kSmpOptions("mock smp options"); bool get_pts_avrcp_test(void) { return false; } @@ -219,7 +219,7 @@ std::unique_ptr LeAudioSourceAudioHalClient::Acquir return std::move(owned_mock_le_audio_source_hal_client_); } -void LeAudioSourceAudioHalClient::DebugDump(int fd) {} +void LeAudioSourceAudioHalClient::DebugDump(int /*fd*/) {} class MockLeAudioSinkHalClient; MockLeAudioSinkHalClient* mock_le_audio_sink_hal_client_; @@ -234,7 +234,7 @@ std::unique_ptr LeAudioSinkAudioHalClient::AcquireUni return std::move(owned_mock_le_audio_sink_hal_client_); } -void LeAudioSinkAudioHalClient::DebugDump(int fd) {} +void LeAudioSinkAudioHalClient::DebugDump(int /*fd*/) {} RawAddress GetTestAddress(uint8_t index) { EXPECT_LT(index, UINT8_MAX); @@ -340,9 +340,9 @@ protected: is_audio_unicast_source_acquired = false; ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)) - .WillByDefault([this](const LeAudioCodecConfiguration& codec_configuration, + .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/, LeAudioSourceAudioHalClient::Callbacks* audioReceiver, - DsaModes dsa_modes) { + DsaModes /*dsa_modes*/) { unicast_source_hal_cb_ = audioReceiver; return true; }); @@ -359,9 +359,9 @@ protected: is_audio_unicast_sink_acquired = false; ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)) - .WillByDefault([this](const LeAudioCodecConfiguration& codec_configuration, + .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/, LeAudioSinkAudioHalClient::Callbacks* audioReceiver, - DsaModes dsa_modes) { + DsaModes /*dsa_modes*/) { unicast_sink_hal_cb_ = audioReceiver; return true; }); @@ -387,9 +387,9 @@ protected: is_audio_unicast_source_acquired = false; ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)) - .WillByDefault([this](const LeAudioCodecConfiguration& codec_configuration, + .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/, LeAudioSourceAudioHalClient::Callbacks* audioReceiver, - DsaModes dsa_modes) { + DsaModes /*dsa_modes*/) { unicast_source_hal_cb_ = audioReceiver; return true; }); @@ -400,9 +400,9 @@ protected: is_audio_unicast_sink_acquired = false; ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)) - .WillByDefault([this](const LeAudioCodecConfiguration& codec_configuration, + .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/, LeAudioSinkAudioHalClient::Callbacks* audioReceiver, - DsaModes dsa_modes) { + DsaModes /*dsa_modes*/) { unicast_sink_hal_cb_ = audioReceiver; return true; }); @@ -412,7 +412,7 @@ protected: }); ON_CALL(*mock_le_audio_sink_hal_client_, SendData) - .WillByDefault([](uint8_t* data, uint16_t size) { return size; }); + .WillByDefault([](uint8_t* /*data*/, uint16_t size) { return size; }); // HAL ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool { return true; }); @@ -641,8 +641,9 @@ protected: // default action for WriteDescriptor function call ON_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)) .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle, - std::vector value, tGATT_WRITE_TYPE write_type, - GATT_WRITE_OP_CB cb, void* cb_data) -> void { + std::vector value, + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, + void* cb_data) -> void { auto& ascs = peer_devices.at(conn_id)->ascs; uint8_t idx; @@ -673,8 +674,8 @@ protected: global_conn_id = 1; ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)) - .WillByDefault(Invoke([&](tGATT_IF client_if, const RawAddress& remote_bda, - bool is_direct, bool opportunistic) { + .WillByDefault(Invoke([&](tGATT_IF /*client_if*/, const RawAddress& remote_bda, + bool /*is_direct*/, bool /*opportunistic*/) { InjectConnectedEvent(remote_bda, global_conn_id++); })); @@ -804,7 +805,7 @@ protected: ON_CALL(mock_groups_module_, Initialize(_)).WillByDefault(SaveArg<0>(&group_callbacks_)); ON_CALL(mock_groups_module_, GetGroupId(_, _)) - .WillByDefault([this](const RawAddress& addr, bluetooth::Uuid uuid) { + .WillByDefault([this](const RawAddress& addr, bluetooth::Uuid /*uuid*/) { if (groups.find(addr) != groups.end()) { return groups.at(addr); } @@ -812,7 +813,7 @@ protected: }); ON_CALL(mock_groups_module_, RemoveDevice(_, _)) - .WillByDefault([this](const RawAddress& addr, int group_id_) { + .WillByDefault([this](const RawAddress& addr, int /*group_id*/) { int group_id = -1; if (groups.find(addr) != groups.end()) { group_id = groups[addr]; @@ -833,20 +834,21 @@ protected: // Our test devices have unique LSB - use it for unique grouping when // devices added with a non-CIS context and no grouping info ON_CALL(mock_groups_module_, AddDevice(_, bluetooth::le_audio::uuid::kCapServiceUuid, _)) - .WillByDefault([this](const RawAddress& addr, - bluetooth::Uuid uuid = bluetooth::le_audio::uuid::kCapServiceUuid, - int group_id = bluetooth::groups::kGroupUnknown) -> int { - if (group_id == bluetooth::groups::kGroupUnknown) { - /* Generate group id from address */ - groups[addr] = addr.address[RawAddress::kLength - 1]; - group_id = groups[addr]; - } else { - groups[addr] = group_id; - } + .WillByDefault( + [this](const RawAddress& addr, + bluetooth::Uuid /*uuid*/ = bluetooth::le_audio::uuid::kCapServiceUuid, + int group_id = bluetooth::groups::kGroupUnknown) -> int { + if (group_id == bluetooth::groups::kGroupUnknown) { + /* Generate group id from address */ + groups[addr] = addr.address[RawAddress::kLength - 1]; + group_id = groups[addr]; + } else { + groups[addr] = group_id; + } - InjectGroupDeviceAdded(addr, groups[addr]); - return addr.address[RawAddress::kLength - 1]; - }); + InjectGroupDeviceAdded(addr, groups[addr]); + return addr.address[RawAddress::kLength - 1]; + }); ON_CALL(mock_state_machine_, Initialize(_)) .WillByDefault(SaveArg<0>(&state_machine_callbacks_)); @@ -1721,14 +1723,14 @@ protected: void DisconnectLeAudioWithGattClose( const RawAddress& address, uint16_t conn_id, - tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) { + tGATT_DISCONN_REASON /*reason*/ = GATT_CONN_TERMINATE_LOCAL_HOST) { EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::DISCONNECTED, address)) .Times(1); // For test purpose use the acl handle same as conn_id ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _)) - .WillByDefault([conn_id](RawAddress const& bd_addr, tBT_TRANSPORT transport) { + .WillByDefault([conn_id](RawAddress const& /*bd_addr*/, tBT_TRANSPORT /*transport*/) { return conn_id; }); EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(0); @@ -1750,11 +1752,11 @@ protected: // For test purpose use the acl handle same as conn_id ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _)) - .WillByDefault([conn_id](RawAddress const& bd_addr, tBT_TRANSPORT transport) { + .WillByDefault([conn_id](RawAddress const& /*bd_addr*/, tBT_TRANSPORT /*transport*/) { return conn_id; }); EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)) - .WillOnce([this, &reason](uint16_t handle, tHCI_STATUS rs) { + .WillOnce([this, &reason](uint16_t handle, tHCI_STATUS /*rs*/) { InjectDisconnectedEvent(handle, reason); }); EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(0); @@ -1949,7 +1951,7 @@ protected: Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); } - void StartStreaming(audio_usage_t usage, audio_content_type_t content_type, int group_id, + void StartStreaming(audio_usage_t usage, audio_content_type_t content_type, int /*group_id*/, audio_source_t audio_source = AUDIO_SOURCE_INVALID, bool reconfigure_existing_stream = false, bool expected_resume_confirmation = true) { @@ -1978,7 +1980,7 @@ protected: SyncOnMainLoop(); } - void StopStreaming(int group_id, bool suspend_source = false) { + void StopStreaming(int /*group_id*/, bool suspend_source = false) { ASSERT_NE(unicast_source_hal_cb_, nullptr); /* TODO We should have a way to confirm Stop() otherwise, audio framework @@ -2579,8 +2581,8 @@ protected: if (cis_count_out) { EXPECT_CALL(*mock_iso_manager_, SendIsoData(_, _, _)) .Times(cis_count_out) - .WillRepeatedly([&handles](uint16_t iso_handle, const uint8_t* data, - uint16_t data_len) { handles.push_back(iso_handle); }); + .WillRepeatedly([&handles](uint16_t iso_handle, const uint8_t* /*data*/, + uint16_t /*data_len*/) { handles.push_back(iso_handle); }); } std::vector data(data_len); unicast_source_hal_cb_->OnAudioDataReady(data); @@ -2729,17 +2731,18 @@ protected: EXPECT_CALL(mock_storage_load, Call()).Times(1); ON_CALL(mock_btm_interface_, GetHCIConnHandle(_, _)) - .WillByDefault([this](RawAddress const& bd_addr, tBT_TRANSPORT transport) -> uint16_t { - for (auto const& [conn_id, dev_wrapper] : peer_devices) { - if (dev_wrapper->addr == bd_addr) { - return conn_id; - } - } - log::error("GetHCIConnHandle Mock: not a valid test device!"); - return 0x00FE; - }); + .WillByDefault( + [this](RawAddress const& bd_addr, tBT_TRANSPORT /*transport*/) -> uint16_t { + for (auto const& [conn_id, dev_wrapper] : peer_devices) { + if (dev_wrapper->addr == bd_addr) { + return conn_id; + } + } + log::error("GetHCIConnHandle Mock: not a valid test device!"); + return 0x00FE; + }); ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)) - .WillByDefault([this](uint16_t handle, tHCI_STATUS rs) { + .WillByDefault([this](uint16_t handle, tHCI_STATUS /*rs*/) { ASSERT_NE(handle, GATT_INVALID_CONN_ID); InjectDisconnectedEvent(handle, GATT_CONN_TERMINATE_LOCAL_HOST); }); @@ -3097,7 +3100,7 @@ TEST_F(UnicastTest, ConnectOneEarbudWithInvalidCsis) { /* Make sure Group has not knowledge about the device */ ON_CALL(mock_groups_module_, GetGroupId(_, _)) - .WillByDefault([](const RawAddress& addr, bluetooth::Uuid uuid) { + .WillByDefault([](const RawAddress& /*addr*/, bluetooth::Uuid /*uuid*/) { return bluetooth::groups::kGroupUnknown; }); @@ -3242,7 +3245,7 @@ TEST_F(UnicastTestHealthStatus, ConnectOneEarbudWithInvalidCsis_withHealthStatus /* Make sure Group has not knowledge about the device */ ON_CALL(mock_groups_module_, GetGroupId(_, _)) - .WillByDefault([](const RawAddress& addr, bluetooth::Uuid uuid) { + .WillByDefault([](const RawAddress& /*addr*/, bluetooth::Uuid /*uuid*/) { return bluetooth::groups::kGroupUnknown; }); @@ -5089,7 +5092,7 @@ TEST_F(UnicastTest, TestUpdateConfigurationCallbackWhileStreaming) { do_in_main_thread(base::BindOnce( [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks, - LeAudioDeviceGroup* group) { + LeAudioDeviceGroup* /*group*/) { state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING); }, group_id, base::Unretained(this->state_machine_callbacks_), std::move(group))); @@ -5128,7 +5131,7 @@ TEST_F(UnicastTest, TestDeactivateWhileStartingStream) { do_in_main_thread(base::BindOnce( [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks, - LeAudioDeviceGroup* group) { + LeAudioDeviceGroup* /*group*/) { state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING); }, group_id, base::Unretained(this->state_machine_callbacks_), std::move(group))); @@ -6411,7 +6414,7 @@ TEST_F(UnicastTest, TwoEarbudsStreaming) { // Report working CSIS ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -7822,7 +7825,7 @@ TEST_F(UnicastTest, StreamingVxAospSampleSound) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -7873,7 +7876,7 @@ TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSinkSource) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -7899,7 +7902,7 @@ TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSinkSource) { EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1); EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _)) .Times(1) - .WillOnce([](const types::BidirectionalPair& stream_params, + .WillOnce([](const types::BidirectionalPair& /*stream_params*/, types::BidirectionalPair delays_ms, std::function update_receiver) { @@ -7936,7 +7939,7 @@ TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSource) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -7961,7 +7964,7 @@ TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSource) { EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(0); EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _)) .Times(1) - .WillOnce([](const types::BidirectionalPair& stream_params, + .WillOnce([](const types::BidirectionalPair& /*stream_params*/, types::BidirectionalPair delays_ms, std::function update_receiver) { @@ -7997,7 +8000,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -8085,7 +8088,7 @@ TEST_F(UnicastTest, TwoEarbudsStopConversational_StartStreamSonification) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -8169,7 +8172,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -8267,7 +8270,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigF ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -8398,7 +8401,7 @@ TEST_F(UnicastTest, TwoEarbudsVoipStreamingVerifyMetadataUpdate) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -8467,7 +8470,7 @@ TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -8550,7 +8553,7 @@ TEST_F(UnicastTest, TwoEarbuds2ndLateConnect) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -8608,7 +8611,7 @@ TEST_F(UnicastTest, LateStreamConnectBasedOnContextType) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -8685,7 +8688,7 @@ TEST_F(UnicastTest, LateStreamConnectBasedOnContextTypeNotFullyConnected) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -8746,7 +8749,7 @@ TEST_F(UnicastTest, CheckDeviceIsNotAttachedToStreamWhenNotNeeded) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -8821,7 +8824,7 @@ TEST_F(UnicastTest, ReconnectedDeviceAndAttachedToStreamBecauseOfAvailableContex ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -8919,7 +8922,7 @@ TEST_F(UnicastTest, ReconnectedDeviceNotAttachedToStreamBecauseOfNotAvailableCon ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -9019,7 +9022,7 @@ TEST_F(UnicastTest, TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -9107,7 +9110,7 @@ TEST_F(UnicastTest, StartStream_AvailableContextTypeNotifiedLater) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -9168,7 +9171,7 @@ TEST_F(UnicastTest, ModifyContextTypeOnDeviceA_WhileDeviceB_IsDisconnected) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -9258,7 +9261,7 @@ TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUsingUnspecified) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -9327,7 +9330,7 @@ TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable) ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -9406,7 +9409,7 @@ TEST_F(UnicastTest, StartStreamToSupportedContextTypeThenMixUnavailable) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); const RawAddress test_address0 = GetTestAddress(0); const RawAddress test_address1 = GetTestAddress(1); @@ -9529,7 +9532,7 @@ TEST_F(UnicastTest, TwoEarbuds2ndDisconnected) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -9580,7 +9583,7 @@ TEST_F(UnicastTest, TwoEarbuds2ndDisconnected) { int num_of_connected = 0; ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _)) .WillByDefault( - [&num_of_connected](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { + [&num_of_connected](LeAudioDeviceGroup* group, LeAudioDevice* /*leAudioDevice*/) { num_of_connected = group->NumOfConnected(); }); @@ -9616,7 +9619,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnect) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -9675,7 +9678,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnectStreamStopTimeout) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -11195,7 +11198,7 @@ TEST_F(UnicastTest, AddMemberToAllowListWhenOneDeviceConnected) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -11252,7 +11255,7 @@ TEST_F(UnicastTest, ResetToDefaultReconnectionMode) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -11674,7 +11677,7 @@ TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsActive) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -11820,7 +11823,7 @@ TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsInactive) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -11914,7 +11917,7 @@ TEST_F(UnicastTestHandoverMode, ClearSinkMonitorModeWhileUnicastIsActive) { ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return group_size; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; })); // First earbud const RawAddress test_address0 = GetTestAddress(0); @@ -12075,7 +12078,7 @@ TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsActive) { true /*connect_through_csis*/); ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id)) - .WillByDefault(Invoke([&](int group_id) { return 2; })); + .WillByDefault(Invoke([&](int /*group_id*/) { return 2; })); // Start streaming EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); @@ -12395,9 +12398,9 @@ TEST_F(UnicastTest, CodecFrameBlocks2) { ON_CALL(*mock_codec_manager_, UpdateActiveAudioConfig) .WillByDefault( Invoke([&](const types::BidirectionalPair& stream_params, - types::BidirectionalPair delays_ms, + types::BidirectionalPair /*delays_ms*/, std::function - updater) { codec_manager_stream_params = stream_params; })); + /*updater*/) { codec_manager_stream_params = stream_params; })); const RawAddress test_address0 = GetTestAddress(0); int group_id = bluetooth::groups::kGroupUnknown; diff --git a/system/bta/le_audio/metrics_collector_linux.cc b/system/bta/le_audio/metrics_collector_linux.cc index e505ce0e1ac..de2c267b8ee 100644 --- a/system/bta/le_audio/metrics_collector_linux.cc +++ b/system/bta/le_audio/metrics_collector_linux.cc @@ -28,18 +28,18 @@ MetricsCollector* MetricsCollector::Get() { return MetricsCollector::instance; } -void MetricsCollector::OnGroupSizeUpdate(int32_t group_id, int32_t group_size) {} +void MetricsCollector::OnGroupSizeUpdate(int32_t /*group_id*/, int32_t /*group_size*/) {} -void MetricsCollector::OnConnectionStateChanged(int32_t group_id, const RawAddress& address, - bluetooth::le_audio::ConnectionState state, - ConnectionStatus status) {} +void MetricsCollector::OnConnectionStateChanged(int32_t /*group_id*/, const RawAddress& /*address*/, + bluetooth::le_audio::ConnectionState /*state*/, + ConnectionStatus /*status*/) {} void MetricsCollector::OnStreamStarted( - int32_t group_id, bluetooth::le_audio::types::LeAudioContextType context_type) {} + int32_t /*group_id*/, bluetooth::le_audio::types::LeAudioContextType /*context_type*/) {} -void MetricsCollector::OnStreamEnded(int32_t group_id) {} +void MetricsCollector::OnStreamEnded(int32_t /*group_id*/) {} -void MetricsCollector::OnBroadcastStateChanged(bool started) {} +void MetricsCollector::OnBroadcastStateChanged(bool /*started*/) {} void MetricsCollector::Flush() {} diff --git a/system/bta/le_audio/mock_codec_interface.cc b/system/bta/le_audio/mock_codec_interface.cc index 67c88d136d3..fb1655af432 100644 --- a/system/bta/le_audio/mock_codec_interface.cc +++ b/system/bta/le_audio/mock_codec_interface.cc @@ -24,7 +24,7 @@ namespace bluetooth::le_audio { struct CodecInterface::Impl : public MockCodecInterface { public: - Impl(const types::LeAudioCodecId& codec_id) { output_channel_data_.resize(1); } + Impl(const types::LeAudioCodecId& /*codec_id*/) { output_channel_data_.resize(1); } ~Impl() = default; std::vector& GetDecodedSamples() { return output_channel_data_; } diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index d21b831ba32..e3e3b9c481b 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -481,7 +481,7 @@ public: } } - void ProcessHciNotifOnCigCreate(LeAudioDeviceGroup* group, uint8_t status, uint8_t cig_id, + void ProcessHciNotifOnCigCreate(LeAudioDeviceGroup* group, uint8_t status, uint8_t /*cig_id*/, std::vector conn_handles) override { /* TODO: What if not all cises will be configured ? * conn_handle.size() != active ases in group @@ -717,9 +717,10 @@ public: } } - void ProcessHciNotifIsoLinkQualityRead(LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice, - uint8_t conn_handle, uint32_t txUnackedPackets, - uint32_t txFlushedPackets, uint32_t txLastSubeventPackets, + void ProcessHciNotifIsoLinkQualityRead(LeAudioDeviceGroup* /*group*/, + LeAudioDevice* /*leAudioDevice*/, uint8_t conn_handle, + uint32_t txUnackedPackets, uint32_t txFlushedPackets, + uint32_t txLastSubeventPackets, uint32_t retransmittedPackets, uint32_t crcErrorPackets, uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) { log::info( @@ -1766,9 +1767,9 @@ private: return nullptr; } - void AseStateMachineProcessIdle(struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& arh, - struct ase* ase, LeAudioDeviceGroup* group, - LeAudioDevice* leAudioDevice) { + void AseStateMachineProcessIdle( + struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& /*arh*/, struct ase* ase, + LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { switch (ase->state) { case AseState::BTA_LE_AUDIO_ASE_STATE_IDLE: case AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED: @@ -1913,7 +1914,7 @@ private: } void AseStateMachineProcessCodecConfigured( - struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, + struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& /*arh*/, struct ase* ase, uint8_t* data, uint16_t len, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { if (!group) { log::error("leAudioDevice doesn't belong to any group"); @@ -2225,7 +2226,7 @@ private: } void AseStateMachineProcessQosConfigured( - struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, + struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& /*arh*/, struct ase* ase, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { if (!group) { log::error("leAudioDevice doesn't belong to any group"); @@ -2711,7 +2712,7 @@ private: } void AseStateMachineProcessEnabling( - struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, + struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& /*arh*/, struct ase* ase, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { if (!group) { log::error("leAudioDevice doesn't belong to any group"); @@ -2779,7 +2780,7 @@ private: } void AseStateMachineProcessStreaming( - struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, + struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& /*arh*/, struct ase* ase, uint8_t* data, uint16_t len, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { if (!group) { log::error("leAudioDevice doesn't belong to any group"); @@ -2866,7 +2867,7 @@ private: } void AseStateMachineProcessDisabling( - struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, + struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& /*arh*/, struct ase* ase, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { if (!group) { log::error("leAudioDevice doesn't belong to any group"); @@ -2953,7 +2954,7 @@ private: } void AseStateMachineProcessReleasing( - struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase, + struct bluetooth::le_audio::client_parser::ascs::ase_rsp_hdr& /*arh*/, struct ase* ase, LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) { if (!group) { log::error("leAudioDevice doesn't belong to any group"); diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index 02212d6dbf2..ed44a5003fa 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -283,17 +283,15 @@ protected: MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_); ON_CALL(mock_csis_client_module_, Get()).WillByDefault(Return(&mock_csis_client_module_)); ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true)); - ON_CALL(mock_csis_client_module_, GetDeviceList(_)).WillByDefault(Invoke([this](int group_id) { - return addresses_; - })); - ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Invoke([this](int group_id) { - return (int)(addresses_.size()); - })); + ON_CALL(mock_csis_client_module_, GetDeviceList(_)) + .WillByDefault(Invoke([this](int /*group_id*/) { return addresses_; })); + ON_CALL(mock_csis_client_module_, GetDesiredSize(_)) + .WillByDefault(Invoke([this](int /*group_id*/) { return (int)(addresses_.size()); })); // Support 2M Phy ON_CALL(btm_interface, IsPhy2mSupported(_, _)).WillByDefault(Return(true)); ON_CALL(btm_interface, GetHCIConnHandle(_, _)) - .WillByDefault(Invoke([](RawAddress const& remote_bda, tBT_TRANSPORT transport) { + .WillByDefault(Invoke([](RawAddress const& remote_bda, tBT_TRANSPORT /*transport*/) { return remote_bda.IsEmpty() ? HCI_INVALID_HANDLE : ((uint16_t)(remote_bda.address[0] ^ remote_bda.address[1] ^ @@ -304,9 +302,9 @@ protected: })); ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, GATT_WRITE_NO_RSP, _, _)) - .WillByDefault( - Invoke([this](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { + .WillByDefault(Invoke( + [this](uint16_t conn_id, uint16_t handle, std::vector value, + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, void* cb_data) { for (auto& dev : le_audio_devices_) { if (dev->conn_id_ == conn_id) { // Control point write handler @@ -396,7 +394,7 @@ protected: } }); - ON_CALL(*mock_iso_manager_, RemoveCig).WillByDefault([this](uint8_t cig_id, bool force) { + ON_CALL(*mock_iso_manager_, RemoveCig).WillByDefault([this](uint8_t cig_id, bool /*force*/) { log::debug("CreateRemove"); auto& group = le_audio_device_groups_[cig_id]; @@ -408,7 +406,7 @@ protected: ON_CALL(*mock_iso_manager_, SetupIsoDataPath) .WillByDefault([this](uint16_t conn_handle, - bluetooth::hci::iso_manager::iso_data_path_params p) { + bluetooth::hci::iso_manager::iso_data_path_params /*p*/) { log::debug("SetupIsoDataPath"); ASSERT_NE(conn_handle, kInvalidCisConnHandle); @@ -434,7 +432,7 @@ protected: }); ON_CALL(*mock_iso_manager_, RemoveIsoDataPath) - .WillByDefault([this](uint16_t conn_handle, uint8_t iso_direction) { + .WillByDefault([this](uint16_t conn_handle, uint8_t /*iso_direction*/) { log::debug("RemoveIsoDataPath"); ASSERT_NE(conn_handle, kInvalidCisConnHandle); @@ -1204,7 +1202,7 @@ protected: ON_CALL(ase_ctp_handler, AseCtpConfigureCodecHandler) .WillByDefault(Invoke([group, verify_ase_count, caching, inject_configured, this]( LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { auto num_ase = value[1]; // Verify ase count if needed @@ -1275,7 +1273,7 @@ protected: ON_CALL(ase_ctp_handler, AseCtpConfigureQosHandler) .WillByDefault(Invoke([group, verify_ase_count, caching, inject_qos_configured, this]( LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { auto num_ase = value[1]; // Verify ase count if needed @@ -1347,7 +1345,7 @@ protected: uint8_t reason) { auto foo = [group, opcode, response_code, reason](LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { auto num_ase = value[1]; std::vector notif_value(2 + num_ase * sizeof(struct client_parser::ascs::ctp_ase_entry)); @@ -1417,7 +1415,7 @@ protected: ON_CALL(ase_ctp_handler, AseCtpEnableHandler) .WillByDefault(Invoke([group, verify_ase_count, inject_enabling, incject_streaming, this](LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { auto num_ase = value[1]; // Verify ase count if needed @@ -1469,7 +1467,7 @@ protected: ON_CALL(ase_ctp_handler, AseCtpDisableHandler) .WillByDefault(Invoke([group, verify_ase_count, this]( LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { auto num_ase = value[1]; // Verify ase count if needed @@ -1512,7 +1510,7 @@ protected: ON_CALL(ase_ctp_handler, AseCtpReceiverStartReadyHandler) .WillByDefault(Invoke([group, verify_ase_count, this]( LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { auto num_ase = value[1]; // Verify ase count if needed @@ -1544,7 +1542,7 @@ protected: ON_CALL(ase_ctp_handler, AseCtpReceiverStopReadyHandler) .WillByDefault(Invoke([group, verify_ase_count, this]( LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { auto num_ase = value[1]; // Verify ase count if needed @@ -1577,7 +1575,7 @@ protected: ON_CALL(ase_ctp_handler, AseCtpReleaseHandler) .WillByDefault(Invoke([group, verify_ase_count, inject_disconnect_device, dev, this]( LeAudioDevice* device, std::vector value, - GATT_WRITE_OP_CB cb, void* cb_data) { + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { if (dev != nullptr && device != dev) { log::info("Do nothing for {}", dev->address_); return; diff --git a/system/bta/ras/ras_client.cc b/system/bta/ras/ras_client.cc index b007c71ff43..8d5cd3b4739 100644 --- a/system/bta/ras/ras_client.cc +++ b/system/bta/ras/ras_client.cc @@ -431,7 +431,7 @@ public: } void GattWriteCallbackForVendorSpecificData(tCONN_ID conn_id, tGATT_STATUS status, - uint16_t handle, const uint8_t* value, + uint16_t handle, const uint8_t* /*value*/, GattWriteCallbackData* data) { if (data != nullptr) { GattWriteCallbackData* structPtr = static_cast(data); @@ -466,7 +466,7 @@ public: } void GattWriteCallback(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - const uint8_t* value) { + const uint8_t* /*value*/) { if (status != GATT_SUCCESS) { log::error("Fail to write conn_id {}, status {}, handle {}", conn_id, gatt_status_text(status), handle); @@ -490,7 +490,7 @@ public: } static void GattWriteCallback(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) { + uint16_t /*len*/, const uint8_t* value, void* data) { if (instance != nullptr) { if (data != nullptr) { GattWriteCallbackData* structPtr = static_cast(data); @@ -542,8 +542,8 @@ public: nullptr); } - void OnDescriptorWrite(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) { + void OnDescriptorWrite(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* /*data*/) { log::info("conn_id:{}, handle:{}, status:{}", conn_id, handle, gatt_status_text(status)); } diff --git a/system/bta/test/bta_ag_sco_test.cc b/system/bta/test/bta_ag_sco_test.cc index 16da3830214..bbd5bd24302 100644 --- a/system/bta/test/bta_ag_sco_test.cc +++ b/system/bta/test/bta_ag_sco_test.cc @@ -30,7 +30,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -bool btm_peer_supports_esco_ev3(const RawAddress& remote_bda) { return true; } +bool btm_peer_supports_esco_ev3(const RawAddress& /*remote_bda*/) { return true; } tBTM_CB btm_cb; LeAudioClient* LeAudioClient::Get() { return nullptr; } bool LeAudioClient::IsLeAudioClientInStreaming() { return false; } diff --git a/system/bta/test/bta_ag_test.cc b/system/bta/test/bta_ag_test.cc index 45549aeb9b3..f7b6d4d21ee 100644 --- a/system/bta/test/bta_ag_test.cc +++ b/system/bta/test/bta_ag_test.cc @@ -46,7 +46,7 @@ using namespace bluetooth; namespace { -bool bta_ag_hdl_event(const BT_HDR_RIGID* p_msg) { return true; } +bool bta_ag_hdl_event(const BT_HDR_RIGID* /*p_msg*/) { return true; } void BTA_AgDisable() { bta_sys_deregister(BTA_ID_AG); } const tBTA_SYS_REG bta_ag_reg = {bta_ag_hdl_event, BTA_AgDisable}; @@ -72,7 +72,7 @@ protected: bta_sys_register(BTA_ID_AG, &bta_ag_reg); - bta_ag_cb.p_cback = [](tBTA_AG_EVT event, tBTA_AG* p_data) {}; + bta_ag_cb.p_cback = [](tBTA_AG_EVT /*event*/, tBTA_AG* /*p_data*/) {}; RawAddress::FromString("00:11:22:33:44:55", addr); test::mock::device_esco_parameters::esco_parameters_for_codec.body = [this](esco_codec_t codec) { @@ -145,7 +145,7 @@ TEST_F(BtaAgActTest, set_codec_q0_success) { tBTA_AG_SCB* p_scb = &bta_ag_cb.scb[0]; const tBTA_AG_DATA data = {.api_setcodec.codec = BTA_AG_SCO_APTX_SWB_SETTINGS_Q0}; - bta_ag_cb.p_cback = [](tBTA_AG_EVT event, tBTA_AG* p_data) { + bta_ag_cb.p_cback = [](tBTA_AG_EVT /*event*/, tBTA_AG* p_data) { tBTA_AG_VAL* val = (tBTA_AG_VAL*)p_data; ASSERT_EQ(val->num, BTA_AG_SCO_APTX_SWB_SETTINGS_Q0); ASSERT_EQ(val->hdr.status, BTA_AG_SUCCESS); @@ -165,7 +165,7 @@ TEST_F(BtaAgActTest, set_codec_q1_fail_unsupported) { ASSERT_TRUE(enable_aptx_voice_property(true)); - bta_ag_cb.p_cback = [](tBTA_AG_EVT event, tBTA_AG* p_data) { + bta_ag_cb.p_cback = [](tBTA_AG_EVT /*event*/, tBTA_AG* p_data) { tBTA_AG_VAL* val = (tBTA_AG_VAL*)p_data; ASSERT_EQ(val->num, BTA_AG_SCO_APTX_SWB_SETTINGS_Q1); ASSERT_EQ(val->hdr.status, BTA_AG_FAIL_RESOURCES); @@ -280,7 +280,8 @@ TEST_F(BtaAgCmdTest, at_hfp_cback__qcs_ev_codec_q0_enabled) { TEST_F(BtaAgCmdTest, handle_swb_at_event__qcs_ev_codec_q1_fallback_to_q0) { reset_mock_btm_client_interface(); - mock_btm_client_interface.sco.BTM_SetEScoMode = [](enh_esco_params_t* p_params) -> tBTM_STATUS { + mock_btm_client_interface.sco.BTM_SetEScoMode = + [](enh_esco_params_t* /*p_params*/) -> tBTM_STATUS { inc_func_call_count("BTM_SetEScoMode"); return tBTM_STATUS::BTM_SUCCESS; }; @@ -327,7 +328,7 @@ protected: void SetUp() override { BtaAgTest::SetUp(); reset_mock_btm_client_interface(); - mock_btm_client_interface.peer.BTM_ReadRemoteFeatures = [](const RawAddress& addr) { + mock_btm_client_interface.peer.BTM_ReadRemoteFeatures = [](const RawAddress& /*addr*/) { inc_func_call_count("BTM_ReadRemoteFeatures"); return data; }; diff --git a/system/bta/test/bta_av_test.cc b/system/bta/test/bta_av_test.cc index 0775b7c54b9..97bcbca6cb7 100644 --- a/system/bta/test/bta_av_test.cc +++ b/system/bta/test/bta_av_test.cc @@ -36,7 +36,7 @@ const RawAddress kRawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); } // namespace struct alarm_t { - alarm_t(const char* name) {} + alarm_t(const char* /*name*/) {} int any_value; }; diff --git a/system/bta/test/bta_dip_test.cc b/system/bta/test/bta_dip_test.cc index 61ccc5080fa..ab3b620d024 100644 --- a/system/bta/test/bta_dip_test.cc +++ b/system/bta/test/bta_dip_test.cc @@ -42,7 +42,9 @@ static tSDP_DISC_ATTR g_attr_vendor_product_version; static tSDP_DISC_ATTR g_attr_vendor_product_primary_record; static tSDP_DISC_REC g_rec; -static void sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP* p_data, void* user_data) { return; } +static void sdp_dm_cback(tBTA_SDP_EVT /*event*/, tBTA_SDP* /*p_data*/, void* /*user_data*/) { + return; +} class BtaDipTest : public ::testing::Test { protected: diff --git a/system/bta/test/bta_disc_test.cc b/system/bta/test/bta_disc_test.cc index f9db1733f1b..6a9aa3b005b 100644 --- a/system/bta/test/bta_disc_test.cc +++ b/system/bta/test/bta_disc_test.cc @@ -167,7 +167,8 @@ TEST_F(BtaInitializedTest, bta_dm_start_scan) { } TEST_F(BtaInitializedTest, bta_dm_disc_start_device_discovery) { - bta_dm_disc_start_device_discovery([](tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data) {}); + bta_dm_disc_start_device_discovery( + [](tBTA_DM_SEARCH_EVT /*event*/, tBTA_DM_SEARCH* /*p_data*/) {}); } TEST_F(BtaInitializedTest, bta_dm_disc_stop_device_discovery) { @@ -197,7 +198,7 @@ TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_BR_ service_cb_call_cnt = 0; bta_dm_disc_start_service_discovery({nullptr, nullptr, - [](RawAddress addr, const std::vector&, + [](RawAddress /*addr*/, const std::vector&, tBTA_STATUS) { service_cb_call_cnt++; }}, kRawAddress, BT_TRANSPORT_BR_EDR); @@ -246,7 +247,7 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_disabled, std::promise gatt_triggered; int gatt_call_cnt = 0; base::RepeatingCallback gatt_performer = - base::BindLambdaForTesting([&](const RawAddress& bd_addr) { + base::BindLambdaForTesting([&](const RawAddress& /*bd_addr*/) { gatt_call_cnt++; gatt_triggered.set_value(); }); @@ -254,7 +255,7 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_disabled, int sdp_call_cnt = 0; base::RepeatingCallback sdp_performer = - base::BindLambdaForTesting([&](tBTA_DM_SDP_STATE* sdp_state) { sdp_call_cnt++; }); + base::BindLambdaForTesting([&](tBTA_DM_SDP_STATE* /*sdp_state*/) { sdp_call_cnt++; }); bta_dm_disc_override_sdp_performer_for_testing(sdp_performer); gatt_service_cb_both_call_cnt = 0; @@ -262,18 +263,15 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_disabled, bta_dm_disc_start_service_discovery( {[](RawAddress, std::vector&, bool) {}, nullptr, - [](RawAddress addr, const std::vector&, tBTA_STATUS) { + [](RawAddress /*addr*/, const std::vector&, tBTA_STATUS) { service_cb_both_call_cnt++; }}, kRawAddress, BT_TRANSPORT_BR_EDR); EXPECT_EQ(sdp_call_cnt, 1); bta_dm_disc_start_service_discovery( - {[](RawAddress, std::vector&, bool) { - gatt_service_cb_both_call_cnt++; - }, - nullptr, - [](RawAddress addr, const std::vector&, tBTA_STATUS) {}}, + {[](RawAddress, std::vector&, bool) { gatt_service_cb_both_call_cnt++; }, + nullptr, [](RawAddress /*addr*/, const std::vector&, tBTA_STATUS) {}}, kRawAddress, BT_TRANSPORT_LE); // GATT discovery is queued, until SDP finishes @@ -301,31 +299,33 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_enabled, int gatt_call_cnt = 0; base::RepeatingCallback gatt_performer = - base::BindLambdaForTesting([&](const RawAddress& bd_addr) { gatt_call_cnt++; }); + base::BindLambdaForTesting([&](const RawAddress& /*bd_addr*/) { gatt_call_cnt++; }); bta_dm_disc_override_gatt_performer_for_testing(gatt_performer); int sdp_call_cnt = 0; base::RepeatingCallback sdp_performer = - base::BindLambdaForTesting([&](tBTA_DM_SDP_STATE* sdp_state) { sdp_call_cnt++; }); + base::BindLambdaForTesting([&](tBTA_DM_SDP_STATE* /*sdp_state*/) { sdp_call_cnt++; }); bta_dm_disc_override_sdp_performer_for_testing(sdp_performer); gatt_service_cb_both_call_cnt = 0; service_cb_both_call_cnt = 0; - bta_dm_disc_start_service_discovery({[](RawAddress, std::vector&, - bool) { gatt_service_cb_both_call_cnt++; }, - nullptr, - [](RawAddress addr, const std::vector&, - tBTA_STATUS) { service_cb_both_call_cnt++; }}, - kRawAddress, BT_TRANSPORT_BR_EDR); + bta_dm_disc_start_service_discovery( + {[](RawAddress, std::vector&, bool) { gatt_service_cb_both_call_cnt++; }, + nullptr, + [](RawAddress /*addr*/, const std::vector&, tBTA_STATUS) { + service_cb_both_call_cnt++; + }}, + kRawAddress, BT_TRANSPORT_BR_EDR); EXPECT_EQ(sdp_call_cnt, 1); - bta_dm_disc_start_service_discovery({[](RawAddress, std::vector&, - bool) { gatt_service_cb_both_call_cnt++; }, - nullptr, - [](RawAddress addr, const std::vector&, - tBTA_STATUS) { service_cb_both_call_cnt++; }}, - kRawAddress, BT_TRANSPORT_LE); + bta_dm_disc_start_service_discovery( + {[](RawAddress, std::vector&, bool) { gatt_service_cb_both_call_cnt++; }, + nullptr, + [](RawAddress /*addr*/, const std::vector&, tBTA_STATUS) { + service_cb_both_call_cnt++; + }}, + kRawAddress, BT_TRANSPORT_LE); // GATT discovery on same device is immediately started EXPECT_EQ(gatt_call_cnt, 1); diff --git a/system/bta/test/bta_dm_test.cc b/system/bta/test/bta_dm_test.cc index b9a75340c3a..4f91d74e299 100644 --- a/system/bta/test/bta_dm_test.cc +++ b/system/bta/test/bta_dm_test.cc @@ -97,12 +97,12 @@ class BtaDmCustomAlarmTest : public BtaDmTest { protected: void SetUp() override { BtaDmTest::SetUp(); - test::mock::osi_alarm::alarm_set_on_mloop.body = [this](alarm_t* alarm, uint64_t interval_ms, - alarm_callback_t cb, void* data) { - ASSERT_TRUE(alarm != nullptr); - this->alarm_callback = cb; - this->alarm_data = data; - }; + test::mock::osi_alarm::alarm_set_on_mloop.body = + [this](alarm_t* alarm, uint64_t /*interval_ms*/, alarm_callback_t cb, void* data) { + ASSERT_TRUE(alarm != nullptr); + this->alarm_callback = cb; + this->alarm_data = data; + }; } void TearDown() override { test::mock::osi_alarm::alarm_set_on_mloop = {}; @@ -238,8 +238,9 @@ TEST_F(BtaDmTest, bta_dm_set_encryption) { // Setup a device that fails encryption mock_btm_client_interface.security.BTM_SetEncryption = - [](const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK* p_callback, - void* p_ref_data, tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { + [](const RawAddress& /*bd_addr*/, tBT_TRANSPORT /*transport*/, + tBTM_SEC_CALLBACK* /*p_callback*/, void* /*p_ref_data*/, + tBTM_BLE_SEC_ACT /*sec_act*/) -> tBTM_STATUS { inc_func_call_count("BTM_SetEncryption"); return tBTM_STATUS::BTM_MODE_UNSUPPORTED; }; @@ -251,8 +252,9 @@ TEST_F(BtaDmTest, bta_dm_set_encryption) { // Setup a device that successfully starts encryption mock_btm_client_interface.security.BTM_SetEncryption = - [](const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK* p_callback, - void* p_ref_data, tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { + [](const RawAddress& /*bd_addr*/, tBT_TRANSPORT /*transport*/, + tBTM_SEC_CALLBACK* /*p_callback*/, void* /*p_ref_data*/, + tBTM_BLE_SEC_ACT /*sec_act*/) -> tBTM_STATUS { inc_func_call_count("BTM_SetEncryption"); return tBTM_STATUS::BTM_CMD_STARTED; }; @@ -374,7 +376,7 @@ TEST_F(BtaDmTest, bta_dm_remname_cback__HCI_ERR_CONNECTION_EXISTS) { TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BR_EDR) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); - mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& remote_bda, + mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& /*remote_bda*/, tBT_DEVICE_TYPE* p_dev_type, tBLE_ADDR_TYPE* p_addr_type) { *p_dev_type = BT_DEVICE_TYPE_BREDR; @@ -388,7 +390,7 @@ TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BR_EDR) { TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BLE__PUBLIC) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); - mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& remote_bda, + mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& /*remote_bda*/, tBT_DEVICE_TYPE* p_dev_type, tBLE_ADDR_TYPE* p_addr_type) { *p_dev_type = BT_DEVICE_TYPE_BLE; @@ -402,7 +404,7 @@ TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BLE__PUBLIC) { TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__DUMO) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); - mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& remote_bda, + mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& /*remote_bda*/, tBT_DEVICE_TYPE* p_dev_type, tBLE_ADDR_TYPE* p_addr_type) { *p_dev_type = BT_DEVICE_TYPE_DUMO; @@ -432,7 +434,7 @@ TEST_F(BtaDmTest, bta_dm_search_evt_text) { TEST_F(BtaDmTest, bta_dm_remote_name_cmpl) { reset_mock_btm_client_interface(); - mock_btm_client_interface.db.BTM_InqDbRead = [](const RawAddress& bd_addr) -> tBTM_INQ_INFO* { + mock_btm_client_interface.db.BTM_InqDbRead = [](const RawAddress& /*bd_addr*/) -> tBTM_INQ_INFO* { inc_func_call_count("BTM_InqDbRead"); return nullptr; }; @@ -473,7 +475,7 @@ TEST_F(BtaDmCustomAlarmTest, bta_dm_sniff_cback) { TEST_F(BtaDmCustomAlarmTest, sniff_offload_feature__test_sysprop) { bool is_property_enabled = true; test::mock::osi_properties::osi_property_get_bool.body = - [&](const char* key, bool default_value) -> int { return is_property_enabled; }; + [&](const char* /*key*/, bool /*default_value*/) -> int { return is_property_enabled; }; // Expect not to trigger bta_dm_init_pm due to sysprop enabled // and reset the value of .srvc_id. diff --git a/system/bta/test/bta_sec_test.cc b/system/bta/test/bta_sec_test.cc index 0db6800c296..bee18526284 100644 --- a/system/bta/test/bta_sec_test.cc +++ b/system/bta/test/bta_sec_test.cc @@ -70,7 +70,7 @@ TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithName) { static bool callback_sent = false; static tBTA_DM_SP_CFM_REQ cfm_req{}; - bta_dm_sec_enable([](tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) { + bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) { callback_sent = true; cfm_req = p_data->cfm_req; }); @@ -119,7 +119,7 @@ TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRSuccess) { .WillOnce(Return(tBTM_STATUS::BTM_CMD_STARTED)); static tBTA_DM_SP_CFM_REQ cfm_req{}; - bta_dm_sec_enable([](tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) { + bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) { callback_sent = true; cfm_req = p_data->cfm_req; }); @@ -156,7 +156,7 @@ TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRFail) { .WillOnce(Return(tBTM_STATUS::BTM_SUCCESS)); static tBTA_DM_SP_CFM_REQ cfm_req{}; - bta_dm_sec_enable([](tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) { + bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) { callback_sent = true; cfm_req = p_data->cfm_req; }); @@ -202,7 +202,7 @@ TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_KEY_NOTIF_EVT) { .WillByDefault(Return(tBTM_STATUS::BTM_CMD_STARTED)); static tBTA_DM_SP_KEY_NOTIF key_notif{}; - bta_dm_sec_enable([](tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) { + bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) { callback_sent = true; key_notif = p_data->key_notif; }); diff --git a/system/bta/test/bta_test_fixtures.h b/system/bta/test/bta_test_fixtures.h index 47ca24b8db5..373b8461224 100644 --- a/system/bta/test/bta_test_fixtures.h +++ b/system/bta/test/bta_test_fixtures.h @@ -67,17 +67,18 @@ protected: bluetooth::testing::stack::rnr::set_interface(&mock_stack_rnr_interface_); test::mock::stack_gatt_api::GATT_Register.body = - [](const bluetooth::Uuid& p_app_uuid128, const std::string name, tGATT_CBACK* p_cb_info, - bool eatt_support) -> tGATT_IF { return kGattRegisteredIf; }; + [](const bluetooth::Uuid& /*p_app_uuid128*/, const std::string /*name*/, + tGATT_CBACK* /*p_cb_info*/, + bool /*eatt_support*/) -> tGATT_IF { return kGattRegisteredIf; }; mock_btm_client_interface.eir.BTM_GetEirSupportedServices = - [](uint32_t* p_eir_uuid, uint8_t** p, uint8_t max_num_uuid16, - uint8_t* p_num_uuid16) -> uint8_t { return 0; }; + [](uint32_t* /*p_eir_uuid*/, uint8_t** /*p*/, uint8_t /*max_num_uuid16*/, + uint8_t* /*p_num_uuid16*/) -> uint8_t { return 0; }; mock_btm_client_interface.eir.BTM_WriteEIR = [](BT_HDR* p_buf) -> tBTM_STATUS { osi_free(p_buf); return tBTM_STATUS::BTM_SUCCESS; }; mock_btm_client_interface.security.BTM_SecRegister = - [](const tBTM_APPL_INFO* p_cb_info) -> bool { return true; }; + [](const tBTM_APPL_INFO* /*p_cb_info*/) -> bool { return true; }; } void TearDown() override { diff --git a/system/bta/test/common/btm_api_mock.cc b/system/bta/test/common/btm_api_mock.cc index 6c2f30797e5..b7208803a3d 100644 --- a/system/bta/test/common/btm_api_mock.cc +++ b/system/bta/test/common/btm_api_mock.cc @@ -86,7 +86,7 @@ tBTM_SEC_DEV_REC* btm_find_dev(const RawAddress& bd_addr) { return btm_interface->FindDevice(bd_addr); } -void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason, std::string comment) { +void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason, std::string /*comment*/) { log::assert_that(btm_interface != nullptr, "Mock btm interface not set!"); return btm_interface->AclDisconnectFromHandle(handle, reason); } diff --git a/system/bta/vc/device.cc b/system/bta/vc/device.cc index a022bf2d302..ec2088981e0 100644 --- a/system/bta/vc/device.cc +++ b/system/bta/vc/device.cc @@ -399,9 +399,10 @@ bool VolumeControlDevice::EnqueueInitialRequests(tGATT_IF gatt_if, GATT_READ_OP_ * This includes characteristics read and subscription. * In each case we subscribe first to be sure we do not miss any value change. */ -void VolumeControlDevice::EnqueueRemainingRequests(tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, +void VolumeControlDevice::EnqueueRemainingRequests(tGATT_IF /*gatt_if*/, + GATT_READ_OP_CB chrc_read_cb, GATT_READ_MULTI_OP_CB chrc_multi_read_cb, - GATT_WRITE_OP_CB cccd_write_cb) { + GATT_WRITE_OP_CB /*cccd_write_cb*/) { std::vector handles_to_read; for (auto const& input : audio_inputs.volume_audio_inputs) { diff --git a/system/bta/vc/devices_test.cc b/system/bta/vc/devices_test.cc index 8d951ea7fb5..d2f389a8641 100644 --- a/system/bta/vc/devices_test.cc +++ b/system/bta/vc/devices_test.cc @@ -229,8 +229,8 @@ protected: bluetooth::manager::SetMockBtmInterface(&btm_interface); ON_CALL(gatt_interface, GetCharacteristic(_, _)) - .WillByDefault( - Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Characteristic* { + .WillByDefault(Invoke( + [&](uint16_t /*conn_id*/, uint16_t handle) -> const gatt::Characteristic* { for (auto const& service : services) { for (auto const& characteristic : service.characteristics) { if (characteristic.value_handle == handle) { @@ -243,15 +243,16 @@ protected: })); ON_CALL(gatt_interface, GetOwningService(_, _)) - .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* { - for (auto const& service : services) { - if (service.handle <= handle && service.end_handle >= handle) { - return &service; - } - } + .WillByDefault( + Invoke([&](uint16_t /*conn_id*/, uint16_t handle) -> const gatt::Service* { + for (auto const& service : services) { + if (service.handle <= handle && service.end_handle >= handle) { + return &service; + } + } - return nullptr; - })); + return nullptr; + })); ON_CALL(gatt_interface, GetServices(_)).WillByDefault(Return(&services)); @@ -600,10 +601,10 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) { EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first)); } - auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; - auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) {}; + auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; + auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; ASSERT_EQ(true, device->EnqueueInitialRequests(gatt_if, chrc_read_cb, cccd_write_cb)); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); @@ -615,21 +616,22 @@ TEST_F(VolumeControlDeviceTest, test_device_ready) { // grab all the handles requested std::vector requested_handles; ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _)) - .WillByDefault( - Invoke([&requested_handles]( - uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, - void* cb_data) -> void { requested_handles.push_back(handle); })); + .WillByDefault(Invoke( + [&requested_handles]( + uint16_t /*conn_id*/, uint16_t handle, std::vector /*value*/, + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB /*cb*/, + void* /*cb_data*/) -> void { requested_handles.push_back(handle); })); ON_CALL(gatt_queue, ReadCharacteristic(_, _, _, _)) - .WillByDefault(Invoke([&requested_handles](uint16_t conn_id, uint16_t handle, - GATT_READ_OP_CB cb, void* cb_data) -> void { - requested_handles.push_back(handle); - })); - - auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; - auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) {}; + .WillByDefault( + Invoke([&requested_handles](uint16_t /*conn_id*/, uint16_t handle, + GATT_READ_OP_CB /*cb*/, void* /*cb_data*/) -> void { + requested_handles.push_back(handle); + })); + + auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; + auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; ASSERT_EQ(true, device->EnqueueInitialRequests(0x0001, chrc_read_cb, cccd_write_cb)); ASSERT_NE((size_t)0, requested_handles.size()); @@ -669,12 +671,13 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests) { EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0); EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0); - auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; - auto chrc_multi_read_cb = [](uint16_t conn_id, tGATT_STATUS status, tBTA_GATTC_MULTI& handles, - uint16_t len, uint8_t* value, void* data) {}; - auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) {}; + auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; + auto chrc_multi_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, + tBTA_GATTC_MULTI& /*handles*/, uint16_t /*len*/, uint8_t* /*value*/, + void* /*data*/) {}; + auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb); Mock::VerifyAndClearExpectations(&gatt_queue); Mock::VerifyAndClearExpectations(&gatt_interface); @@ -719,12 +722,13 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests_multiread) { EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0); EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0); - auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; - auto chrc_multi_read_cb = [](uint16_t conn_id, tGATT_STATUS status, tBTA_GATTC_MULTI& handles, - uint16_t len, uint8_t* value, void* data) {}; - auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) {}; + auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; + auto chrc_multi_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, + tBTA_GATTC_MULTI& /*handles*/, uint16_t /*len*/, uint8_t* /*value*/, + void* /*data*/) {}; + auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb); @@ -744,8 +748,8 @@ TEST_F(VolumeControlDeviceTest, test_check_link_encrypted) { } TEST_F(VolumeControlDeviceTest, test_control_point_operation) { - GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) {}; + GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); device->change_counter = 0x01; std::vector expected_data({0x03, 0x01}); @@ -755,8 +759,8 @@ TEST_F(VolumeControlDeviceTest, test_control_point_operation) { } TEST_F(VolumeControlDeviceTest, test_control_point_operation_arg) { - GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) {}; + GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); device->change_counter = 0x55; std::vector expected_data({0x01, 0x55, 0x02, 0x03}); @@ -767,16 +771,16 @@ TEST_F(VolumeControlDeviceTest, test_control_point_operation_arg) { } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_volume_offset) { - GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; + GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0062, read_cb, nullptr)); device->GetExtAudioOutVolumeOffset(1, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_location) { - GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; + GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0085, read_cb, nullptr)); device->GetExtAudioOutLocation(2, read_cb, nullptr); @@ -797,8 +801,8 @@ TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_location_non_writable) { } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_description) { - GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; + GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x008a, read_cb, nullptr)); device->GetExtAudioOutDescription(2, read_cb, nullptr); @@ -821,8 +825,8 @@ TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_description_non_writable) } TEST_F(VolumeControlDeviceTest, test_ext_audio_out_control_point_operation) { - GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) {}; + GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); VolumeOffset* offset = device->audio_offsets.FindById(1); ASSERT_NE(nullptr, offset); @@ -834,8 +838,8 @@ TEST_F(VolumeControlDeviceTest, test_ext_audio_out_control_point_operation) { } TEST_F(VolumeControlDeviceTest, test_ext_audio_out_control_point_operation_arg) { - GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) {}; + GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); VolumeOffset* offset = device->audio_offsets.FindById(1); ASSERT_NE(nullptr, offset); @@ -848,32 +852,32 @@ TEST_F(VolumeControlDeviceTest, test_ext_audio_out_control_point_operation_arg) } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_state) { - GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; + GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0022, read_cb, nullptr)); device->GetExtAudioInState(1, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_status) { - GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; + GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0049, read_cb, nullptr)); device->GetExtAudioInStatus(2, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_gain_props) { - GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; + GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0025, read_cb, nullptr)); device->GetExtAudioInGainProps(1, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_description) { - GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - uint8_t* value, void* data) {}; + GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x002e, read_cb, nullptr)); device->GetExtAudioInDescription(1, read_cb, nullptr); @@ -897,8 +901,8 @@ TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description_non_writable) } TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation) { - GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) {}; + GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); VolumeAudioInput* input = device->audio_inputs.FindById(2); ASSERT_NE(nullptr, input); @@ -910,8 +914,8 @@ TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation) { } TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation_arg) { - GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, const uint8_t* value, void* data) {}; + GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); VolumeAudioInput* input = device->audio_inputs.FindById(2); ASSERT_NE(nullptr, input); diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index c00fa87293a..6a449c74c35 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -311,7 +311,7 @@ public: } void OnCharacteristicValueChanged(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, - uint16_t len, uint8_t* value, void* data, + uint16_t len, uint8_t* value, void* /*data*/, bool is_notification) { VolumeControlDevice* device = volume_control_devices_.FindByConnId(conn_id); if (!device) { @@ -522,7 +522,7 @@ public: StartQueueOperation(); } - void OnVolumeControlFlagsChanged(VolumeControlDevice* device, uint16_t len, uint8_t* value) { + void OnVolumeControlFlagsChanged(VolumeControlDevice* device, uint16_t /*len*/, uint8_t* value) { device->flags = *value; bluetooth::log::info("{}, flags {:#x}", device->address, device->flags); @@ -740,8 +740,8 @@ public: callbacks_->OnExtAudioOutDescriptionChanged(device->address, offset->id, offset->description); } - void OnGattWriteCcc(tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* /*data*/) { + void OnGattWriteCcc(tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, + uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) { VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id); if (!device) { bluetooth::log::error("unknown connection_id={:#x}", connection_id); @@ -1364,8 +1364,8 @@ private: const std::vector* arg, int operation_id = -1) { volume_control_devices_.ControlPointOperation( devices, opcode, arg, - [](tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) { + [](tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* data) { if (instance) { instance->OnWriteControlResponse(connection_id, status, handle, data); } @@ -1385,8 +1385,8 @@ private: device->ExtAudioInControlPointOperation( ext_input_id, opcode, arg, - [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) { + [](uint16_t connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* /*data*/) { if (instance) { instance->OnExtAudioInCPWrite(connection_id, status, handle); } @@ -1404,8 +1404,8 @@ private: } device->ExtAudioOutControlPointOperation( ext_output_id, opcode, arg, - [](tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, uint16_t len, - const uint8_t* value, void* data) { + [](tCONN_ID connection_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, + const uint8_t* /*value*/, void* data) { if (instance) { instance->OnExtAudioOutCPWrite(connection_id, status, handle, data); } diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index af4ae2bb27d..b0f203bc824 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -40,7 +40,7 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -void btif_storage_add_volume_control(const RawAddress& addr, bool auto_conn) {} +void btif_storage_add_volume_control(const RawAddress& /*addr*/, bool /*auto_conn*/) {} struct alarm_t { alarm_callback_t cb = nullptr; @@ -485,14 +485,14 @@ protected: // default action for WriteDescriptor function call ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _)) .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, + 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); } })); auto mock_alarm = AlarmMock::Get(); - ON_CALL(*mock_alarm, AlarmNew(_)).WillByDefault(Invoke([](const char* name) { + ON_CALL(*mock_alarm, AlarmNew(_)).WillByDefault(Invoke([](const char* /*name*/) { return new alarm_t(); })); ON_CALL(*mock_alarm, AlarmFree(_)).WillByDefault(Invoke([](alarm_t* alarm) { @@ -515,7 +515,7 @@ protected: })); ON_CALL(*mock_alarm, AlarmSet(_, _, _, _)) .WillByDefault(Invoke( - [](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) { + [](alarm_t* alarm, uint64_t /*interval_ms*/, alarm_callback_t cb, void* data) { if (alarm) { alarm->data = data; alarm->cb = cb; @@ -523,7 +523,7 @@ protected: })); ON_CALL(*mock_alarm, AlarmSetOnMloop(_, _, _, _)) .WillByDefault(Invoke( - [](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) { + [](alarm_t* alarm, uint64_t /*interval_ms*/, alarm_callback_t cb, void* data) { if (alarm) { alarm->on_main_loop = true; alarm->data = data; @@ -694,7 +694,7 @@ protected: .WillByDefault( Invoke([&success, this](const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK* p_callback, void* p_ref_data, - tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { + tBTM_BLE_SEC_ACT /*sec_act*/) -> tBTM_STATUS { if (p_callback) { p_callback(bd_addr, transport, p_ref_data, success ? tBTM_STATUS::BTM_SUCCESS @@ -1264,19 +1264,19 @@ TEST_F(VolumeControlTest, test_read_vcs_database_out_of_sync) { /* Simulate database change on the remote side. */ ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) - .WillByDefault( - Invoke([this](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { - auto* svc = gatt::FindService(services_map[conn_id], handle); - if (svc == nullptr) { - return; - } - - tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC; - if (cb) { - cb(conn_id, status, handle, value.size(), value.data(), cb_data); - } - })); + .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle, + std::vector value, tGATT_WRITE_TYPE /*write_type*/, + GATT_WRITE_OP_CB cb, void* cb_data) { + auto* svc = gatt::FindService(services_map[conn_id], handle); + if (svc == nullptr) { + return; + } + + tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC; + if (cb) { + cb(conn_id, status, handle, value.size(), value.data(), cb_data); + } + })); ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return()); EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _)); @@ -1527,8 +1527,9 @@ protected: GetSearchCompleteEvent(conn_id); ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _)) - .WillByDefault([this](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { + .WillByDefault([this](uint16_t conn_id, uint16_t /*handle*/, std::vector value, + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, + void* cb_data) { uint8_t write_rsp; std::vector ntf_value({value[0], 0, static_cast(value[1] + 1)}); @@ -1581,19 +1582,19 @@ TEST_F(VolumeControlValueSetTest, test_volume_operation_failed) { const std::vector vol_x10({0x04, 0x00, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10, GATT_WRITE, _, _)).Times(1); ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) - .WillByDefault( - Invoke([this](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { - auto* svc = gatt::FindService(services_map[conn_id], handle); - if (svc == nullptr) { - return; - } - - tGATT_STATUS status = GATT_ERROR; - if (cb) { - cb(conn_id, status, handle, value.size(), value.data(), cb_data); - } - })); + .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle, + std::vector value, tGATT_WRITE_TYPE /*write_type*/, + GATT_WRITE_OP_CB cb, void* cb_data) { + auto* svc = gatt::FindService(services_map[conn_id], handle); + if (svc == nullptr) { + return; + } + + tGATT_STATUS status = GATT_ERROR; + if (cb) { + cb(conn_id, status, handle, value.size(), value.data(), cb_data); + } + })); EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1); EXPECT_CALL(*AlarmMock::Get(), AlarmCancel(_)).Times(1); @@ -1607,24 +1608,24 @@ TEST_F(VolumeControlValueSetTest, test_volume_operation_failed_due_to_device_dis const std::vector vol_x10({0x04, 0x00, 0x10}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10, GATT_WRITE, _, _)).Times(1); ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)) - .WillByDefault( - Invoke([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { - /* Do nothing */ - })); + .WillByDefault(Invoke([](uint16_t /*conn_id*/, uint16_t /*handle*/, + std::vector /*value*/, tGATT_WRITE_TYPE /*write_type*/, + GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) { + /* Do nothing */ + })); EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(0); alarm_callback_t active_alarm_cb = nullptr; EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)) - .WillOnce(Invoke( - [&](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) { - if (alarm) { - alarm->on_main_loop = true; - alarm->cb = cb; - active_alarm_cb = cb; - } - })); + .WillOnce(Invoke([&](alarm_t* alarm, uint64_t /*interval_ms*/, alarm_callback_t cb, + void* /*data*/) { + if (alarm) { + alarm->on_main_loop = true; + alarm->cb = cb; + active_alarm_cb = cb; + } + })); ON_CALL(*AlarmMock::Get(), AlarmCancel(_)).WillByDefault(Invoke([&](alarm_t* alarm) { if (alarm) { alarm->cb = nullptr; @@ -1687,7 +1688,7 @@ TEST_F(VolumeControlValueSetTest, test_set_volume_stress_2) { // queued ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _)) .WillByDefault([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, void* cb_data) { uint8_t write_rsp; switch (value[0]) { @@ -1734,7 +1735,7 @@ TEST_F(VolumeControlValueSetTest, test_set_volume_stress_3) { */ ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _)) .WillByDefault([](uint16_t conn_id, uint16_t handle, std::vector value, - tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb, void* cb_data) { + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, void* cb_data) { uint8_t write_rsp; switch (value[0]) { -- GitLab From 1e4b6842e8065278a9055216734b0159911cad9d Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 8 Oct 2024 16:26:58 +0000 Subject: [PATCH 206/875] system/stack/test/fuzzers: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I754d1bc2f0ddfb476b1a32b5964245458385a64f --- system/stack/test/fuzzers/a2dp/Android.bp | 1 - .../stack/test/fuzzers/a2dp/a2dpFuzzHelpers.h | 3 +- .../stack/test/fuzzers/a2dp/codec/Android.bp | 3 -- .../a2dp/codec/a2dpCodecInfoFuzzFunctions.h | 46 +++++++++++-------- system/stack/test/fuzzers/sdp/Android.bp | 1 - .../stack/test/fuzzers/sdp/sdpFuzzFunctions.h | 2 +- .../stack/test/fuzzers/sdp/sdpFuzzHelpers.h | 5 +- 7 files changed, 33 insertions(+), 28 deletions(-) diff --git a/system/stack/test/fuzzers/a2dp/Android.bp b/system/stack/test/fuzzers/a2dp/Android.bp index debbf061b0f..65b56b4895e 100644 --- a/system/stack/test/fuzzers/a2dp/Android.bp +++ b/system/stack/test/fuzzers/a2dp/Android.bp @@ -14,5 +14,4 @@ cc_fuzz { srcs: [ "fuzz_a2dp.cc", ], - cflags: ["-Wno-unused-parameter"], } diff --git a/system/stack/test/fuzzers/a2dp/a2dpFuzzHelpers.h b/system/stack/test/fuzzers/a2dp/a2dpFuzzHelpers.h index 0580e2070c5..d17606a0377 100644 --- a/system/stack/test/fuzzers/a2dp/a2dpFuzzHelpers.h +++ b/system/stack/test/fuzzers/a2dp/a2dpFuzzHelpers.h @@ -44,7 +44,8 @@ tA2DP_SDP_DB_PARAMS generateDBParams(FuzzedDataProvider* fdp, std::vector> a2dp_codec_info_operations = { // A2DP_InitDefaultCodec - [](FuzzedDataProvider* fdp, uint8_t*) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t*) -> void { // Allocate space for a new codec & add it to our tracking vector uint8_t* codec_info = new uint8_t[AVDT_CODEC_SIZE]; a2dp_codec_info_vect.push_back(codec_info); @@ -58,25 +58,27 @@ std::vector> a2dp_codec_info_ }, // A2DP_GetCodecType - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { A2DP_GetCodecType(codec_info); }, + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { + A2DP_GetCodecType(codec_info); + }, // A2DP_IsSourceCodecValid - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_IsSourceCodecValid(codec_info); }, // A2DP_IsPeerSourceCodecValid - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_IsPeerSourceCodecValid(codec_info); }, // A2DP_IsPeerSinkCodecValid - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_IsPeerSinkCodecValid(codec_info); }, // A2DP_IsSinkCodecSupported - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_IsSinkCodecSupported(codec_info); }, @@ -86,10 +88,14 @@ std::vector> a2dp_codec_info_ }, // A2DP_GetMediaType - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { A2DP_GetMediaType(codec_info); }, + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { + A2DP_GetMediaType(codec_info); + }, // A2DP_CodecName - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { A2DP_CodecName(codec_info); }, + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { + A2DP_CodecName(codec_info); + }, // A2DP_CodecTypeEquals [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { @@ -108,22 +114,22 @@ std::vector> a2dp_codec_info_ }, // A2DP_GetTrackSampleRate - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_GetTrackSampleRate(codec_info); }, // A2DP_GetTrackBitsPerSample - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_GetTrackBitsPerSample(codec_info); }, // A2DP_GetTrackChannelCount - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_GetTrackChannelCount(codec_info); }, // A2DP_GetSinkTrackChannelType - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_GetSinkTrackChannelType(codec_info); }, @@ -152,25 +158,27 @@ std::vector> a2dp_codec_info_ }, // A2DP_GetEncoderInterface - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_GetEncoderInterface(codec_info); }, // A2DP_GetDecoderInterface - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_GetDecoderInterface(codec_info); }, // A2DP_AdjustCodec - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { A2DP_AdjustCodec(codec_info); }, + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { + A2DP_AdjustCodec(codec_info); + }, // A2DP_SourceCodecIndex - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_SourceCodecIndex(codec_info); }, // A2DP_SinkCodecIndex - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_SinkCodecIndex(codec_info); }, @@ -186,12 +194,12 @@ std::vector> a2dp_codec_info_ }, // A2DP_GetEecoderEffectiveFrameSize - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_GetEecoderEffectiveFrameSize(codec_info); }, // A2DP_CodecInfoString - [](FuzzedDataProvider* fdp, uint8_t* codec_info) -> void { + [](FuzzedDataProvider* /*fdp*/, uint8_t* codec_info) -> void { A2DP_CodecInfoString(codec_info); }}; diff --git a/system/stack/test/fuzzers/sdp/Android.bp b/system/stack/test/fuzzers/sdp/Android.bp index 86a8c11fddc..bc5aaa702b0 100644 --- a/system/stack/test/fuzzers/sdp/Android.bp +++ b/system/stack/test/fuzzers/sdp/Android.bp @@ -14,5 +14,4 @@ cc_fuzz { srcs: [ "fuzz_sdp.cc", ], - cflags: ["-Wno-unused-parameter"], } diff --git a/system/stack/test/fuzzers/sdp/sdpFuzzFunctions.h b/system/stack/test/fuzzers/sdp/sdpFuzzFunctions.h index 411c878fe98..3b39ea06a74 100644 --- a/system/stack/test/fuzzers/sdp/sdpFuzzFunctions.h +++ b/system/stack/test/fuzzers/sdp/sdpFuzzFunctions.h @@ -164,7 +164,7 @@ static const std::vector> sdp_operation }, // ::SDP_CreateRecord - [](FuzzedDataProvider* fdp) -> void { + [](FuzzedDataProvider* /*fdp*/) -> void { uint32_t handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord(); if (handle) { sdp_record_handles.push_back(handle); diff --git a/system/stack/test/fuzzers/sdp/sdpFuzzHelpers.h b/system/stack/test/fuzzers/sdp/sdpFuzzHelpers.h index a22accbf746..2647e3f844b 100644 --- a/system/stack/test/fuzzers/sdp/sdpFuzzHelpers.h +++ b/system/stack/test/fuzzers/sdp/sdpFuzzHelpers.h @@ -265,7 +265,8 @@ SDP_Sequence_Helper generateArbitrarySdpElemSequence(FuzzedDataProvider* fdp) { } // Define our callback functions we'll be using within our functions -void sdp_disc_cmpl_cb(const RawAddress& bd_addr, tSDP_STATUS result) {} -void sdp_disc_cmpl_cb2(std::vector data, const RawAddress& bd_addr, tSDP_STATUS result) {} +void sdp_disc_cmpl_cb(const RawAddress& /*bd_addr*/, tSDP_STATUS /*result*/) {} +void sdp_disc_cmpl_cb2(std::vector /*data*/, const RawAddress& /*bd_addr*/, + tSDP_STATUS /*result*/) {} #endif // FUZZER_SDP_HELPERS_H_ -- GitLab From 7004a39f26929efebf5015909785629ac10865cd Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 8 Oct 2024 16:27:33 +0000 Subject: [PATCH 207/875] system/audio_bluetooth_hw/Android.bp: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: Ib88a5957007d83f179e722672ac891c615f5c2d2 --- system/audio_bluetooth_hw/Android.bp | 1 - .../audio_bluetooth_hw/audio_bluetooth_hw.cc | 28 ++++++++++------- .../audio_bluetooth_hw/device_port_proxy.cc | 2 +- system/audio_bluetooth_hw/device_port_proxy.h | 8 ++--- .../device_port_proxy_hidl.cc | 2 +- system/audio_bluetooth_hw/stream_apis.cc | 30 +++++++++---------- 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/system/audio_bluetooth_hw/Android.bp b/system/audio_bluetooth_hw/Android.bp index 8587c62e9dc..fe53c511a21 100644 --- a/system/audio_bluetooth_hw/Android.bp +++ b/system/audio_bluetooth_hw/Android.bp @@ -50,7 +50,6 @@ cc_library_shared { "libbluetooth_audio_session", "libhidlbase", ], - cflags: ["-Wno-unused-parameter"], visibility: [ "//device/generic/goldfish/audio", ], diff --git a/system/audio_bluetooth_hw/audio_bluetooth_hw.cc b/system/audio_bluetooth_hw/audio_bluetooth_hw.cc index e752814d2a4..15a7ddaf542 100644 --- a/system/audio_bluetooth_hw/audio_bluetooth_hw.cc +++ b/system/audio_bluetooth_hw/audio_bluetooth_hw.cc @@ -51,43 +51,49 @@ static int adev_set_parameters(struct audio_hw_device* dev, const char* kvpairs) return 0; } -static char* adev_get_parameters(const struct audio_hw_device* dev, const char* keys) { +static char* adev_get_parameters(const struct audio_hw_device* /*dev*/, const char* keys) { LOG(VERBOSE) << __func__ << ": keys=[" << keys << "]"; return strdup(""); } -static int adev_init_check(const struct audio_hw_device* dev) { return 0; } +static int adev_init_check(const struct audio_hw_device* /*dev*/) { return 0; } -static int adev_set_voice_volume(struct audio_hw_device* dev, float volume) { +static int adev_set_voice_volume(struct audio_hw_device* /*dev*/, float volume) { LOG(VERBOSE) << __func__ << ": volume=" << volume; return -ENOSYS; } -static int adev_set_master_volume(struct audio_hw_device* dev, float volume) { +static int adev_set_master_volume(struct audio_hw_device* /*dev*/, float volume) { LOG(VERBOSE) << __func__ << ": volume=" << volume; return -ENOSYS; } -static int adev_get_master_volume(struct audio_hw_device* dev, float* volume) { return -ENOSYS; } +static int adev_get_master_volume(struct audio_hw_device* /*dev*/, float* /*volume*/) { + return -ENOSYS; +} -static int adev_set_master_mute(struct audio_hw_device* dev, bool muted) { +static int adev_set_master_mute(struct audio_hw_device* /*dev*/, bool muted) { LOG(VERBOSE) << __func__ << ": mute=" << muted; return -ENOSYS; } -static int adev_get_master_mute(struct audio_hw_device* dev, bool* muted) { return -ENOSYS; } +static int adev_get_master_mute(struct audio_hw_device* /*dev*/, bool* /*muted*/) { + return -ENOSYS; +} -static int adev_set_mode(struct audio_hw_device* dev, audio_mode_t mode) { +static int adev_set_mode(struct audio_hw_device* /*dev*/, audio_mode_t mode) { LOG(VERBOSE) << __func__ << ": mode=" << mode; return 0; } -static int adev_set_mic_mute(struct audio_hw_device* dev, bool state) { +static int adev_set_mic_mute(struct audio_hw_device* /*dev*/, bool state) { LOG(VERBOSE) << __func__ << ": state=" << state; return -ENOSYS; } -static int adev_get_mic_mute(const struct audio_hw_device* dev, bool* state) { return -ENOSYS; } +static int adev_get_mic_mute(const struct audio_hw_device* /*dev*/, bool* /*state*/) { + return -ENOSYS; +} static int adev_create_audio_patch(struct audio_hw_device* device, unsigned int num_sources, const struct audio_port_config* sources, unsigned int num_sinks, @@ -145,7 +151,7 @@ static int adev_get_audio_port(struct audio_hw_device* device, struct audio_port return -ENOSYS; } -static int adev_dump(const audio_hw_device_t* device, int fd) { return 0; } +static int adev_dump(const audio_hw_device_t* /*device*/, int /*fd*/) { return 0; } static int adev_close(hw_device_t* device) { auto* bluetooth_device = reinterpret_cast(device); diff --git a/system/audio_bluetooth_hw/device_port_proxy.cc b/system/audio_bluetooth_hw/device_port_proxy.cc index 8f29654d1c6..13d831f841c 100644 --- a/system/audio_bluetooth_hw/device_port_proxy.cc +++ b/system/audio_bluetooth_hw/device_port_proxy.cc @@ -140,7 +140,7 @@ bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) { state_ = BluetoothStreamState::STANDBY; - auto control_result_cb = [port = this](uint16_t cookie, bool start_resp, + auto control_result_cb = [port = this](uint16_t cookie, bool /*start_resp*/, const BluetoothAudioStatus& status) { if (!port->in_use()) { LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use"; diff --git a/system/audio_bluetooth_hw/device_port_proxy.h b/system/audio_bluetooth_hw/device_port_proxy.h index 1409d334844..8466bdbaa70 100644 --- a/system/audio_bluetooth_hw/device_port_proxy.h +++ b/system/audio_bluetooth_hw/device_port_proxy.h @@ -101,16 +101,16 @@ public: /*** * Set the current BluetoothStreamState ***/ - virtual void SetState(BluetoothStreamState state) {} + virtual void SetState(BluetoothStreamState /*state*/) {} virtual bool IsA2dp() const { return false; } virtual bool IsLeAudio() const { return false; } - virtual bool GetPreferredDataIntervalUs(size_t* interval_us) const { return false; } + virtual bool GetPreferredDataIntervalUs(size_t* /*interval_us*/) const { return false; } - virtual size_t WriteData(const void* buffer, size_t bytes) const { return 0; } - virtual size_t ReadData(void* buffer, size_t bytes) const { return 0; } + virtual size_t WriteData(const void* /*buffer*/, size_t /*bytes*/) const { return 0; } + virtual size_t ReadData(void* /*buffer*/, size_t /*bytes*/) const { return 0; } }; namespace aidl { diff --git a/system/audio_bluetooth_hw/device_port_proxy_hidl.cc b/system/audio_bluetooth_hw/device_port_proxy_hidl.cc index 20bcb43bb98..92242c26ae7 100644 --- a/system/audio_bluetooth_hw/device_port_proxy_hidl.cc +++ b/system/audio_bluetooth_hw/device_port_proxy_hidl.cc @@ -137,7 +137,7 @@ bool BluetoothAudioPortHidl::SetUp(audio_devices_t devices) { state_ = BluetoothStreamState::STANDBY; - auto control_result_cb = [port = this](uint16_t cookie, bool start_resp, + auto control_result_cb = [port = this](uint16_t cookie, bool /*start_resp*/, const BluetoothAudioStatusHidl& status) { if (!port->in_use()) { LOG(ERROR) << "control_result_cb: BluetoothAudioPort is not in use"; diff --git a/system/audio_bluetooth_hw/stream_apis.cc b/system/audio_bluetooth_hw/stream_apis.cc index cabcdcd6071..7b96f5aa51c 100644 --- a/system/audio_bluetooth_hw/stream_apis.cc +++ b/system/audio_bluetooth_hw/stream_apis.cc @@ -281,7 +281,7 @@ static int out_standby(struct audio_stream* stream) { return retval; } -static int out_dump(const struct audio_stream* stream, int fd) { +static int out_dump(const struct audio_stream* stream, int /*fd*/) { const auto* out = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState(); return 0; @@ -691,7 +691,7 @@ static void out_update_source_metadata_v7(struct audio_stream_out* stream, } } -int adev_open_output_stream(struct audio_hw_device* dev, audio_io_handle_t handle, +int adev_open_output_stream(struct audio_hw_device* dev, audio_io_handle_t /*handle*/, audio_devices_t devices, audio_output_flags_t flags, struct audio_config* config, struct audio_stream_out** stream_out, const char* address __unused) { @@ -811,8 +811,8 @@ void adev_close_output_stream(struct audio_hw_device* dev, struct audio_stream_o delete out; } -size_t adev_get_input_buffer_size(const struct audio_hw_device* dev, - const struct audio_config* config) { +size_t adev_get_input_buffer_size(const struct audio_hw_device* /*dev*/, + const struct audio_config* /*config*/) { /* TODO: Adjust this value */ LOG(VERBOSE) << __func__; return 320; @@ -931,7 +931,7 @@ static int in_standby(struct audio_stream* stream) { return retval; } -static int in_dump(const struct audio_stream* stream, int fd) { +static int in_dump(const struct audio_stream* stream, int /*fd*/) { const auto* in = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState(); @@ -1004,7 +1004,7 @@ static int in_remove_audio_effect(const struct audio_stream* stream, effect_hand return 0; } -static int in_set_gain(struct audio_stream_in* stream, float gain) { +static int in_set_gain(struct audio_stream_in* stream, float /*gain*/) { const auto* in = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); @@ -1104,8 +1104,8 @@ static int in_stop(const struct audio_stream_in* stream) { return 0; } -static int in_create_mmap_buffer(const struct audio_stream_in* stream, int32_t min_size_frames, - struct audio_mmap_buffer_info* info) { +static int in_create_mmap_buffer(const struct audio_stream_in* stream, int32_t /*min_size_frames*/, + struct audio_mmap_buffer_info* /*info*/) { const auto* in = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); @@ -1113,7 +1113,7 @@ static int in_create_mmap_buffer(const struct audio_stream_in* stream, int32_t m } static int in_get_mmap_position(const struct audio_stream_in* stream, - struct audio_mmap_position* position) { + struct audio_mmap_position* /*position*/) { const auto* in = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); @@ -1121,8 +1121,8 @@ static int in_get_mmap_position(const struct audio_stream_in* stream, } static int in_get_active_microphones(const struct audio_stream_in* stream, - struct audio_microphone_characteristic_t* mic_array, - size_t* mic_count) { + struct audio_microphone_characteristic_t* /*mic_array*/, + size_t* /*mic_count*/) { const auto* in = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); @@ -1130,14 +1130,14 @@ static int in_get_active_microphones(const struct audio_stream_in* stream, } static int in_set_microphone_direction(const struct audio_stream_in* stream, - audio_microphone_direction_t direction) { + audio_microphone_direction_t /*direction*/) { const auto* in = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return -ENOSYS; } -static int in_set_microphone_field_dimension(const struct audio_stream_in* stream, float zoom) { +static int in_set_microphone_field_dimension(const struct audio_stream_in* stream, float /*zoom*/) { const auto* in = reinterpret_cast(stream); LOG(VERBOSE) << __func__ << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); @@ -1164,7 +1164,7 @@ static void in_update_sink_metadata_v7(struct audio_stream_in* stream, ->UpdateSinkMetadata(sink_metadata); } -int adev_open_input_stream(struct audio_hw_device* dev, audio_io_handle_t handle, +int adev_open_input_stream(struct audio_hw_device* /*dev*/, audio_io_handle_t /*handle*/, audio_devices_t devices, struct audio_config* config, struct audio_stream_in** stream_in, audio_input_flags_t flags __unused, const char* address __unused, audio_source_t source __unused) { @@ -1246,7 +1246,7 @@ int adev_open_input_stream(struct audio_hw_device* dev, audio_io_handle_t handle return 0; } -void adev_close_input_stream(struct audio_hw_device* dev, struct audio_stream_in* stream) { +void adev_close_input_stream(struct audio_hw_device* /*dev*/, struct audio_stream_in* stream) { auto* in = reinterpret_cast(stream); if (in->bluetooth_input_->GetState() != BluetoothStreamState::DISABLED) { -- GitLab From bf1b33b39d7f04b19883ee1aa2e7ac5551a55681 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 8 Oct 2024 16:28:37 +0000 Subject: [PATCH 208/875] system/osi/test/fuzzers: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I354095d19580b14229bfc9c41257644d99c3abd2 --- system/osi/test/fuzzers/alarm/Android.bp | 1 - system/osi/test/fuzzers/alarm/fuzz_alarm.cc | 2 +- system/osi/test/fuzzers/compat/Android.bp | 1 - system/osi/test/fuzzers/compat/fuzz_compat.cc | 3 ++- system/osi/test/fuzzers/fixed_queue/Android.bp | 1 - system/osi/test/fuzzers/fixed_queue/fuzz_fixed_queue.cc | 6 +++--- system/osi/test/fuzzers/list/Android.bp | 1 - system/osi/test/fuzzers/list/fuzz_list.cc | 4 ++-- 8 files changed, 8 insertions(+), 11 deletions(-) diff --git a/system/osi/test/fuzzers/alarm/Android.bp b/system/osi/test/fuzzers/alarm/Android.bp index 47c499a8a1f..e1108e87312 100644 --- a/system/osi/test/fuzzers/alarm/Android.bp +++ b/system/osi/test/fuzzers/alarm/Android.bp @@ -30,7 +30,6 @@ cc_fuzz { ], cflags: [ "-Wno-unused-function", - "-Wno-unused-parameter", ], header_libs: ["libbluetooth_headers"], fuzz_config: { diff --git a/system/osi/test/fuzzers/alarm/fuzz_alarm.cc b/system/osi/test/fuzzers/alarm/fuzz_alarm.cc index 5bf587fcfd8..bc69bf855c0 100644 --- a/system/osi/test/fuzzers/alarm/fuzz_alarm.cc +++ b/system/osi/test/fuzzers/alarm/fuzz_alarm.cc @@ -63,7 +63,7 @@ static MessageLoopThread* thread = new MessageLoopThread("fake main thread"); bluetooth::common::MessageLoopThread* get_main_thread() { return thread; } -static void cb(void* data) { +static void cb(void* /*data*/) { ++cb_counter; semaphore.post(); } diff --git a/system/osi/test/fuzzers/compat/Android.bp b/system/osi/test/fuzzers/compat/Android.bp index 33cb80a6053..2f7ac4aab04 100644 --- a/system/osi/test/fuzzers/compat/Android.bp +++ b/system/osi/test/fuzzers/compat/Android.bp @@ -23,5 +23,4 @@ cc_fuzz { "libbluetooth_log", "libosi", ], - cflags: ["-Wno-unused-parameter"], } diff --git a/system/osi/test/fuzzers/compat/fuzz_compat.cc b/system/osi/test/fuzzers/compat/fuzz_compat.cc index 84d986ef64f..cf209ccbc9e 100644 --- a/system/osi/test/fuzzers/compat/fuzz_compat.cc +++ b/system/osi/test/fuzzers/compat/fuzz_compat.cc @@ -19,7 +19,8 @@ #define MAX_BUFFER_SIZE 4096 -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { +extern "C" int LLVMFuzzerTestOneInput([[maybe_unused]] const uint8_t* Data, + [[maybe_unused]] size_t Size) { // Our functions are only defined with __GLIBC__ #if __GLIBC__ // Init our wrapper diff --git a/system/osi/test/fuzzers/fixed_queue/Android.bp b/system/osi/test/fuzzers/fixed_queue/Android.bp index 8bb68f41f82..8758597a558 100644 --- a/system/osi/test/fuzzers/fixed_queue/Android.bp +++ b/system/osi/test/fuzzers/fixed_queue/Android.bp @@ -24,5 +24,4 @@ cc_fuzz { "libchrome", "libosi", ], - cflags: ["-Wno-unused-parameter"], } diff --git a/system/osi/test/fuzzers/fixed_queue/fuzz_fixed_queue.cc b/system/osi/test/fuzzers/fixed_queue/fuzz_fixed_queue.cc index 30c163390c4..e5671f0828c 100644 --- a/system/osi/test/fuzzers/fixed_queue/fuzz_fixed_queue.cc +++ b/system/osi/test/fuzzers/fixed_queue/fuzz_fixed_queue.cc @@ -29,8 +29,8 @@ static future_t* received_message_future = nullptr; // Empty callback function -void fqFreeCb(void* data) {} -void fqCb(fixed_queue_t* queue, void* data) { +void fqFreeCb(void* /*data*/) {} +void fqCb(fixed_queue_t* queue, void* /*data*/) { void* msg = fixed_queue_try_dequeue(queue); future_ready(received_message_future, msg); } @@ -72,7 +72,7 @@ void createNewFuture() { } void callArbitraryFunction(fixed_queue_t* fixed_queue, std::vector* live_buffer_vector, - std::vector* live_thread_vector, + std::vector* /*live_thread_vector*/, FuzzedDataProvider* dataProvider) { void* buf_ptr = nullptr; size_t index = 0; diff --git a/system/osi/test/fuzzers/list/Android.bp b/system/osi/test/fuzzers/list/Android.bp index 65f4fcbecd8..5c8f15e81eb 100644 --- a/system/osi/test/fuzzers/list/Android.bp +++ b/system/osi/test/fuzzers/list/Android.bp @@ -21,5 +21,4 @@ cc_fuzz { "liblog", "libosi", ], - cflags: ["-Wno-unused-parameter"], } diff --git a/system/osi/test/fuzzers/list/fuzz_list.cc b/system/osi/test/fuzzers/list/fuzz_list.cc index e0e74165d20..b4ae8c5e0bf 100644 --- a/system/osi/test/fuzzers/list/fuzz_list.cc +++ b/system/osi/test/fuzzers/list/fuzz_list.cc @@ -27,9 +27,9 @@ struct list_node_t { void* data; }; -void cb(void* data) {} +void cb(void* /*data*/) {} // Pass a ptr to FuzzedDataProvider in context -bool list_iter_cb_impl(void* data, void* context) { +bool list_iter_cb_impl(void* /*data*/, void* context) { FuzzedDataProvider* dataProvider = reinterpret_cast(context); return dataProvider->ConsumeBool(); } -- GitLab From 061242e393c334b0694bda4b38ae254e007cf885 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 8 Oct 2024 16:29:20 +0000 Subject: [PATCH 209/875] system: Enforce -Wunused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: Ifa12df68191725545adaad8eb0c6ada5dfd28d2d --- system/gd/dumpsys/bundler/Android.bp | 2 - system/gd/dumpsys/bundler/bundler.cc | 2 +- system/main/Android.bp | 7 -- .../test/main_shim_stack_lifecycle_test.cc | 32 +++---- system/main/test/main_shim_test.cc | 90 ++++++++++--------- system/packet/Android.bp | 3 - system/test/suite/Android.bp | 1 - system/test/suite/adapter/bluetooth_test.cc | 4 +- system/test/suite/gatt/gatt_test.cc | 16 ++-- 9 files changed, 75 insertions(+), 82 deletions(-) diff --git a/system/gd/dumpsys/bundler/Android.bp b/system/gd/dumpsys/bundler/Android.bp index bda314154b2..301346ec6c8 100644 --- a/system/gd/dumpsys/bundler/Android.bp +++ b/system/gd/dumpsys/bundler/Android.bp @@ -72,7 +72,6 @@ cc_binary_host { defaults: [ "bluetooth_flatbuffer_bundler_defaults", ], - cflags: ["-Wno-unused-parameter"], } cc_test_host { @@ -89,5 +88,4 @@ cc_test_host { test_options: { unit_test: true, }, - cflags: ["-Wno-unused-parameter"], } diff --git a/system/gd/dumpsys/bundler/bundler.cc b/system/gd/dumpsys/bundler/bundler.cc index a88da57466a..72097ac101e 100644 --- a/system/gd/dumpsys/bundler/bundler.cc +++ b/system/gd/dumpsys/bundler/bundler.cc @@ -261,7 +261,7 @@ int WriteBundledSchema() { return EXIT_SUCCESS; } -int Usage(int argc, char** argv) { +int Usage(int /*argc*/, char** argv) { fprintf(stderr, "Usage: %s [-r | -w] [-f ] [-g ] [-n ] [-v] -m " " Post(base::BindOnce( - [](int id, int iter, std::shared_ptr stack_manager) { + [](int /*id*/, int iter, std::shared_ptr stack_manager) { stack_manager->GetUnsafeModule()->TestMethod({ .iter = iter, .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData data) {}, + .callback = [](TestCallbackData /*data*/) {}, }); }, c->Id(), i, StackManager())); c->Post(base::BindOnce( - [](int id, int iter, std::shared_ptr stack_manager) { + [](int /*id*/, int iter, std::shared_ptr stack_manager) { stack_manager->GetUnsafeModule()->TestMethod({ .iter = iter, .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData data) {}, + .callback = [](TestCallbackData /*data*/) {}, }); }, c->Id(), i, StackManager())); c->Post(base::BindOnce( - [](int id, int iter, std::shared_ptr stack_manager) { + [](int /*id*/, int iter, std::shared_ptr stack_manager) { stack_manager->GetUnsafeModule()->TestMethod({ .iter = iter, .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData data) {}, + .callback = [](TestCallbackData /*data*/) {}, }); }, c->Id(), i, StackManager())); @@ -554,12 +554,12 @@ TEST_F(StackLifecycleWithDefaultModulesUnitTest, client_using_stack_manager_when for (int i = 0; i < kNumIters; i++) { for (auto& c : client_group.clients_) { c->Post(base::BindOnce( - [](int id, int iter, Counters* counters, - std::shared_ptr stack_manager) { + [](int /*id*/, int iter, Counters* counters, + std::shared_ptr /*stack_manager*/) { TestData test_data = { .iter = iter, .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData data) {}, + .callback = [](TestCallbackData /*data*/) {}, }; if (bluetooth::shim::Stack::GetInstance()->CallOnModule( [test_data](TestStackModule1* mod) { mod->TestMethod(test_data); })) { @@ -570,12 +570,12 @@ TEST_F(StackLifecycleWithDefaultModulesUnitTest, client_using_stack_manager_when }, c->Id(), i, &counters, StackManager())); c->Post(base::BindOnce( - [](int id, int iter, Counters* counters, - std::shared_ptr stack_manager) { + [](int /*id*/, int iter, Counters* counters, + std::shared_ptr /*stack_manager*/) { TestData test_data = { .iter = iter, .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData data) {}, + .callback = [](TestCallbackData /*data*/) {}, }; if (bluetooth::shim::Stack::GetInstance()->CallOnModule( [test_data](TestStackModule2* mod) { mod->TestMethod(test_data); })) { @@ -586,12 +586,12 @@ TEST_F(StackLifecycleWithDefaultModulesUnitTest, client_using_stack_manager_when }, c->Id(), i, &counters, StackManager())); c->Post(base::BindOnce( - [](int id, int iter, Counters* counters, - std::shared_ptr stack_manager) { + [](int /*id*/, int iter, Counters* counters, + std::shared_ptr /*stack_manager*/) { TestData test_data = { .iter = iter, .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData data) {}, + .callback = [](TestCallbackData /*data*/) {}, }; if (bluetooth::shim::Stack::GetInstance()->CallOnModule( [test_data](TestStackModule3* mod) { mod->TestMethod(test_data); })) { diff --git a/system/main/test/main_shim_test.cc b/system/main/test/main_shim_test.cc index 43d40bc799e..7dbbedd6071 100644 --- a/system/main/test/main_shim_test.cc +++ b/system/main/test/main_shim_test.cc @@ -123,36 +123,39 @@ bluetooth::common::TimestamperInMilliseconds timestamper_in_milliseconds; void mock_on_send_data_upwards(BT_HDR*) {} -void mock_on_packets_completed(uint16_t handle, uint16_t num_packets) {} +void mock_on_packets_completed(uint16_t /*handle*/, uint16_t /*num_packets*/) {} -void mock_connection_classic_on_connected(const RawAddress& bda, uint16_t handle, uint8_t enc_mode, - bool locally_initiated) {} +void mock_connection_classic_on_connected(const RawAddress& /*bda*/, uint16_t /*handle*/, + uint8_t /*enc_mode*/, bool /*locally_initiated*/) {} -void mock_connection_classic_on_failed(const RawAddress& bda, tHCI_STATUS status, - bool locally_initiated) {} +void mock_connection_classic_on_failed(const RawAddress& /*bda*/, tHCI_STATUS /*status*/, + bool /*locally_initiated*/) {} -void mock_connection_classic_on_disconnected(tHCI_STATUS status, uint16_t handle, - tHCI_STATUS reason) { +void mock_connection_classic_on_disconnected(tHCI_STATUS /*status*/, uint16_t handle, + tHCI_STATUS /*reason*/) { ASSERT_TRUE(mock_function_handle_promise_map.find(__func__) != mock_function_handle_promise_map.end()); mock_function_handle_promise_map[__func__].set_value(handle); } -void mock_connection_le_on_connected(const tBLE_BD_ADDR& address_with_type, uint16_t handle, - tHCI_ROLE role, uint16_t conn_interval, uint16_t conn_latency, - uint16_t conn_timeout, const RawAddress& local_rpa, - const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type, - bool can_read_discoverable_characteristics) {} -void mock_connection_le_on_failed(const tBLE_BD_ADDR& address_with_type, uint16_t handle, - bool enhanced, tHCI_STATUS status) {} +void mock_connection_le_on_connected(const tBLE_BD_ADDR& /*address_with_type*/, uint16_t /*handle*/, + tHCI_ROLE /*role*/, uint16_t /*conn_interval*/, + uint16_t /*conn_latency*/, uint16_t /*conn_timeout*/, + const RawAddress& /*local_rpa*/, + const RawAddress& /*peer_rpa*/, + tBLE_ADDR_TYPE /*peer_addr_type*/, + bool /*can_read_discoverable_characteristics*/) {} +void mock_connection_le_on_failed(const tBLE_BD_ADDR& /*address_with_type*/, uint16_t /*handle*/, + bool /*enhanced*/, tHCI_STATUS /*status*/) {} static std::promise mock_connection_le_on_disconnected_promise; -void mock_connection_le_on_disconnected(tHCI_STATUS status, uint16_t handle, tHCI_STATUS reason) { +void mock_connection_le_on_disconnected(tHCI_STATUS /*status*/, uint16_t handle, + tHCI_STATUS /*reason*/) { mock_connection_le_on_disconnected_promise.set_value(handle); } -void mock_link_classic_on_read_remote_extended_features_complete(uint16_t handle, - uint8_t current_page_number, - uint8_t max_page_number, - uint64_t features) {} +void mock_link_classic_on_read_remote_extended_features_complete(uint16_t /*handle*/, + uint8_t /*current_page_number*/, + uint8_t /*max_page_number*/, + uint64_t /*features*/) {} shim::acl_interface_t acl_interface{ .on_send_data_upwards = mock_on_send_data_upwards, @@ -211,7 +214,7 @@ template class MockEnQueue : public os::IQueueEnqueue { using EnqueueCallback = base::Callback()>; - void RegisterEnqueue(os::Handler* handler, EnqueueCallback callback) override {} + void RegisterEnqueue(os::Handler* /*handler*/, EnqueueCallback /*callback*/) override {} void UnregisterEnqueue() override {} }; @@ -219,7 +222,7 @@ template class MockDeQueue : public os::IQueueDequeue { using DequeueCallback = base::Callback; - void RegisterDequeue(os::Handler* handler, DequeueCallback callback) override {} + void RegisterDequeue(os::Handler* /*handler*/, DequeueCallback /*callback*/) override {} void UnregisterDequeue() override {} std::unique_ptr TryDequeue() override { return nullptr; } }; @@ -258,7 +261,7 @@ public: return true; } - bool Disconnect(hci::DisconnectReason reason) override { + bool Disconnect(hci::DisconnectReason /*reason*/) override { disconnect_cnt_++; disconnect_promise_.set_value(handle_); return true; @@ -299,7 +302,7 @@ public: bool ReadRemoteVersionInformation() override { return true; } bool LeReadRemoteFeatures() override { return true; } - void Disconnect(hci::DisconnectReason reason) override { + void Disconnect(hci::DisconnectReason /*reason*/) override { disconnect_cnt_++; disconnect_promise_.set_value(handle_); } @@ -546,24 +549,27 @@ TEST_F(MainShimTest, BleScannerInterfaceImpl_nop) { class TestScanningCallbacks : public ::ScanningCallbacks { public: ~TestScanningCallbacks() {} - void OnScannerRegistered(const bluetooth::Uuid app_uuid, uint8_t scannerId, - uint8_t status) override {} - void OnSetScannerParameterComplete(uint8_t scannerId, uint8_t status) override {} - void OnScanResult(uint16_t event_type, uint8_t addr_type, RawAddress bda, uint8_t primary_phy, - uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, - uint16_t periodic_adv_int, std::vector adv_data) override {} - void OnTrackAdvFoundLost(AdvertisingTrackInfo advertising_track_info) override {} - void OnBatchScanReports(int client_if, int status, int report_format, int num_records, - std::vector data) override {} - void OnBatchScanThresholdCrossed(int client_if) override {} - void OnPeriodicSyncStarted(int reg_id, uint8_t status, uint16_t sync_handle, - uint8_t advertising_sid, uint8_t address_type, RawAddress address, - uint8_t phy, uint16_t interval) override {} - void OnPeriodicSyncReport(uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, - std::vector data) override {} - void OnPeriodicSyncLost(uint16_t sync_handle) override {} - void OnPeriodicSyncTransferred(int pa_source, uint8_t status, RawAddress address) override {} - void OnBigInfoReport(uint16_t sync_handle, bool encrypted) override {} + void OnScannerRegistered(const bluetooth::Uuid /*app_uuid*/, uint8_t /*scannerId*/, + uint8_t /*status*/) override {} + void OnSetScannerParameterComplete(uint8_t /*scannerId*/, uint8_t /*status*/) override {} + void OnScanResult(uint16_t /*event_type*/, uint8_t /*addr_type*/, RawAddress /*bda*/, + uint8_t /*primary_phy*/, uint8_t /*secondary_phy*/, uint8_t /*advertising_sid*/, + int8_t /*tx_power*/, int8_t /*rssi*/, uint16_t /*periodic_adv_int*/, + std::vector /*adv_data*/) override {} + void OnTrackAdvFoundLost(AdvertisingTrackInfo /*advertising_track_info*/) override {} + void OnBatchScanReports(int /*client_if*/, int /*status*/, int /*report_format*/, + int /*num_records*/, std::vector /*data*/) override {} + void OnBatchScanThresholdCrossed(int /*client_if*/) override {} + void OnPeriodicSyncStarted(int /*reg_id*/, uint8_t /*status*/, uint16_t /*sync_handle*/, + uint8_t /*advertising_sid*/, uint8_t /*address_type*/, + RawAddress /*address*/, uint8_t /*phy*/, + uint16_t /*interval*/) override {} + void OnPeriodicSyncReport(uint16_t /*sync_handle*/, int8_t /*tx_power*/, int8_t /*rssi*/, + uint8_t /*status*/, std::vector /*data*/) override {} + void OnPeriodicSyncLost(uint16_t /*sync_handle*/) override {} + void OnPeriodicSyncTransferred(int /*pa_source*/, uint8_t /*status*/, + RawAddress /*address*/) override {} + void OnBigInfoReport(uint16_t /*sync_handle*/, bool /*encrypted*/) override {} }; TEST_F(MainShimTest, DISABLED_BleScannerInterfaceImpl_OnScanResult) { @@ -646,7 +652,7 @@ TEST_F(MainShimTestWithClassicConnection, nop) {} TEST_F(MainShimTestWithClassicConnection, read_extended_feature) { int read_remote_extended_feature_call_count = 0; raw_connection_->read_remote_extended_features_function_ = - [&read_remote_extended_feature_call_count](uint8_t page_number) { + [&read_remote_extended_feature_call_count](uint8_t /*page_number*/) { read_remote_extended_feature_call_count++; }; diff --git a/system/packet/Android.bp b/system/packet/Android.bp index b5257108d2a..d3ba6dfd71c 100644 --- a/system/packet/Android.bp +++ b/system/packet/Android.bp @@ -83,9 +83,6 @@ cc_test { "libchrome", "libgmock", ], - cflags: [ - "-Wno-unused-parameter", - ], target: { android: { static_libs: [ diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp index 6729fa6712c..4ce6367d5b4 100644 --- a/system/test/suite/Android.bp +++ b/system/test/suite/Android.bp @@ -153,5 +153,4 @@ cc_test { }, host: {}, }, - cflags: ["-Wno-unused-parameter"], } diff --git a/system/test/suite/adapter/bluetooth_test.cc b/system/test/suite/adapter/bluetooth_test.cc index ce7f0c4479b..e28a2259fa6 100644 --- a/system/test/suite/adapter/bluetooth_test.cc +++ b/system/test/suite/adapter/bluetooth_test.cc @@ -40,7 +40,7 @@ void AdapterStateChangedCallback(bt_state_t new_state) { semaphore_post(instance->adapter_state_changed_callback_sem_); } -void AdapterPropertiesCallback(bt_status_t status, int num_properties, +void AdapterPropertiesCallback(bt_status_t /*status*/, int num_properties, bt_property_t* new_properties) { property_free_array(instance->last_changed_properties_, instance->properties_changed_count_); instance->last_changed_properties_ = property_copy_array(new_properties, num_properties); @@ -48,7 +48,7 @@ void AdapterPropertiesCallback(bt_status_t status, int num_properties, semaphore_post(instance->adapter_properties_callback_sem_); } -void RemoteDevicePropertiesCallback(bt_status_t status, RawAddress* remote_bd_addr, +void RemoteDevicePropertiesCallback(bt_status_t /*status*/, RawAddress* remote_bd_addr, int num_properties, bt_property_t* properties) { instance->curr_remote_device_ = *remote_bd_addr; property_free_array(instance->remote_device_last_changed_properties_, diff --git a/system/test/suite/gatt/gatt_test.cc b/system/test/suite/gatt/gatt_test.cc index f297e78f2f5..b99dbf77f8e 100644 --- a/system/test/suite/gatt/gatt_test.cc +++ b/system/test/suite/gatt/gatt_test.cc @@ -26,29 +26,29 @@ namespace bttest { static GattTest* instance = nullptr; -void RegisterClientCallback(int status, int clientIf, const bluetooth::Uuid& app_uuid) { +void RegisterClientCallback(int status, int clientIf, const bluetooth::Uuid& /*app_uuid*/) { instance->status_ = status; instance->client_interface_id_ = clientIf; semaphore_post(instance->register_client_callback_sem_); } -void ScanResultCallback(uint16_t ble_evt_type, uint8_t addr_type, RawAddress* bda, - uint8_t ble_primary_phy, uint8_t ble_secondary_phy, - uint8_t ble_advertising_sid, int8_t ble_tx_power, int8_t rssi, - uint16_t ble_periodic_adv_int, std::vector adv_data, - RawAddress* original_bda) { +void ScanResultCallback(uint16_t /*ble_evt_type*/, uint8_t /*addr_type*/, RawAddress* /*bda*/, + uint8_t /*ble_primary_phy*/, uint8_t /*ble_secondary_phy*/, + uint8_t /*ble_advertising_sid*/, int8_t /*ble_tx_power*/, int8_t /*rssi*/, + uint16_t /*ble_periodic_adv_int*/, std::vector /*adv_data*/, + RawAddress* /*original_bda*/) { semaphore_post(instance->scan_result_callback_sem_); } // GATT server callbacks -void RegisterServerCallback(int status, int server_if, const bluetooth::Uuid& uuid) { +void RegisterServerCallback(int status, int server_if, const bluetooth::Uuid& /*uuid*/) { instance->status_ = status; instance->server_interface_id_ = server_if; semaphore_post(instance->register_server_callback_sem_); } void ServiceAddedCallback(int status, int server_if, const btgatt_db_element_t* service, - size_t service_count) { + size_t /*service_count*/) { instance->status_ = status; instance->server_interface_id_ = server_if; instance->service_handle_ = service[0].attribute_handle; -- GitLab From a0950e32a21e15461a7ae9590cf4cee058fa3d7d Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 8 Oct 2024 16:35:26 +0000 Subject: [PATCH 210/875] BUILD.gn: Remove cflag -Wno-unused-parameter Bug: 299772495 Test: m com.android.btservices Flag: EXEMPT, mechanical refactor Change-Id: I450634af79ecdf376273bdb86da0eebee0a0fb3a --- system/gd/BUILD.gn | 1 - system/gd/dumpsys/bundler/BUILD.gn | 1 - 2 files changed, 2 deletions(-) diff --git a/system/gd/BUILD.gn b/system/gd/BUILD.gn index 4e14df9a254..5786a5b7004 100644 --- a/system/gd/BUILD.gn +++ b/system/gd/BUILD.gn @@ -20,7 +20,6 @@ import("//common-mk/flatbuffer.gni") config("gd_defaults") { cflags_cc = [ "-DGOOGLE_PROTOBUF_NO_RTTI", - "-Wno-unused-parameter", "-Wno-unused-result", "-Wno-tautological-overlap-compare", ] diff --git a/system/gd/dumpsys/bundler/BUILD.gn b/system/gd/dumpsys/bundler/BUILD.gn index 4be41331c2e..324afbb4f17 100644 --- a/system/gd/dumpsys/bundler/BUILD.gn +++ b/system/gd/dumpsys/bundler/BUILD.gn @@ -31,7 +31,6 @@ config("bundler_defaults") { cflags_cc = [ "-std=c++17", - "-Wno-unused-parameter", "-Wno-unused-variable", "-Wno-poison-system-directories", ] -- GitLab From 4acdbf6c0e3b57ffbc94cf70ff1045f171b1b679 Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Thu, 8 Aug 2024 00:15:17 +0000 Subject: [PATCH 211/875] Add flag com.android.bluetooth.flag.btsec_avdt_msg_ind_type_confusion Bug: 358212054 Bug: 315241296 Flag: com.android.bluetooth.flags.btsec_avdt_msg_ind_type_confusion Test: m libbluetooth Ignore-AOSP-First: security Tag: #security Change-Id: Ie01375e604ba07f015fabb26f4c247a1766aa170 --- flags/security.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/security.aconfig b/flags/security.aconfig index 2bb69eac95d..5f9e3b1a083 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -44,3 +44,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "btsec_avdt_msg_ind_type_confusion" + namespace: "bluetooth" + description: "Properly check current state and sig value of avdt rej/rsp messages before parsing" + bug: "358212054" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 0e257142534d2355c60c8bfcb69dc4f2e2278f33 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 8 Oct 2024 18:52:52 +0000 Subject: [PATCH 212/875] Lint: enforce as error Now that the baseline is up to date we can enforce some as error to prevent spreading the disease. Bug: 289445022 Test: m Bluetooth Flag: Exempt lint Change-Id: I13f25b3fa43b9ac1b97b4f67c0cb45b3603f17e3 --- android/app/Android.bp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/android/app/Android.bp b/android/app/Android.bp index af6a2af8951..f038a3f43b9 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -293,15 +293,44 @@ android_app { javacflags: ["-Aroom.schemaLocation=packages/modules/Bluetooth/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/schemas"], lint: { - // TODO(b/318814235): Add back ObsoleteSdkInt to this list. error_checks: [ + "Autofill", + "DefaultLocale", + "DuplicateDefinition", + // "ExportedContentProvider", // TODO: b/289445022 - enable this check + // "ExportedReceiver", // TODO: b/289445022 - enable this check + // "ExportedService", // TODO: b/289445022 - enable this check "ExtraText", + "ExtraTranslation", + "GestureBackNavigation", + "GuardedLogInvocation", + "HandlerLeak", + "InflateParams", + // "InvalidPermission", // TODO: b/289445022 - enable this check + "LabelFor", "MissingClass", + // "MissingVersion", // TODO: b/289445022 - enable this check + "MonochromeLauncherIcon", "NewApi", + "ObsoleteSdkInt", + // "QueryAllPackagesPermission", // TODO: b/289445022 - enable this check "Recycle", "RtlHardcoded", + "RtlSymmetry", + "ScrollViewSize", + "SetTextI18n", + "SimpleDateFormat", + "StaticFieldLeak", + "StringFormatCount", + "StringFormatInvalid", + "TextFields", + "TypographyEllipsis", "UseSparseArrays", "UseValueOf", + "VectorPath", + "VisibleForTests", + "Wakelock", + "WakelockTimeout", ], extra_check_modules: ["BluetoothLintChecker"], baseline_filename: "lint-baseline.xml", -- GitLab From 5701b75f35d47133d0bf9ae2fa966ce8db5ffa73 Mon Sep 17 00:00:00 2001 From: Pomai Ahlo Date: Fri, 4 Oct 2024 14:43:51 -0700 Subject: [PATCH 213/875] Rename tPORT_STATE to PortSettings Also rename "pars" variables to "settings" for consistency Bug: 345006660 Test: m com.android.btservices Flag: EXEMPT mechanical refactor Change-Id: I52f71268dfd9fe6b90d62c58212e248954a40dec --- system/bta/jv/bta_jv_act.cc | 24 +++---- system/stack/include/port_api.h | 19 +++--- system/stack/rfcomm/port_api.cc | 28 ++++----- system/stack/rfcomm/port_int.h | 4 +- system/stack/rfcomm/port_rfc.cc | 16 ++--- system/stack/rfcomm/port_utils.cc | 10 +-- system/stack/rfcomm/rfc_int.h | 13 ++-- system/stack/rfcomm/rfc_port_fsm.cc | 63 +++++++++---------- system/stack/rfcomm/rfc_port_if.cc | 13 ++-- system/stack/rfcomm/rfc_ts_frames.cc | 20 +++--- .../test/mock/mock_stack_rfcomm_port_api.cc | 4 +- 11 files changed, 108 insertions(+), 106 deletions(-) diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc index 2a3ffaea4b0..647e7b2a5b0 100644 --- a/system/bta/jv/bta_jv_act.cc +++ b/system/bta/jv/bta_jv_act.cc @@ -1442,7 +1442,7 @@ void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddre tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id) { uint16_t handle = 0; uint32_t event_mask = BTA_JV_RFC_EV_MASK; - tPORT_STATE port_state; + PortSettings port_settings; tBTA_JV bta_jv = { .rfc_cl_init = @@ -1485,13 +1485,13 @@ void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddre if (PORT_SetDataCOCallback(handle, bta_jv_port_data_co_cback) != PORT_SUCCESS) { log::warn("Unable to set RFCOMM client data callback handle:{}", handle); } - if (PORT_GetState(handle, &port_state) != PORT_SUCCESS) { + if (PORT_GetSettings(handle, &port_settings) != PORT_SUCCESS) { log::warn("Unable to get RFCOMM client state handle:{}", handle); } - port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); + port_settings.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); - if (PORT_SetState(handle, &port_state) != PORT_SUCCESS) { + if (PORT_SetSettings(handle, &port_settings) != PORT_SUCCESS) { log::warn("Unable to set RFCOMM client state handle:{}", handle); } @@ -1677,7 +1677,7 @@ static void bta_jv_port_event_sr_cback(uint32_t code, uint16_t port_handle) { static tBTA_JV_PCB* bta_jv_add_rfc_port(tBTA_JV_RFC_CB* p_cb, tBTA_JV_PCB* p_pcb_open) { uint8_t used = 0, i, listen = 0; uint32_t si = 0; - tPORT_STATE port_state; + PortSettings port_settings; uint32_t event_mask = BTA_JV_RFC_EV_MASK; tBTA_JV_PCB* p_pcb = NULL; tBTA_SEC sec_mask; @@ -1733,13 +1733,13 @@ static tBTA_JV_PCB* bta_jv_add_rfc_port(tBTA_JV_RFC_CB* p_cb, tBTA_JV_PCB* p_pcb if (PORT_SetDataCOCallback(p_pcb->port_handle, bta_jv_port_data_co_cback) != PORT_SUCCESS) { log::warn("Unable to set RFCOMM server data callback handle:{}", p_pcb->port_handle); } - if (PORT_GetState(p_pcb->port_handle, &port_state) != PORT_SUCCESS) { + if (PORT_GetSettings(p_pcb->port_handle, &port_settings) != PORT_SUCCESS) { log::warn("Unable to get RFCOMM server state handle:{}", p_pcb->port_handle); } - port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); + port_settings.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); - if (PORT_SetState(p_pcb->port_handle, &port_state) != PORT_SUCCESS) { + if (PORT_SetSettings(p_pcb->port_handle, &port_settings) != PORT_SUCCESS) { log::warn("Unable to set RFCOMM server state handle:{}", p_pcb->port_handle); } p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si); @@ -1762,7 +1762,7 @@ void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t ma tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id) { uint16_t handle = 0; uint32_t event_mask = BTA_JV_RFC_EV_MASK; - tPORT_STATE port_state; + PortSettings port_settings; tBTA_JV_RFC_CB* p_cb = NULL; tBTA_JV_PCB* p_pcb; tBTA_JV_RFCOMM_START evt_data; @@ -1800,13 +1800,13 @@ void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t ma PORT_SUCCESS) { log::warn("Unable to set RFCOMM server event mask and callback handle:{}", handle); } - if (PORT_GetState(handle, &port_state) != PORT_SUCCESS) { + if (PORT_GetSettings(handle, &port_settings) != PORT_SUCCESS) { log::warn("Unable to get RFCOMM server state handle:{}", handle); } - port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); + port_settings.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); - if (PORT_SetState(handle, &port_state) != PORT_SUCCESS) { + if (PORT_SetSettings(handle, &port_settings) != PORT_SUCCESS) { log::warn("Unable to set RFCOMM port state handle:{}", handle); } } while (0); diff --git a/system/stack/include/port_api.h b/system/stack/include/port_api.h index d096e754726..ae511a49ecf 100644 --- a/system/stack/include/port_api.h +++ b/system/stack/include/port_api.h @@ -38,7 +38,7 @@ * Define port settings structure send from the application in the * set settings request, or to the application in the set settings indication. */ -typedef struct { +struct PortSettings { #define PORT_BAUD_RATE_9600 0x03 uint8_t baud_rate; @@ -70,8 +70,7 @@ typedef struct { #define PORT_XOFF_DC3 0x13 uint8_t xoff_char; - -} tPORT_STATE; +}; /* * Define the callback function prototypes. Parameters are specific @@ -350,28 +349,28 @@ typedef void(tPORT_MGMT_CALLBACK)(const tPORT_RESULT code, uint16_t port_handle) * Function PORT_SetState * * Description This function configures connection according to the - * specifications in the tPORT_STATE structure. + * specifications in the PortSettings structure. * * Parameters: handle - Handle returned in the RFCOMM_CreateConnection - * p_settings - Pointer to a tPORT_STATE structure containing + * p_settings - Pointer to a PortSettings structure containing * configuration information for the connection. * ******************************************************************************/ -[[nodiscard]] int PORT_SetState(uint16_t handle, tPORT_STATE* p_settings); +[[nodiscard]] int PORT_SetSettings(uint16_t handle, PortSettings* p_settings); /******************************************************************************* * - * Function PORT_GetState + * Function PORT_GetSettings * - * Description This function is called to fill tPORT_STATE structure + * Description This function is called to fill PortSettings structure * with the current control settings for the port * * Parameters: handle - Handle returned in the RFCOMM_CreateConnection - * p_settings - Pointer to a tPORT_STATE structure in which + * p_settings - Pointer to a PortSettings structure in which * configuration information is returned. * ******************************************************************************/ -[[nodiscard]] int PORT_GetState(uint16_t handle, tPORT_STATE* p_settings); +[[nodiscard]] int PORT_GetSettings(uint16_t handle, PortSettings* p_settings); /******************************************************************************* * diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc index b8a8e35b111..34af8e34548 100644 --- a/system/stack/rfcomm/port_api.cc +++ b/system/stack/rfcomm/port_api.cc @@ -561,21 +561,21 @@ bool PORT_IsCollisionDetected(RawAddress bd_addr) { /******************************************************************************* * - * Function PORT_SetState + * Function PORT_SetSettings * * Description This function configures connection according to the - * specifications in the tPORT_STATE structure. + * specifications in the PortSettings structure. * * Parameters: handle - Handle returned in the RFCOMM_CreateConnection - * p_settings - Pointer to a tPORT_STATE structure containing + * p_settings - Pointer to a PortSettings structure containing * configuration information for the connection. * * ******************************************************************************/ -int PORT_SetState(uint16_t handle, tPORT_STATE* p_settings) { +int PORT_SetSettings(uint16_t handle, PortSettings* p_settings) { uint8_t baud_rate; - log::verbose("PORT_SetState() handle:{}", handle); + log::verbose("PORT_SetSettings() handle:{}", handle); tPORT* p_port = get_port_from_handle(handle); if (p_port == nullptr) { log::error("Unable to get RFCOMM port control block bad handle:{}", handle); @@ -590,10 +590,10 @@ int PORT_SetState(uint16_t handle, tPORT_STATE* p_settings) { return PORT_LINE_ERR; } - log::verbose("PORT_SetState() handle:{} FC_TYPE:0x{:x}", handle, p_settings->fc_type); + log::verbose("PORT_SetSettings() handle:{} FC_TYPE:0x{:x}", handle, p_settings->fc_type); - baud_rate = p_port->user_port_pars.baud_rate; - p_port->user_port_pars = *p_settings; + baud_rate = p_port->user_port_settings.baud_rate; + p_port->user_port_settings = *p_settings; /* for now we've been asked to pass only baud rate */ if (baud_rate != p_settings->baud_rate) { @@ -604,18 +604,18 @@ int PORT_SetState(uint16_t handle, tPORT_STATE* p_settings) { /******************************************************************************* * - * Function PORT_GetState + * Function PORT_GetSettings * - * Description This function is called to fill tPORT_STATE structure + * Description This function is called to fill PortSettings structure * with the curremt control settings for the port * * Parameters: handle - Handle returned in the RFCOMM_CreateConnection - * p_settings - Pointer to a tPORT_STATE structure in which + * p_settings - Pointer to a PortSettings structure in which * configuration information is returned. * ******************************************************************************/ -int PORT_GetState(uint16_t handle, tPORT_STATE* p_settings) { - log::verbose("PORT_GetState() handle:{}", handle); +int PORT_GetSettings(uint16_t handle, PortSettings* p_settings) { + log::verbose("PORT_GetSettings() handle:{}", handle); tPORT* p_port = get_port_from_handle(handle); if (p_port == nullptr) { @@ -631,7 +631,7 @@ int PORT_GetState(uint16_t handle, tPORT_STATE* p_settings) { return PORT_LINE_ERR; } - *p_settings = p_port->user_port_pars; + *p_settings = p_port->user_port_settings; return PORT_SUCCESS; } diff --git a/system/stack/rfcomm/port_int.h b/system/stack/rfcomm/port_int.h index 3505763b567..f4773d58440 100644 --- a/system/stack/rfcomm/port_int.h +++ b/system/stack/rfcomm/port_int.h @@ -172,8 +172,8 @@ typedef struct { tPORT_DATA tx; /* Control block for data from app to peer */ tPORT_DATA rx; /* Control block for data from peer to app */ - tPORT_STATE user_port_pars; /* Port parameters for user connection */ - tPORT_STATE peer_port_pars; /* Port parameters for user connection */ + PortSettings user_port_settings; /* Port parameters for user connection */ + PortSettings peer_port_settings; /* Port parameters for peer connection */ tPORT_CTRL local_ctrl; tPORT_CTRL peer_ctrl; diff --git a/system/stack/rfcomm/port_rfc.cc b/system/stack/rfcomm/port_rfc.cc index b94aff9f305..387e7a71975 100644 --- a/system/stack/rfcomm/port_rfc.cc +++ b/system/stack/rfcomm/port_rfc.cc @@ -142,7 +142,7 @@ void port_start_par_neg(tPORT* p_port) { return; } - RFCOMM_PortParameterNegotiationRequest(p_mcb, p_port->dlci, &p_port->user_port_pars); + RFCOMM_PortParameterNegotiationRequest(p_mcb, p_port->dlci, &p_port->user_port_settings); } /******************************************************************************* @@ -519,7 +519,7 @@ void PORT_DlcEstablishCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint16_t * allocated before meaning that application already made open. * ******************************************************************************/ -void PORT_PortNegInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars, uint16_t param_mask) { +void PORT_PortNegInd(tRFC_MCB* p_mcb, uint8_t dlci, PortSettings* p_settings, uint16_t param_mask) { tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci); log::verbose("PORT_PortNegInd"); @@ -528,15 +528,15 @@ void PORT_PortNegInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars, uint16_ /* This can be a first request for this port */ p_port = port_find_dlci_port(dlci); if (!p_port) { - RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_pars, 0); + RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_settings, 0); return; } p_mcb->port_handles[dlci] = p_port->handle; } /* Check if the flow control is acceptable on local side */ - p_port->peer_port_pars = *p_pars; - RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_pars, param_mask); + p_port->peer_port_settings = *p_settings; + RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_settings, param_mask); } /******************************************************************************* @@ -547,7 +547,8 @@ void PORT_PortNegInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars, uint16_ * state for the port. Propagate change to the user. * ******************************************************************************/ -void PORT_PortNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* /* p_pars */, uint16_t result) { +void PORT_PortNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, PortSettings* /* p_settings */, + uint16_t result) { tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci); log::verbose("PORT_PortNegCnf"); @@ -822,7 +823,8 @@ void PORT_DataInd(tRFC_MCB* p_mcb, uint8_t dlci, BT_HDR* p_buf) { } /* If user registered to receive notification when a particular byte is */ /* received we mast check all received bytes */ - if (((rx_char1 = p_port->user_port_pars.rx_char1) != 0) && (p_port->ev_mask & PORT_EV_RXFLAG)) { + if (((rx_char1 = p_port->user_port_settings.rx_char1) != 0) && + (p_port->ev_mask & PORT_EV_RXFLAG)) { for (i = 0, p = (uint8_t*)(p_buf + 1) + p_buf->offset; i < p_buf->len; i++) { if (*p++ == rx_char1) { events |= PORT_EV_RXFLAG; diff --git a/system/stack/rfcomm/port_utils.cc b/system/stack/rfcomm/port_utils.cc index 97f3dc84b58..7f64661eadd 100644 --- a/system/stack/rfcomm/port_utils.cc +++ b/system/stack/rfcomm/port_utils.cc @@ -41,7 +41,7 @@ using namespace bluetooth; -static const tPORT_STATE default_port_pars = { +static const PortSettings default_port_settings = { PORT_BAUD_RATE_9600, PORT_8_BITS, PORT_ONESTOPBIT, @@ -110,8 +110,8 @@ void port_set_defaults(tPORT* p_port) { p_port->rx_flag_ev_pending = false; p_port->peer_mtu = RFCOMM_DEFAULT_MTU; - p_port->user_port_pars = default_port_pars; - p_port->peer_port_pars = default_port_pars; + p_port->user_port_settings = default_port_settings; + p_port->peer_port_settings = default_port_settings; p_port->credit_tx = 0; p_port->credit_rx = 0; @@ -242,14 +242,14 @@ void port_release_port(tPORT* p_port) { /* save event mask and callback */ uint32_t mask = p_port->ev_mask; tPORT_CALLBACK* p_port_cb = p_port->p_callback; - tPORT_STATE user_port_pars = p_port->user_port_pars; + PortSettings user_port_settings = p_port->user_port_settings; port_set_defaults(p_port); /* restore */ p_port->ev_mask = mask; p_port->p_callback = p_port_cb; - p_port->user_port_pars = user_port_pars; + p_port->user_port_settings = user_port_settings; p_port->mtu = p_port->keep_mtu; p_port->state = PORT_CONNECTION_STATE_OPENING; diff --git a/system/stack/rfcomm/rfc_int.h b/system/stack/rfcomm/rfc_int.h index ddd38d5b4e6..b773ee2dc29 100644 --- a/system/stack/rfcomm/rfc_int.h +++ b/system/stack/rfcomm/rfc_int.h @@ -66,9 +66,10 @@ void RFCOMM_ParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, bool state); -void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars); -void RFCOMM_PortParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars, - uint16_t param_mask); +void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci, + PortSettings* p_settings); +void RFCOMM_PortParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci, + PortSettings* p_settings, uint16_t param_mask); void RFCOMM_ControlReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars); void RFCOMM_ControlRsp(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars); @@ -249,7 +250,7 @@ void rfc_send_pn(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, uint16_t mtu, u void rfc_send_test(tRFC_MCB* p_rfc_mcb, bool is_command, BT_HDR* p_buf); void rfc_send_msc(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, tPORT_CTRL* p_pars); void rfc_send_rls(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, uint8_t status); -void rfc_send_rpn(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, tPORT_STATE* p_pars, +void rfc_send_rpn(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, PortSettings* p_settings, uint16_t mask); void rfc_send_fcon(tRFC_MCB* p_mcb, bool is_command); void rfc_send_fcoff(tRFC_MCB* p_mcb, bool is_command); @@ -279,8 +280,8 @@ void PORT_ParNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl, uin void PORT_FlowInd(tRFC_MCB* p_mcb, uint8_t dlci, bool fc); -void PORT_PortNegInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars, uint16_t param_mask); -void PORT_PortNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars, uint16_t result); +void PORT_PortNegInd(tRFC_MCB* p_mcb, uint8_t dlci, PortSettings* p_settings, uint16_t param_mask); +void PORT_PortNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, PortSettings* p_settings, uint16_t result); void PORT_ControlInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars); void PORT_ControlCnf(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars); diff --git a/system/stack/rfcomm/rfc_port_fsm.cc b/system/stack/rfcomm/rfc_port_fsm.cc index f8bffa36cbf..6313abf0731 100644 --- a/system/stack/rfcomm/rfc_port_fsm.cc +++ b/system/stack/rfcomm/rfc_port_fsm.cc @@ -61,7 +61,7 @@ static void rfc_port_sm_disc_wait_ua(tPORT* p_port, tRFC_PORT_EVENT event, void* static void rfc_port_uplink_data(tPORT* p_port, BT_HDR* p_buf); -static void rfc_set_port_state(tPORT_STATE* port_pars, MX_FRAME* p_frame); +static void rfc_set_port_settings(PortSettings* port_settings, MX_FRAME* p_frame); /******************************************************************************* * @@ -672,33 +672,32 @@ void rfc_process_pn(tRFC_MCB* p_mcb, bool is_command, MX_FRAME* p_frame) { * ******************************************************************************/ void rfc_process_rpn(tRFC_MCB* p_mcb, bool is_command, bool is_request, MX_FRAME* p_frame) { - tPORT_STATE port_pars; + PortSettings port_settings = {}; tPORT* p_port; p_port = port_find_mcb_dlci_port(p_mcb, p_frame->dlci); if (p_port == nullptr) { /* This is the first command on the port */ if (is_command) { - memset(&port_pars, 0, sizeof(tPORT_STATE)); - rfc_set_port_state(&port_pars, p_frame); + rfc_set_port_settings(&port_settings, p_frame); - PORT_PortNegInd(p_mcb, p_frame->dlci, &port_pars, p_frame->u.rpn.param_mask); + PORT_PortNegInd(p_mcb, p_frame->dlci, &port_settings, p_frame->u.rpn.param_mask); } return; } if (is_command && is_request) { /* This is the special situation when peer just request local pars */ - rfc_send_rpn(p_mcb, p_frame->dlci, false, &p_port->peer_port_pars, 0); + rfc_send_rpn(p_mcb, p_frame->dlci, false, &p_port->peer_port_settings, 0); return; } - port_pars = p_port->peer_port_pars; + port_settings = p_port->peer_port_settings; - rfc_set_port_state(&port_pars, p_frame); + rfc_set_port_settings(&port_settings, p_frame); if (is_command) { - PORT_PortNegInd(p_mcb, p_frame->dlci, &port_pars, p_frame->u.rpn.param_mask); + PORT_PortNegInd(p_mcb, p_frame->dlci, &port_settings, p_frame->u.rpn.param_mask); return; } @@ -715,18 +714,18 @@ void rfc_process_rpn(tRFC_MCB* p_mcb, bool is_command, bool is_request, MX_FRAME if (p_port->rfc.expected_rsp & RFC_RSP_RPN_REPLY) { p_port->rfc.expected_rsp &= ~RFC_RSP_RPN_REPLY; - p_port->peer_port_pars = port_pars; + p_port->peer_port_settings = port_settings; - if ((port_pars.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT)) || - (port_pars.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT))) { + if ((port_settings.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT)) || + (port_settings.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT))) { /* This is satisfactory port parameters. Set mask as it was Ok */ p_frame->u.rpn.param_mask = RFCOMM_RPN_PM_MASK; } else { /* Current peer parameters are not good, try to fix them */ - p_port->peer_port_pars.fc_type = (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT); + p_port->peer_port_settings.fc_type = (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT); p_port->rfc.expected_rsp |= RFC_RSP_RPN; - rfc_send_rpn(p_mcb, p_frame->dlci, true, &p_port->peer_port_pars, + rfc_send_rpn(p_mcb, p_frame->dlci, true, &p_port->peer_port_settings, RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT); rfc_port_timer_start(p_port, RFC_T2_TIMEOUT); return; @@ -740,29 +739,29 @@ void rfc_process_rpn(tRFC_MCB* p_mcb, bool is_command, bool is_request, MX_FRAME (RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT)) || ((p_frame->u.rpn.param_mask & (RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT)) == (RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT))) { - PORT_PortNegCnf(p_mcb, p_port->dlci, &port_pars, RFCOMM_SUCCESS); + PORT_PortNegCnf(p_mcb, p_port->dlci, &port_settings, RFCOMM_SUCCESS); return; } /* If we were proposing RTR flow control try RTC flow control */ /* If we were proposing RTC flow control try no flow control */ /* otherwise drop the connection */ - if (p_port->peer_port_pars.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT)) { + if (p_port->peer_port_settings.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT)) { /* Current peer parameters are not good, try to fix them */ - p_port->peer_port_pars.fc_type = (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT); + p_port->peer_port_settings.fc_type = (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT); p_port->rfc.expected_rsp |= RFC_RSP_RPN; - rfc_send_rpn(p_mcb, p_frame->dlci, true, &p_port->peer_port_pars, + rfc_send_rpn(p_mcb, p_frame->dlci, true, &p_port->peer_port_settings, RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT); rfc_port_timer_start(p_port, RFC_T2_TIMEOUT); return; } /* Other side does not support flow control */ - if (p_port->peer_port_pars.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT)) { - p_port->peer_port_pars.fc_type = RFCOMM_FC_OFF; - PORT_PortNegCnf(p_mcb, p_port->dlci, &port_pars, RFCOMM_SUCCESS); + if (p_port->peer_port_settings.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT)) { + p_port->peer_port_settings.fc_type = RFCOMM_FC_OFF; + PORT_PortNegCnf(p_mcb, p_port->dlci, &port_settings, RFCOMM_SUCCESS); } } @@ -947,39 +946,39 @@ void rfc_process_l2cap_congestion(tRFC_MCB* p_mcb, bool is_congested) { /******************************************************************************* * - * Function rfc_set_port_pars + * Function rfc_set_port_settings * - * Description This function sets the tPORT_STATE structure given a + * Description This function sets the PortSettings structure given a * p_frame. * ******************************************************************************/ -void rfc_set_port_state(tPORT_STATE* port_pars, MX_FRAME* p_frame) { +void rfc_set_port_settings(PortSettings* port_settings, MX_FRAME* p_frame) { if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_BIT_RATE) { - port_pars->baud_rate = p_frame->u.rpn.baud_rate; + port_settings->baud_rate = p_frame->u.rpn.baud_rate; } if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_DATA_BITS) { - port_pars->byte_size = p_frame->u.rpn.byte_size; + port_settings->byte_size = p_frame->u.rpn.byte_size; } if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_STOP_BITS) { - port_pars->stop_bits = p_frame->u.rpn.stop_bits; + port_settings->stop_bits = p_frame->u.rpn.stop_bits; } if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_PARITY) { - port_pars->parity = p_frame->u.rpn.parity; + port_settings->parity = p_frame->u.rpn.parity; } if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_PARITY_TYPE) { - port_pars->parity_type = p_frame->u.rpn.parity_type; + port_settings->parity_type = p_frame->u.rpn.parity_type; } if (p_frame->u.rpn.param_mask & (RFCOMM_RPN_PM_XONXOFF_ON_INPUT | RFCOMM_RPN_PM_XONXOFF_ON_OUTPUT | RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT | RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT)) { - port_pars->fc_type = p_frame->u.rpn.fc_type; + port_settings->fc_type = p_frame->u.rpn.fc_type; } if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_XON_CHAR) { - port_pars->xon_char = p_frame->u.rpn.xon_char; + port_settings->xon_char = p_frame->u.rpn.xon_char; } if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_XOFF_CHAR) { - port_pars->xoff_char = p_frame->u.rpn.xoff_char; + port_settings->xoff_char = p_frame->u.rpn.xoff_char; } } diff --git a/system/stack/rfcomm/rfc_port_if.cc b/system/stack/rfcomm/rfc_port_if.cc index 0a124d62a82..c6c37cc11cf 100644 --- a/system/stack/rfcomm/rfc_port_if.cc +++ b/system/stack/rfcomm/rfc_port_if.cc @@ -193,7 +193,8 @@ void RFCOMM_ParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t * control block. * ******************************************************************************/ -void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars) { +void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci, + PortSettings* p_settings) { if (p_mcb->state != RFC_MX_STATE_CONNECTED) { PORT_PortNegCnf(p_mcb, dlci, nullptr, RFCOMM_ERROR); return; @@ -206,13 +207,13 @@ void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci, tPORT } /* Send Parameter Negotiation Command UIH frame */ - if (!p_pars) { + if (!p_settings) { p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY; } else { p_port->rfc.expected_rsp |= RFC_RSP_RPN; } - rfc_send_rpn(p_mcb, dlci, true, p_pars, RFCOMM_RPN_PM_MASK); + rfc_send_rpn(p_mcb, dlci, true, p_settings, RFCOMM_RPN_PM_MASK); rfc_port_timer_start(p_port, RFC_T2_TIMEOUT); } @@ -224,13 +225,13 @@ void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci, tPORT * Port parameters negotiation. * ******************************************************************************/ -void RFCOMM_PortParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars, - uint16_t param_mask) { +void RFCOMM_PortParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci, + PortSettings* p_settings, uint16_t param_mask) { if (p_mcb->state != RFC_MX_STATE_CONNECTED) { return; } - rfc_send_rpn(p_mcb, dlci, false, p_pars, param_mask); + rfc_send_rpn(p_mcb, dlci, false, p_settings, param_mask); } /******************************************************************************* diff --git a/system/stack/rfcomm/rfc_ts_frames.cc b/system/stack/rfcomm/rfc_ts_frames.cc index 93bf02a0a42..ea57abf6dc2 100644 --- a/system/stack/rfcomm/rfc_ts_frames.cc +++ b/system/stack/rfcomm/rfc_ts_frames.cc @@ -404,7 +404,7 @@ void rfc_send_nsc(tRFC_MCB* p_mcb) { * Description This function sends Remote Port Negotiation Command * ******************************************************************************/ -void rfc_send_rpn(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, tPORT_STATE* p_pars, +void rfc_send_rpn(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, PortSettings* p_settings, uint16_t mask) { uint8_t* p_data; BT_HDR* p_buf = (BT_HDR*)osi_malloc(RFCOMM_CMD_BUF_SIZE); @@ -414,7 +414,7 @@ void rfc_send_rpn(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, tPORT_STATE* p *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_RPN; - if (!p_pars) { + if (!p_settings) { *p_data++ = RFCOMM_EA | (RFCOMM_MX_RPN_REQ_LEN << 1); *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI); @@ -424,14 +424,14 @@ void rfc_send_rpn(tRFC_MCB* p_mcb, uint8_t dlci, bool is_command, tPORT_STATE* p *p_data++ = RFCOMM_EA | (RFCOMM_MX_RPN_LEN << 1); *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI); - *p_data++ = p_pars->baud_rate; - *p_data++ = (p_pars->byte_size << RFCOMM_RPN_BITS_SHIFT) | - (p_pars->stop_bits << RFCOMM_RPN_STOP_BITS_SHIFT) | - (p_pars->parity << RFCOMM_RPN_PARITY_SHIFT) | - (p_pars->parity_type << RFCOMM_RPN_PARITY_TYPE_SHIFT); - *p_data++ = p_pars->fc_type; - *p_data++ = p_pars->xon_char; - *p_data++ = p_pars->xoff_char; + *p_data++ = p_settings->baud_rate; + *p_data++ = (p_settings->byte_size << RFCOMM_RPN_BITS_SHIFT) | + (p_settings->stop_bits << RFCOMM_RPN_STOP_BITS_SHIFT) | + (p_settings->parity << RFCOMM_RPN_PARITY_SHIFT) | + (p_settings->parity_type << RFCOMM_RPN_PARITY_TYPE_SHIFT); + *p_data++ = p_settings->fc_type; + *p_data++ = p_settings->xon_char; + *p_data++ = p_settings->xoff_char; *p_data++ = (mask & 0xFF); *p_data++ = (mask >> 8); diff --git a/system/test/mock/mock_stack_rfcomm_port_api.cc b/system/test/mock/mock_stack_rfcomm_port_api.cc index 922e27743da..e3dffbbf48f 100644 --- a/system/test/mock/mock_stack_rfcomm_port_api.cc +++ b/system/test/mock/mock_stack_rfcomm_port_api.cc @@ -43,7 +43,7 @@ int PORT_FlowControl_MaxCredit(uint16_t /* handle */, bool /* enable */) { inc_func_call_count(__func__); return 0; } -int PORT_GetState(uint16_t /* handle */, tPORT_STATE* /* p_settings */) { +int PORT_GetSettings(uint16_t /* handle */, PortSettings* /* p_settings */) { inc_func_call_count(__func__); return 0; } @@ -61,7 +61,7 @@ int PORT_SetEventMaskAndCallback(uint16_t /* port_handle */, uint32_t /* mask */ inc_func_call_count(__func__); return 0; } -int PORT_SetState(uint16_t /* handle */, tPORT_STATE* /* p_settings */) { +int PORT_SetSettings(uint16_t /* handle */, PortSettings* /* p_settings */) { inc_func_call_count(__func__); return 0; } -- GitLab From 1a5e5a6150fc7853de868c7327ac91c89814ce56 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Tue, 8 Oct 2024 20:34:59 +0000 Subject: [PATCH 214/875] Fix stopVoiceRecognition logging typo Bug: 330220655 Change-Id: Id740d065b231a4ee9abd9e6b9d7aae5a89346592 Flag: exempt, logging change Test: m p/m/Bluetooth --- android/app/src/com/android/bluetooth/hfp/HeadsetService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index 26b83a1892a..7e89394ee36 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -1196,7 +1196,7 @@ public class HeadsetService extends ProfileService { if (!Objects.equals(mActiveDevice, device)) { Log.w( TAG, - "startVoiceRecognition: requested device " + "stopVoiceRecognition: requested device " + device + " is not active, use active device " + mActiveDevice -- GitLab From 5a096122ebcd9c38f5fa4e2a05c33bde5afec8c8 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 24 Sep 2024 20:18:59 +0000 Subject: [PATCH 215/875] Supports start CS distance measurement from peripheral Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 350777645 Test: m com.android.btservices Change-Id: Ica050eb7b9adc3f1c85eb104f60a7091726390c0 --- system/bta/include/bta_ras_api.h | 2 + system/bta/ras/ras_server.cc | 24 ++++- system/gd/hci/distance_measurement_manager.cc | 99 +++++++++++++++---- system/gd/hci/distance_measurement_manager.h | 11 ++- .../main/shim/distance_measurement_manager.cc | 46 ++++++--- 5 files changed, 143 insertions(+), 39 deletions(-) diff --git a/system/bta/include/bta_ras_api.h b/system/bta/include/bta_ras_api.h index e18da6e9d92..23457094faa 100644 --- a/system/bta/include/bta_ras_api.h +++ b/system/bta/include/bta_ras_api.h @@ -37,6 +37,8 @@ public: virtual void OnVendorSpecificReply( const RawAddress& address, const std::vector& vendor_specific_reply) = 0; + virtual void OnRasServerConnected(const RawAddress& identity_address) = 0; + virtual void OnRasServerDisconnected(const RawAddress& identity_address) = 0; }; class RasServer { diff --git a/system/bta/ras/ras_server.cc b/system/bta/ras/ras_server.cc index 0152fe9506d..4419dc3e961 100644 --- a/system/bta/ras/ras_server.cc +++ b/system/bta/ras/ras_server.cc @@ -221,16 +221,32 @@ public: log::warn("Create new tracker"); } trackers_[address].conn_id_ = p_data->conn.conn_id; + + RawAddress identity_address = p_data->conn.remote_bda; + tBLE_ADDR_TYPE address_type = BLE_ADDR_PUBLIC_ID; + btm_random_pseudo_to_identity_addr(&identity_address, &address_type); + // TODO: optimize, remove this event, initialize the tracker within the GD on demand. + callbacks_->OnRasServerConnected(identity_address); } void OnGattDisconnect(tBTA_GATTS* p_data) { - auto address = p_data->conn.remote_bda; - log::info("Address: {}, conn_id:{}", address, p_data->conn.conn_id); - if (trackers_.find(address) != trackers_.end()) { - trackers_.erase(address); + auto remote_bda = p_data->conn.remote_bda; + log::info("Address: {}, conn_id:{}", remote_bda, p_data->conn.conn_id); + if (trackers_.find(remote_bda) != trackers_.end()) { + NotifyRasServerDisconnected(remote_bda); + trackers_.erase(remote_bda); } } + void NotifyRasServerDisconnected(const RawAddress& remote_bda) { + tBLE_BD_ADDR ble_identity_bd_addr; + ble_identity_bd_addr.bda = remote_bda; + ble_identity_bd_addr.type = BLE_ADDR_RANDOM; + btm_random_pseudo_to_identity_addr(&ble_identity_bd_addr.bda, &ble_identity_bd_addr.type); + + callbacks_->OnRasServerDisconnected(ble_identity_bd_addr.bda); + } + void OnGattServerRegister(tBTA_GATTS* p_data) { tGATT_STATUS status = p_data->reg_oper.status; log::info("status: {}", gatt_status_text(p_data->reg_oper.status)); diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index f1709f5683a..4556cde53ca 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -141,6 +141,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { struct CsTracker { Address address; + hci::Role local_hci_role; uint16_t local_counter; uint16_t remote_counter; CsRole role; @@ -253,7 +254,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } void start_distance_measurement(const Address address, uint16_t connection_handle, - uint16_t interval, DistanceMeasurementMethod method) { + hci::Role local_hci_role, uint16_t interval, + DistanceMeasurementMethod method) { log::info("Address:{}, method:{}", address, method); // Remove this check if we support any connection less method @@ -282,14 +284,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } break; case METHOD_CS: { - init_cs_tracker(address, connection_handle, interval); + init_cs_tracker(address, connection_handle, local_hci_role, interval); start_distance_measurement_with_cs(address, connection_handle); } break; } } void init_cs_tracker(const Address& cs_remote_address, uint16_t connection_handle, - uint16_t interval) { + hci::Role local_hci_role, uint16_t interval) { if (cs_trackers_.find(connection_handle) != cs_trackers_.end() && cs_trackers_[connection_handle].address != cs_remote_address) { log::debug("Remove old tracker for {}", cs_remote_address); @@ -307,6 +309,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { cs_trackers_[connection_handle].local_start = true; cs_trackers_[connection_handle].measurement_ongoing = true; cs_trackers_[connection_handle].waiting_for_start_callback = true; + cs_trackers_[connection_handle].local_hci_role = local_hci_role; } void start_distance_measurement_with_cs(const Address& cs_remote_address, @@ -374,7 +377,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } - void handle_ras_connected_event( + void handle_ras_client_connected_event( const Address address, uint16_t connection_handle, uint16_t att_handle, const std::vector vendor_specific_data) { log::info( @@ -400,7 +403,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { start_distance_measurement_with_cs(tracker.address, connection_handle); } - void handle_ras_disconnected_event(const Address address) { + void handle_ras_client_disconnected_event(const Address address) { log::info("address:{}", address); for (auto it = cs_trackers_.begin(); it != cs_trackers_.end();) { if (it->second.address == address) { @@ -417,16 +420,61 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } - void handle_vendor_specific_reply( - const Address address, uint16_t connection_handle, + void handle_ras_server_vendor_specific_reply( + const Address& address, uint16_t connection_handle, const std::vector vendor_specific_reply) { - cs_trackers_[connection_handle].address = address; + if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + log::info("no cs tracker found for {}", connection_handle); + return; + } + if (cs_trackers_[connection_handle].address != address) { + log::info("the cs tracker address was changed as {}, not {}.", + cs_trackers_[connection_handle].address, address); + return; + } if (ranging_hal_->IsBound()) { ranging_hal_->HandleVendorSpecificReply(connection_handle, vendor_specific_reply); return; } } + void handle_ras_server_connected(const Address& identity_address, uint16_t connection_handle, + hci::Role local_hci_role) { + log::info("initialize the cs tracker for {}", connection_handle); + // create CS tracker to serve the ras_server + if (cs_trackers_.find(connection_handle) != cs_trackers_.end()) { + if (cs_trackers_[connection_handle].local_start && + cs_trackers_[connection_handle].measurement_ongoing) { + log::info("cs tracker for {} is being used for measurement.", identity_address); + return; + } + } + if (cs_trackers_[connection_handle].address != identity_address) { + log::debug("Remove old tracker for {}", identity_address); + cs_trackers_.erase(connection_handle); + } + + cs_trackers_[connection_handle].address = identity_address; + cs_trackers_[connection_handle].local_start = false; + cs_trackers_[connection_handle].local_hci_role = local_hci_role; + } + + void handle_ras_server_disconnected(const Address& identity_address, uint16_t connection_handle) { + if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + log::info("no CS tracker available."); + return; + } + if (cs_trackers_[connection_handle].address != identity_address) { + log::info("cs tracker connection is associated with device {}, not device {}", + cs_trackers_[connection_handle].address, identity_address); + return; + } + if (!cs_trackers_[connection_handle].local_start) { + log::info("erase cs tracker for {}, as ras server is disconnected.", connection_handle); + cs_trackers_.erase(connection_handle); + } + } + void handle_vendor_specific_reply_complete(const Address address, uint16_t connection_handle, bool success) { log::info("address:{}, connection_handle:0x{:04x}, success:{}", address, connection_handle, @@ -627,11 +675,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } send_le_cs_set_default_settings(event_view.GetConnectionHandle()); if (cs_trackers_.find(connection_handle) != cs_trackers_.end() && - cs_trackers_[connection_handle].local_start) { + cs_trackers_[connection_handle].local_hci_role == hci::Role::CENTRAL) { + // send the cmd from the BLE central only. send_le_cs_security_enable(connection_handle); - } else { - // TODO(b/361567359): problematic? HACK_ may not get the identity address for sure. - cs_trackers_[connection_handle].address = acl_manager_->HACK_GetLeAddress(connection_handle); } if (event_view.GetOptionalSubfeaturesSupported().phase_based_ranging_ == 0x01) { @@ -1534,10 +1580,11 @@ void DistanceMeasurementManager::RegisterDistanceMeasurementCallbacks( void DistanceMeasurementManager::StartDistanceMeasurement(const Address& address, uint16_t connection_handle, + hci::Role local_hci_role, uint16_t interval, DistanceMeasurementMethod method) { - CallOn(pimpl_.get(), &impl::start_distance_measurement, address, connection_handle, interval, - method); + CallOn(pimpl_.get(), &impl::start_distance_measurement, address, connection_handle, + local_hci_role, interval, method); } void DistanceMeasurementManager::StopDistanceMeasurement(const Address& address, @@ -1546,24 +1593,36 @@ void DistanceMeasurementManager::StopDistanceMeasurement(const Address& address, CallOn(pimpl_.get(), &impl::stop_distance_measurement, address, connection_handle, method); } -void DistanceMeasurementManager::HandleRasConnectedEvent( +void DistanceMeasurementManager::HandleRasClientConnectedEvent( const Address& address, uint16_t connection_handle, uint16_t att_handle, const std::vector& vendor_specific_data) { - CallOn(pimpl_.get(), &impl::handle_ras_connected_event, address, connection_handle, att_handle, - vendor_specific_data); + CallOn(pimpl_.get(), &impl::handle_ras_client_connected_event, address, connection_handle, + att_handle, vendor_specific_data); } -void DistanceMeasurementManager::HandleRasDisconnectedEvent(const Address& address) { - CallOn(pimpl_.get(), &impl::handle_ras_disconnected_event, address); +void DistanceMeasurementManager::HandleRasClientDisconnectedEvent(const Address& address) { + CallOn(pimpl_.get(), &impl::handle_ras_client_disconnected_event, address); } void DistanceMeasurementManager::HandleVendorSpecificReply( const Address& address, uint16_t connection_handle, const std::vector& vendor_specific_reply) { - CallOn(pimpl_.get(), &impl::handle_vendor_specific_reply, address, connection_handle, + CallOn(pimpl_.get(), &impl::handle_ras_server_vendor_specific_reply, address, connection_handle, vendor_specific_reply); } +void DistanceMeasurementManager::HandleRasServerConnected(const Address& identity_address, + uint16_t connection_handle, + hci::Role local_hci_role) { + CallOn(pimpl_.get(), &impl::handle_ras_server_connected, identity_address, connection_handle, + local_hci_role); +} + +void DistanceMeasurementManager::HandleRasServerDisconnected( + const bluetooth::hci::Address& identity_address, uint16_t connection_handle) { + CallOn(pimpl_.get(), &impl::handle_ras_server_disconnected, identity_address, connection_handle); +} + void DistanceMeasurementManager::HandleVendorSpecificReplyComplete(const Address& address, uint16_t connection_handle, bool success) { diff --git a/system/gd/hci/distance_measurement_manager.h b/system/gd/hci/distance_measurement_manager.h index ee7ba9ee0e2..3732599ec36 100644 --- a/system/gd/hci/distance_measurement_manager.h +++ b/system/gd/hci/distance_measurement_manager.h @@ -19,6 +19,7 @@ #include "address.h" #include "hal/ranging_hal.h" +#include "hci/hci_packets.h" #include "module.h" namespace bluetooth { @@ -79,17 +80,21 @@ public: DistanceMeasurementManager& operator=(const DistanceMeasurementManager&) = delete; void RegisterDistanceMeasurementCallbacks(DistanceMeasurementCallbacks* callbacks); - void StartDistanceMeasurement(const Address&, uint16_t connection_handle, uint16_t interval, + void StartDistanceMeasurement(const Address&, uint16_t connection_handle, + hci::Role local_hci_role, uint16_t interval, DistanceMeasurementMethod method); void StopDistanceMeasurement(const Address& address, uint16_t connection_handle, DistanceMeasurementMethod method); - void HandleRasConnectedEvent( + void HandleRasClientConnectedEvent( const Address& address, uint16_t connection_handle, uint16_t att_handle, const std::vector& vendor_specific_data); - void HandleRasDisconnectedEvent(const Address& address); + void HandleRasClientDisconnectedEvent(const Address& address); void HandleVendorSpecificReply( const Address& address, uint16_t connection_handle, const std::vector& vendor_specific_reply); + void HandleRasServerConnected(const Address& identity_address, uint16_t connection_handle, + hci::Role local_hci_role); + void HandleRasServerDisconnected(const Address& identity_address, uint16_t connection_handle); void HandleVendorSpecificReplyComplete(const Address& address, uint16_t connection_handle, bool success); void HandleRemoteData(const Address& address, uint16_t connection_handle, diff --git a/system/main/shim/distance_measurement_manager.cc b/system/main/shim/distance_measurement_manager.cc index 22b540c3c52..da81b820d09 100644 --- a/system/main/shim/distance_measurement_manager.cc +++ b/system/main/shim/distance_measurement_manager.cc @@ -19,6 +19,7 @@ #include "bta/include/bta_ras_api.h" #include "btif/include/btif_common.h" #include "hci/distance_measurement_manager.h" +#include "hci/hci_packets.h" #include "main/shim/entry.h" #include "main/shim/helpers.h" #include "stack/include/acl_api.h" @@ -49,9 +50,12 @@ public: * @param bd_addr could be random, rpa or identity address. * @return BLE ACL handle */ - uint16_t GetConnectionHandle(const RawAddress& bd_addr) { + uint16_t GetConnectionHandleAndRole(const RawAddress& bd_addr, hci::Role* hci_role = nullptr) { tBTM_SEC_DEV_REC* p_sec_dev_rec = btm_find_dev(bd_addr); if (p_sec_dev_rec != nullptr) { + if (hci_role != nullptr) { + *hci_role = p_sec_dev_rec->role_central ? hci::Role::CENTRAL : hci::Role::PERIPHERAL; + } return p_sec_dev_rec->get_ble_hci_handle(); } return kIllegalConnectionHandle; @@ -69,8 +73,10 @@ public: void DoStartDistanceMeasurement(RawAddress identity_addr, uint16_t interval, uint8_t method) { DistanceMeasurementMethod distance_measurement_method = static_cast(method); + hci::Role local_hci_role; + uint16_t connection_handle = GetConnectionHandleAndRole(identity_addr, &local_hci_role); bluetooth::shim::GetDistanceMeasurementManager()->StartDistanceMeasurement( - bluetooth::ToGdAddress(identity_addr), GetConnectionHandle(identity_addr), interval, + bluetooth::ToGdAddress(identity_addr), connection_handle, local_hci_role, interval, distance_measurement_method); if (distance_measurement_method == DistanceMeasurementMethod::METHOD_CS) { bluetooth::ras::GetRasClient()->Connect(identity_addr); @@ -84,7 +90,7 @@ public: void DoStopDistanceMeasurement(RawAddress identity_addr, uint8_t method) { bluetooth::shim::GetDistanceMeasurementManager()->StopDistanceMeasurement( - bluetooth::ToGdAddress(identity_addr), GetConnectionHandle(identity_addr), + bluetooth::ToGdAddress(identity_addr), GetConnectionHandleAndRole(identity_addr), static_cast(method)); } @@ -169,9 +175,9 @@ public: // Must be called from main_thread // Callbacks of bluetooth::ras::RasServerCallbacks - void OnVendorSpecificReply( - const RawAddress& address, - const std::vector& vendor_specific_reply) { + void OnVendorSpecificReply(const RawAddress& address, + const std::vector& + vendor_specific_reply) override { std::vector hal_vendor_specific_characteristics; for (auto& characteristic : vendor_specific_reply) { bluetooth::hal::VendorSpecificCharacteristic vendor_specific_characteristic; @@ -181,10 +187,26 @@ public: hal_vendor_specific_characteristics.emplace_back(vendor_specific_characteristic); } bluetooth::shim::GetDistanceMeasurementManager()->HandleVendorSpecificReply( - bluetooth::ToGdAddress(address), GetConnectionHandle(address), + bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address), hal_vendor_specific_characteristics); } + // Must be called from main_thread + // Callbacks of bluetooth::ras::RasServerCallbacks + void OnRasServerConnected(const RawAddress& identity_address) override { + hci::Role local_hci_role; + uint16_t connection_handle = GetConnectionHandleAndRole(identity_address, &local_hci_role); + bluetooth::shim::GetDistanceMeasurementManager()->HandleRasServerConnected( + bluetooth::ToGdAddress(identity_address), connection_handle, local_hci_role); + } + + // Must be called from main_thread + // Callbacks of bluetooth::ras::RasSeverCallbacks + void OnRasServerDisconnected(const RawAddress& identity_address) override { + bluetooth::shim::GetDistanceMeasurementManager()->HandleRasServerDisconnected( + bluetooth::ToGdAddress(identity_address), GetConnectionHandleAndRole(identity_address)); + } + // Must be called from main_thread // Callbacks of bluetooth::ras::RasClientCallbacks void OnConnected(const RawAddress& address, uint16_t att_handle, @@ -199,26 +221,26 @@ public: hal_vendor_specific_characteristics.emplace_back(vendor_specific_characteristic); } - bluetooth::shim::GetDistanceMeasurementManager()->HandleRasConnectedEvent( - bluetooth::ToGdAddress(address), GetConnectionHandle(address), att_handle, + bluetooth::shim::GetDistanceMeasurementManager()->HandleRasClientConnectedEvent( + bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address), att_handle, hal_vendor_specific_characteristics); } void OnDisconnected(const RawAddress& address) { - bluetooth::shim::GetDistanceMeasurementManager()->HandleRasDisconnectedEvent( + bluetooth::shim::GetDistanceMeasurementManager()->HandleRasClientDisconnectedEvent( bluetooth::ToGdAddress(address)); } // Must be called from main_thread void OnWriteVendorSpecificReplyComplete(const RawAddress& address, bool success) { bluetooth::shim::GetDistanceMeasurementManager()->HandleVendorSpecificReplyComplete( - bluetooth::ToGdAddress(address), GetConnectionHandle(address), success); + bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address), success); } // Must be called from main_thread void OnRemoteData(const RawAddress& address, const std::vector& data) { bluetooth::shim::GetDistanceMeasurementManager()->HandleRemoteData( - bluetooth::ToGdAddress(address), GetConnectionHandle(address), data); + bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address), data); } private: -- GitLab From cce49d0225fb805c47dd94f4914072f27e6cea46 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 8 Oct 2024 12:08:15 +0200 Subject: [PATCH 216/875] use shim api directly Get rid of pass-through methods: BTM_AcceptlistAddDirect BTM_AcceptlistRemove BTM_AcceptlistClear Move btm_update_scanner_filter_policy to only place where it's used. Test: mma -j32; Bug: 372202918 Flag: exempt, removing intermidiate layer, no logical change Change-Id: I8c4a02875c7c28fc176644d45bebf0c29a2aafa2 --- system/stack/Android.bp | 5 +- system/stack/BUILD.gn | 1 - system/stack/btm/btm_ble_bgconn.cc | 133 ------------------ system/stack/btm/btm_ble_bgconn.h | 34 ----- system/stack/btm/btm_ble_gap.cc | 29 ++++ system/stack/btm/btm_ble_int.h | 3 - system/stack/btm/btm_dev.cc | 8 +- system/stack/gatt/connection_manager.cc | 26 ++-- system/stack/gatt/gatt_main.cc | 2 +- system/stack/gatt/gatt_utils.cc | 4 +- system/stack/include/btm_ble_api.h | 2 - .../test/gatt_connection_manager_test.cc | 47 ++++--- system/test/mock/mock_stack_btm_ble_bgconn.cc | 83 ----------- system/test/mock/mock_stack_btm_ble_bgconn.h | 98 ------------- .../mock_stack_gatt_connection_manager.cc | 1 - 15 files changed, 79 insertions(+), 397 deletions(-) delete mode 100644 system/stack/btm/btm_ble_bgconn.cc delete mode 100644 system/stack/btm/btm_ble_bgconn.h delete mode 100644 system/test/mock/mock_stack_btm_ble_bgconn.cc delete mode 100644 system/test/mock/mock_stack_btm_ble_bgconn.h diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 20f12e4c23e..ed20eaf8d06 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -255,7 +255,6 @@ cc_library_static { "btm/btm_ble.cc", "btm/btm_ble_addr.cc", "btm/btm_ble_adv_filter.cc", - "btm/btm_ble_bgconn.cc", "btm/btm_ble_cont_energy.cc", "btm/btm_ble_gap.cc", "btm/btm_ble_privacy.cc", @@ -1139,6 +1138,7 @@ cc_test { ], srcs: [ ":TestCommonMockFunctions", + ":TestMockMainShim", ":TestMockRustFfi", ":TestMockStackArbiter", ":TestMockStackBtm", @@ -1163,6 +1163,7 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libbt-common", + "libbt-platform-protos-lite", "libchrome", "libevent", "libgmock", @@ -1433,6 +1434,7 @@ cc_test { ":TestMockBta", ":TestMockBtif", ":TestMockDevice", + ":TestMockMainShim", ":TestMockRustFfi", ":TestMockStackBtm", ":TestMockStackL2cap", @@ -1678,7 +1680,6 @@ cc_test { "btm/btm_ble.cc", "btm/btm_ble_addr.cc", "btm/btm_ble_adv_filter.cc", - "btm/btm_ble_bgconn.cc", "btm/btm_ble_cont_energy.cc", "btm/btm_ble_gap.cc", "btm/btm_ble_privacy.cc", diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn index cc966337c4a..c2b87b44a55 100644 --- a/system/stack/BUILD.gn +++ b/system/stack/BUILD.gn @@ -95,7 +95,6 @@ source_set("stack") { "btm/btm_ble.cc", "btm/btm_ble_addr.cc", "btm/btm_ble_adv_filter.cc", - "btm/btm_ble_bgconn.cc", "btm/btm_ble_cont_energy.cc", "btm/btm_ble_gap.cc", "btm/btm_ble_privacy.cc", diff --git a/system/stack/btm/btm_ble_bgconn.cc b/system/stack/btm/btm_ble_bgconn.cc deleted file mode 100644 index 64625291fef..00000000000 --- a/system/stack/btm/btm_ble_bgconn.cc +++ /dev/null @@ -1,133 +0,0 @@ -/****************************************************************************** - * - * Copyright 1999-2012 Broadcom Corporation - * - * 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. - * - ******************************************************************************/ - -/****************************************************************************** - * - * This file contains functions for BLE acceptlist operation. - * - ******************************************************************************/ - -#define LOG_TAG "ble_bgconn" - -#include "stack/btm/btm_ble_bgconn.h" - -#include - -#include -#include - -#include "hci/controller_interface.h" -#include "main/shim/acl_api.h" -#include "main/shim/entry.h" -#include "os/log.h" -#include "stack/btm/btm_ble_int.h" -#include "stack/btm/btm_dev.h" -#include "stack/btm/btm_int_types.h" -#include "types/raw_address.h" - -using namespace bluetooth; - -extern tBTM_CB btm_cb; - -// Unfortunately (for now?) we have to maintain a copy of the device acceptlist -// on the host to determine if a device is pending to be connected or not. This -// controls whether the host should keep trying to scan for acceptlisted -// peripherals or not. -// TODO: Move all of this to controller/le/background_list or similar? -struct BackgroundConnection { - RawAddress address; - uint8_t addr_type; - bool in_controller_wl; - uint8_t addr_type_in_wl; - bool pending_removal; -}; - -struct BgConnHash { - std::size_t operator()(const RawAddress& x) const { - const uint8_t* a = x.address; - return a[0] ^ (a[1] << 8) ^ (a[2] << 16) ^ (a[3] << 24) ^ a[4] ^ (a[5] << 8); - } -}; - -static std::unordered_map background_connections; - -/******************************************************************************* - * - * Function btm_update_scanner_filter_policy - * - * Description This function updates the filter policy of scanner - ******************************************************************************/ -void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) { - uint32_t scan_interval = !btm_cb.ble_ctr_cb.inq_var.scan_interval - ? BTM_BLE_GAP_DISC_SCAN_INT - : btm_cb.ble_ctr_cb.inq_var.scan_interval; - uint32_t scan_window = !btm_cb.ble_ctr_cb.inq_var.scan_window - ? BTM_BLE_GAP_DISC_SCAN_WIN - : btm_cb.ble_ctr_cb.inq_var.scan_window; - uint8_t scan_phy = !btm_cb.ble_ctr_cb.inq_var.scan_phy ? BTM_BLE_DEFAULT_PHYS - : btm_cb.ble_ctr_cb.inq_var.scan_phy; - - log::verbose(""); - - btm_cb.ble_ctr_cb.inq_var.sfp = scan_policy; - btm_cb.ble_ctr_cb.inq_var.scan_type = - btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_NONE - ? BTM_BLE_SCAN_MODE_ACTI - : btm_cb.ble_ctr_cb.inq_var.scan_type; - - btm_send_hci_set_scan_params(btm_cb.ble_ctr_cb.inq_var.scan_type, (uint16_t)scan_interval, - (uint16_t)scan_window, (uint8_t)scan_phy, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, scan_policy); -} - -/** Adds the device into acceptlist. Returns false if acceptlist is full and - * device can't be added, true otherwise. */ -bool BTM_AcceptlistAdd(const RawAddress& address) { return BTM_AcceptlistAdd(address, false); } - -/** Adds the device into acceptlist and indicates whether to using direct - * connect parameters. Returns false if acceptlist is full and device can't - * be added, true otherwise. */ -bool BTM_AcceptlistAdd(const RawAddress& address, bool is_direct) { - if (!bluetooth::shim::GetController()->SupportsBle()) { - log::warn("Controller does not support Le"); - return false; - } - - return bluetooth::shim::ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), - is_direct); -} - -/** Removes the device from acceptlist */ -void BTM_AcceptlistRemove(const RawAddress& address) { - if (!bluetooth::shim::GetController()->SupportsBle()) { - log::warn("Controller does not support Le"); - return; - } - - bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address)); - return; -} - -/** Clear the acceptlist, end any pending acceptlist connections */ -void BTM_AcceptlistClear() { - if (!bluetooth::shim::GetController()->SupportsBle()) { - log::warn("Controller does not support Le"); - return; - } - bluetooth::shim::ACL_IgnoreAllLeConnections(); -} diff --git a/system/stack/btm/btm_ble_bgconn.h b/system/stack/btm/btm_ble_bgconn.h deleted file mode 100644 index 2f2303f5c6f..00000000000 --- a/system/stack/btm/btm_ble_bgconn.h +++ /dev/null @@ -1,34 +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. - * - ******************************************************************************/ - -#include "types/raw_address.h" - -/** Adds the device into acceptlist. Returns false if acceptlist is full and - * device can't be added, true otherwise. */ -bool BTM_AcceptlistAdd(const RawAddress& address); - -/** Adds the device into acceptlist and indicates whether to using direct - * connect parameters. Returns false if acceptlist is full and device can't - * be added, true otherwise. */ -bool BTM_AcceptlistAdd(const RawAddress& address, bool is_direct); - -/** Removes the device from acceptlist */ -void BTM_AcceptlistRemove(const RawAddress& address); - -/** Clear the acceptlist, end any pending acceptlist connections */ -void BTM_AcceptlistClear(); diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc index bd92d9121dd..fb0a6c1cedf 100644 --- a/system/stack/btm/btm_ble_gap.cc +++ b/system/stack/btm/btm_ble_gap.cc @@ -2377,6 +2377,35 @@ static void btm_ble_start_scan() { } } +/******************************************************************************* + * + * Function btm_update_scanner_filter_policy + * + * Description This function updates the filter policy of scanner + ******************************************************************************/ +static void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) { + uint32_t scan_interval = !btm_cb.ble_ctr_cb.inq_var.scan_interval + ? BTM_BLE_GAP_DISC_SCAN_INT + : btm_cb.ble_ctr_cb.inq_var.scan_interval; + uint32_t scan_window = !btm_cb.ble_ctr_cb.inq_var.scan_window + ? BTM_BLE_GAP_DISC_SCAN_WIN + : btm_cb.ble_ctr_cb.inq_var.scan_window; + uint8_t scan_phy = !btm_cb.ble_ctr_cb.inq_var.scan_phy ? BTM_BLE_DEFAULT_PHYS + : btm_cb.ble_ctr_cb.inq_var.scan_phy; + + log::verbose(""); + + btm_cb.ble_ctr_cb.inq_var.sfp = scan_policy; + btm_cb.ble_ctr_cb.inq_var.scan_type = + btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_NONE + ? BTM_BLE_SCAN_MODE_ACTI + : btm_cb.ble_ctr_cb.inq_var.scan_type; + + btm_send_hci_set_scan_params(btm_cb.ble_ctr_cb.inq_var.scan_type, (uint16_t)scan_interval, + (uint16_t)scan_window, (uint8_t)scan_phy, + btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, scan_policy); +} + /******************************************************************************* * * Function btm_ble_stop_scan diff --git a/system/stack/btm/btm_ble_int.h b/system/stack/btm/btm_ble_int.h index fad1f3d377e..eb8e88a2ceb 100644 --- a/system/stack/btm/btm_ble_int.h +++ b/system/stack/btm/btm_ble_int.h @@ -43,9 +43,6 @@ void btm_ble_connected(const RawAddress& bda, uint16_t handle, uint8_t enc_mode, bool can_read_discoverable_characteristics); void btm_ble_connection_established(const RawAddress& bda); -/* acceptlist function */ -void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy); - /* background connection function */ void btm_ble_update_mode_operation(uint8_t link_role, const RawAddress* bda, tHCI_STATUS status); /* BLE address management */ diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc index ad5ad9de159..af7869423f1 100644 --- a/system/stack/btm/btm_dev.cc +++ b/system/stack/btm/btm_dev.cc @@ -36,6 +36,7 @@ #include "btm_sec_api.h" #include "btm_sec_cb.h" #include "internal_include/bt_target.h" +#include "main/shim/acl_api.h" #include "main/shim/dumpsys.h" #include "osi/include/allocator.h" #include "rust/src/connection/ffi/connection_shim.h" @@ -151,9 +152,6 @@ void BTM_SecAddDevice(const RawAddress& bd_addr, DEV_CLASS dev_class, LinkKey li p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR; } -/** Removes the device from acceptlist */ -void BTM_AcceptlistRemove(const RawAddress& address); - /** Free resources associated with the device associated with |bd_addr| address. * * *** WARNING *** @@ -186,9 +184,9 @@ bool BTM_SecDeleteDevice(const RawAddress& bd_addr) { log::info("Remove device {} from filter accept list before delete record", bd_addr); if (com::android::bluetooth::flags::unified_connection_manager()) { bluetooth::connection::GetConnectionManager().stop_all_connections_to_device( - bluetooth::connection::ResolveRawAddress(p_dev_rec->bd_addr)); + bluetooth::connection::ResolveRawAddress(bda)); } else { - BTM_AcceptlistRemove(p_dev_rec->bd_addr); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bda)); } const auto device_type = p_dev_rec->device_type; diff --git a/system/stack/gatt/connection_manager.cc b/system/stack/gatt/connection_manager.cc index 6b6f8a71ba6..45e19c91990 100644 --- a/system/stack/gatt/connection_manager.cc +++ b/system/stack/gatt/connection_manager.cc @@ -27,10 +27,11 @@ #include #include +#include "main/shim/acl_api.h" #include "main/shim/le_scanning_manager.h" #include "os/logging/log_adapter.h" #include "osi/include/alarm.h" -#include "stack/btm/btm_ble_bgconn.h" +#include "stack/btm/btm_dev.h" #include "stack/include/advertise_data_parser.h" #include "stack/include/bt_types.h" #include "stack/include/btm_ble_api.h" @@ -229,7 +230,7 @@ bool background_connect_targeted_announcement_add(tAPP_ID app_id, const RawAddre } if (disable_accept_list) { - BTM_AcceptlistRemove(address); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address)); bgconn_dev[address].is_in_accept_list = false; } @@ -275,7 +276,8 @@ bool background_connect_add(uint8_t app_id, const RawAddress& address) { if (is_targeted_announcement_enabled) { log::debug("Targeted announcement enabled, do not add to AcceptList"); } else { - if (!BTM_AcceptlistAdd(address)) { + if (!bluetooth::shim::ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), + false)) { log::warn("Failed to add device {} to accept list for app {}", address, static_cast(app_id)); return false; @@ -300,7 +302,7 @@ bool remove_unconditional(const RawAddress& address) { return false; } - BTM_AcceptlistRemove(address); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address)); bgconn_dev.erase(it); return true; } @@ -342,7 +344,8 @@ bool background_connect_remove(uint8_t app_id, const RawAddress& address) { /* Keep using filtering */ log::debug("Keep using target announcement filtering"); } else if (!it->second.doing_bg_conn.empty()) { - if (!BTM_AcceptlistAdd(address)) { + if (!bluetooth::shim::ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), + false)) { log::warn("Could not re add device to accept list"); } else { bgconn_dev[address].is_in_accept_list = true; @@ -356,7 +359,7 @@ bool background_connect_remove(uint8_t app_id, const RawAddress& address) { // no more apps interested - remove from accept list and delete record if (accept_list_enabled) { - BTM_AcceptlistRemove(address); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address)); return true; } @@ -392,7 +395,7 @@ void on_app_deregistered(uint8_t app_id) { continue; } - BTM_AcceptlistRemove(it->first); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(it->first)); it = bgconn_dev.erase(it); } } @@ -424,7 +427,7 @@ void reset(bool after_reset) { bgconn_dev.clear(); if (!after_reset) { target_announcements_filtering_set(false); - BTM_AcceptlistClear(); + bluetooth::shim::ACL_IgnoreAllLeConnections(); } } @@ -458,7 +461,7 @@ bool direct_connect_add(uint8_t app_id, const RawAddress& address) { } if (!in_acceptlist) { - if (!BTM_AcceptlistAdd(address, true)) { + if (!bluetooth::shim::ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), true)) { // if we can't add to acceptlist, turn parameters back to slow. log::warn("Unable to add le device to acceptlist"); return false; @@ -506,7 +509,8 @@ bool direct_connect_remove(uint8_t app_id, const RawAddress& address, bool conne * when connection timeout out, the lower layer removes device from * the allow list. */ - if (!BTM_AcceptlistAdd(address)) { + if (!bluetooth::shim::ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), + false)) { log::warn("Failed to re-add device {} to accept list after connection timeout", address); } } @@ -514,7 +518,7 @@ bool direct_connect_remove(uint8_t app_id, const RawAddress& address, bool conne } // no more apps interested - remove from acceptlist - BTM_AcceptlistRemove(address); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address)); if (!is_targeted_announcement_enabled) { bgconn_dev.erase(it); diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index bbec4b65003..299b847c5a4 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -268,7 +268,7 @@ void gatt_cancel_connect(const RawAddress& bd_addr, tBT_TRANSPORT transport) { bluetooth::connection::ResolveRawAddress(bd_addr)); } else { if (!connection_manager::direct_connect_remove(CONN_MGR_ID_L2CAP, bd_addr)) { - BTM_AcceptlistRemove(bd_addr); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bd_addr)); log::info( "GATT connection manager has no record but removed filter " "acceptlist gatt_if:{} peer:{}", diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index 9b1452b47f7..ec449c0ecdd 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -32,10 +32,12 @@ #include "hardware/bt_gatt_types.h" #include "internal_include/bt_target.h" +#include "main/shim/acl_api.h" #include "main/shim/dumpsys.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" #include "rust/src/connection/ffi/connection_shim.h" +#include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" #include "stack/eatt/eatt.h" #include "stack/gatt/connection_manager.h" @@ -1667,7 +1669,7 @@ bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) { if (!connection_manager::is_background_connection(bda)) { if (!com::android::bluetooth::flags::gatt_fix_multiple_direct_connect() || p_tcb->app_hold_link.empty()) { - BTM_AcceptlistRemove(bda); + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bda)); } log::info( "Gatt connection manager has no background record but removed " diff --git a/system/stack/include/btm_ble_api.h b/system/stack/include/btm_ble_api.h index ea1a297a30f..50c74b89dd3 100644 --- a/system/stack/include/btm_ble_api.h +++ b/system/stack/include/btm_ble_api.h @@ -146,8 +146,6 @@ bool BTM_IsBleConnection(uint16_t conn_handle); bool BTM_ReadRemoteConnectionAddr(const RawAddress& pseudo_addr, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, bool ota_address); -#include "stack/btm/btm_ble_bgconn.h" - /******************************************************** * * Function BTM_BleSetPrefConnParams diff --git a/system/stack/test/gatt_connection_manager_test.cc b/system/stack/test/gatt_connection_manager_test.cc index e7912106083..28be08d198f 100644 --- a/system/stack/test/gatt_connection_manager_test.cc +++ b/system/stack/test/gatt_connection_manager_test.cc @@ -28,7 +28,6 @@ namespace { // actually scheduled class AcceptlistMock { public: - MOCK_METHOD1(AcceptlistAdd, bool(const RawAddress&)); MOCK_METHOD2(AcceptlistAdd, bool(const RawAddress&, bool is_direct)); MOCK_METHOD1(AcceptlistRemove, void(const RawAddress&)); MOCK_METHOD0(AcceptlistClear, void()); @@ -50,20 +49,24 @@ constexpr tAPP_ID CLIENT2 = 2; constexpr tAPP_ID CLIENT3 = 3; constexpr tAPP_ID CLIENT10 = 10; -// Implementation of btm_ble_bgconn.h API for test. -bool BTM_AcceptlistAdd(const RawAddress& address) { - return localAcceptlistMock->AcceptlistAdd(address); +const tBLE_BD_ADDR BTM_Sec_GetAddressWithType(const RawAddress& bd_addr) { + return tBLE_BD_ADDR{.type = BLE_ADDR_PUBLIC, .bda = bd_addr}; } -bool BTM_AcceptlistAdd(const RawAddress& address, bool is_direct) { - return localAcceptlistMock->AcceptlistAdd(address, is_direct); -} +namespace bluetooth { +namespace shim { -void BTM_AcceptlistRemove(const RawAddress& address) { - return localAcceptlistMock->AcceptlistRemove(address); +bool ACL_AcceptLeConnectionFrom(const tBLE_BD_ADDR& address, bool is_direct) { + return localAcceptlistMock->AcceptlistAdd(address.bda, is_direct); +} +void ACL_IgnoreLeConnectionFrom(const tBLE_BD_ADDR& address) { + return localAcceptlistMock->AcceptlistRemove(address.bda); } -void BTM_AcceptlistClear() { return localAcceptlistMock->AcceptlistClear(); } +void ACL_IgnoreAllLeConnections() { return localAcceptlistMock->AcceptlistClear(); } + +} // namespace shim +} // namespace bluetooth void BTM_BleTargetAnnouncementObserve(bool enable, tBTM_INQ_RESULTS_CB* p_results_cb) { localAcceptlistMock->EnableTargetedAnnouncements(enable, p_results_cb); @@ -112,7 +115,7 @@ void on_connection_timed_out(uint8_t app_id, const RawAddress& address) { /** Verify that app can add a device to acceptlist, it is returned as interested * app, and then can remove the device later. */ TEST_F(BleConnectionManager, test_background_connection_add_remove) { - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).WillOnce(Return(true)); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true)); EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0); EXPECT_TRUE(background_connect_add(CLIENT1, address1)); @@ -123,7 +126,7 @@ TEST_F(BleConnectionManager, test_background_connection_add_remove) { EXPECT_EQ(apps.size(), 1UL); EXPECT_EQ(apps.count(CLIENT1), 1UL); - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_)).Times(0); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_, _)).Times(0); EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1); EXPECT_TRUE(background_connect_remove(CLIENT1, address1)); @@ -137,7 +140,7 @@ TEST_F(BleConnectionManager, test_background_connection_add_remove) { * device being added to whtie list only once, also, that device is removed only * after last client removes it. */ TEST_F(BleConnectionManager, test_background_connection_multiple_clients) { - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).WillOnce(Return(true)); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true)); EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0); EXPECT_TRUE(background_connect_add(CLIENT1, address1)); EXPECT_TRUE(background_connect_add(CLIENT1, address1)); @@ -148,7 +151,7 @@ TEST_F(BleConnectionManager, test_background_connection_multiple_clients) { Mock::VerifyAndClearExpectations(localAcceptlistMock.get()); - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_)).Times(0); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_, _)).Times(0); // removing from nonexisting client, should fail EXPECT_FALSE(background_connect_remove(CLIENT10, address1)); @@ -250,7 +253,7 @@ TEST_F(BleConnectionManager, test_app_unregister) { */ EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, true)).WillOnce(Return(true)); - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address2)).WillOnce(Return(true)); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address2, false)).WillOnce(Return(true)); EXPECT_TRUE(direct_connect_add(CLIENT1, address1)); EXPECT_TRUE(background_connect_add(CLIENT1, address2)); EXPECT_TRUE(direct_connect_add(CLIENT2, address2)); @@ -296,7 +299,7 @@ TEST_F(BleConnectionManager, test_target_announement_connect) { TEST_F(BleConnectionManager, test_add_targeted_announement_when_allow_list_used) { /* Accept adding to allow list */ - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).WillOnce(Return(true)); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true)); /* This shall be called when registering announcements */ EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1); @@ -308,7 +311,7 @@ TEST_F(BleConnectionManager, test_add_targeted_announement_when_allow_list_used) TEST_F(BleConnectionManager, test_add_background_connect_when_targeted_announcement_are_enabled) { /* Accept adding to allow list */ - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).Times(0); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(0); /* This shall be called when registering announcements */ EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0); @@ -320,7 +323,7 @@ TEST_F(BleConnectionManager, test_add_background_connect_when_targeted_announcem } TEST_F(BleConnectionManager, test_re_add_background_connect_to_allow_list) { - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).Times(0); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(0); EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0); EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT2, address1)); @@ -333,7 +336,7 @@ TEST_F(BleConnectionManager, test_re_add_background_connect_to_allow_list) { */ /* Accept adding to allow list */ - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).WillOnce(Return(true)); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true)); EXPECT_TRUE(background_connect_remove(CLIENT2, address1)); Mock::VerifyAndClearExpectations(localAcceptlistMock.get()); @@ -349,9 +352,9 @@ TEST_F(BleConnectionManager, test_re_add_to_allow_list_after_timeout_with_multip void* alarm_data = nullptr; /* Accept adding to allow list */ - ON_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).WillByDefault(Return(true)); + ON_CALL(*localAcceptlistMock, AcceptlistAdd(address1, _)).WillByDefault(Return(true)); - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).Times(1); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(1); EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0); EXPECT_TRUE(background_connect_add(CLIENT1, address1)); @@ -369,7 +372,7 @@ TEST_F(BleConnectionManager, test_re_add_to_allow_list_after_timeout_with_multip // simulate timeout seconds passed, alarm executing EXPECT_CALL(*localAcceptlistMock, OnConnectionTimedOut(CLIENT2, address1)).Times(1); EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0); - EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1)).Times(1); + EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(1); EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1); alarm_callback(alarm_data); diff --git a/system/test/mock/mock_stack_btm_ble_bgconn.cc b/system/test/mock/mock_stack_btm_ble_bgconn.cc deleted file mode 100644 index 2d14a1a5b6d..00000000000 --- a/system/test/mock/mock_stack_btm_ble_bgconn.cc +++ /dev/null @@ -1,83 +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:11 - * - * mockcify.pl ver 0.2 - */ -// Mock include file to share data between tests and mock -#include "test/mock/mock_stack_btm_ble_bgconn.h" - -#include "test/common/mock_functions.h" -#include "types/raw_address.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -// Mocked compile conditionals, if any -// Mocked internal structures, if any -struct BackgroundConnection {}; -struct BgConnHash {}; - -namespace test { -namespace mock { -namespace stack_btm_ble_bgconn { - -// Function state capture and return values, if needed -struct btm_update_scanner_filter_policy btm_update_scanner_filter_policy; -struct BTM_SetLeConnectionModeToFast BTM_SetLeConnectionModeToFast; -struct BTM_SetLeConnectionModeToSlow BTM_SetLeConnectionModeToSlow; -struct BTM_AcceptlistAdd BTM_AcceptlistAdd; -struct BTM_AcceptlistAddDirect BTM_AcceptlistAddDirect; -struct BTM_AcceptlistRemove BTM_AcceptlistRemove; -struct BTM_AcceptlistClear BTM_AcceptlistClear; - -} // namespace stack_btm_ble_bgconn -} // namespace mock -} // namespace test - -void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) { - inc_func_call_count(__func__); - test::mock::stack_btm_ble_bgconn::btm_update_scanner_filter_policy(scan_policy); -} -bool BTM_SetLeConnectionModeToFast() { - inc_func_call_count(__func__); - return test::mock::stack_btm_ble_bgconn::BTM_SetLeConnectionModeToFast(); -} -void BTM_SetLeConnectionModeToSlow() { - inc_func_call_count(__func__); - test::mock::stack_btm_ble_bgconn::BTM_SetLeConnectionModeToSlow(); -} -bool BTM_AcceptlistAdd(const RawAddress& address) { - inc_func_call_count(__func__); - return test::mock::stack_btm_ble_bgconn::BTM_AcceptlistAdd(address); -} -bool BTM_AcceptlistAdd(const RawAddress& address, bool is_direct) { - inc_func_call_count(__func__); - return test::mock::stack_btm_ble_bgconn::BTM_AcceptlistAddDirect(address, is_direct); -} -void BTM_AcceptlistRemove(const RawAddress& address) { - inc_func_call_count(__func__); - test::mock::stack_btm_ble_bgconn::BTM_AcceptlistRemove(address); -} -void BTM_AcceptlistClear() { - inc_func_call_count(__func__); - test::mock::stack_btm_ble_bgconn::BTM_AcceptlistClear(); -} - -// END mockcify generation diff --git a/system/test/mock/mock_stack_btm_ble_bgconn.h b/system/test/mock/mock_stack_btm_ble_bgconn.h deleted file mode 100644 index 803bc10ba4e..00000000000 --- a/system/test/mock/mock_stack_btm_ble_bgconn.h +++ /dev/null @@ -1,98 +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:11 - * - * mockcify.pl ver 0.2 - */ - -#include - -// Original included files, if any -#include "stack/include/btm_ble_api_types.h" -#include "types/raw_address.h" - -// Mocked compile conditionals, if any -namespace test { -namespace mock { -namespace stack_btm_ble_bgconn { - -// Name: btm_update_scanner_filter_policy -// Params: tBTM_BLE_SFP scan_policy -// Returns: void -struct btm_update_scanner_filter_policy { - std::function body{[](tBTM_BLE_SFP /* scan_policy */) {}}; - void operator()(tBTM_BLE_SFP scan_policy) { body(scan_policy); } -}; -extern struct btm_update_scanner_filter_policy btm_update_scanner_filter_policy; -// Name: BTM_SetLeConnectionModeToFast -// Params: -// Returns: bool -struct BTM_SetLeConnectionModeToFast { - std::function body{[]() { return false; }}; - bool operator()() { return body(); } -}; -extern struct BTM_SetLeConnectionModeToFast BTM_SetLeConnectionModeToFast; -// Name: BTM_SetLeConnectionModeToSlow -// Params: -// Returns: void -struct BTM_SetLeConnectionModeToSlow { - std::function body{[]() {}}; - void operator()() { body(); } -}; -extern struct BTM_SetLeConnectionModeToSlow BTM_SetLeConnectionModeToSlow; -// Name: BTM_AcceptlistAdd -// Params: const RawAddress& address -// Returns: bool -struct BTM_AcceptlistAdd { - std::function body{ - [](const RawAddress& /* address */) { return false; }}; - bool operator()(const RawAddress& address) { return body(address); } -}; -extern struct BTM_AcceptlistAdd BTM_AcceptlistAdd; -// Name: BTM_AcceptlistAddDirect -// Params: const RawAddress& address, bool is_direct -// Returns: bool -struct BTM_AcceptlistAddDirect { - std::function body{ - [](const RawAddress& /* address */, bool /* is_direct */) { return false; }}; - bool operator()(const RawAddress& address, bool is_direct) { return body(address, is_direct); } -}; -extern struct BTM_AcceptlistAddDirect BTM_AcceptlistAddDirect; -// Name: BTM_AcceptlistRemove -// Params: const RawAddress& address -// Returns: void -struct BTM_AcceptlistRemove { - std::function body{[](const RawAddress& /* address */) {}}; - void operator()(const RawAddress& address) { body(address); } -}; -extern struct BTM_AcceptlistRemove BTM_AcceptlistRemove; -// Name: BTM_AcceptlistClear -// Params: -// Returns: void -struct BTM_AcceptlistClear { - std::function body{[]() {}}; - void operator()() { body(); } -}; -extern struct BTM_AcceptlistClear BTM_AcceptlistClear; - -} // namespace stack_btm_ble_bgconn -} // namespace mock -} // namespace test - -// END mockcify generation diff --git a/system/test/mock/mock_stack_gatt_connection_manager.cc b/system/test/mock/mock_stack_gatt_connection_manager.cc index 3c6c48f7b3b..a27d7d2d6df 100644 --- a/system/test/mock/mock_stack_gatt_connection_manager.cc +++ b/system/test/mock/mock_stack_gatt_connection_manager.cc @@ -21,7 +21,6 @@ #include -#include "stack/btm/btm_ble_bgconn.h" #include "stack/gatt/connection_manager.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" -- GitLab From 481dfa26154bca9a69f19ba97f61a0b26b3191e7 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Mon, 7 Oct 2024 04:11:10 +0000 Subject: [PATCH 217/875] Fix background connection The `cif_set` should have been used instead of `cif_mask` when dynamic allocation is enabled. Using `cif_mask` prevented background connections from being established when the flag was turned on. This change corrects the function call and adds a test for background GATT connections to ensure the issue is resolved and prevent future regressions. Bug: 371617855 Bug: 348559823 Flag: gatt_client_dynamic_allocation Test: atest GattClientTest Change-Id: I5e8fba7e3b133475fe2e98581209145b75d3fb41 --- .../src/android/bluetooth/GattClientTest.java | 76 +++++++++++++------ system/bta/gatt/bta_gattc_utils.cc | 21 +++-- 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java index 85fe1cc160e..b2042ee5051 100644 --- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java +++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; -import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.test_utils.EnableBluetoothRule; import android.content.Context; import android.platform.test.annotations.RequiresFlagsEnabled; @@ -40,15 +39,17 @@ import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.Log; import androidx.test.core.app.ApplicationProvider; +import androidx.test.platform.app.InstrumentationRegistry; import com.android.bluetooth.flags.Flags; -import com.android.compatibility.common.util.AdoptShellPermissionsRule; import com.google.protobuf.ByteString; import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; +import org.junit.After; import org.junit.Assume; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -73,6 +74,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.UUID; @RunWith(TestParameterInjector.class) @@ -98,15 +100,38 @@ public class GattClientTest { public final PandoraDevice mBumble = new PandoraDevice(); @Rule(order = 2) - public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule(); - - @Rule(order = 3) public final EnableBluetoothRule mEnableBluetoothRule = new EnableBluetoothRule(false, true); private final Context mContext = ApplicationProvider.getApplicationContext(); private final BluetoothManager mManager = mContext.getSystemService(BluetoothManager.class); private final BluetoothAdapter mAdapter = mManager.getAdapter(); - private final BluetoothLeScanner mLeScanner = mAdapter.getBluetoothLeScanner(); + + private Host mHost; + private BluetoothDevice mRemoteLeDevice; + + @Before + public void setUp() throws Exception { + InstrumentationRegistry.getInstrumentation() + .getUiAutomation() + .adoptShellPermissionIdentity(); + + mHost = new Host(mContext); + mRemoteLeDevice = + mAdapter.getRemoteLeDevice( + Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); + mRemoteLeDevice.removeBond(); + } + + @After + public void tearUp() throws Exception { + InstrumentationRegistry.getInstrumentation() + .getUiAutomation() + .dropShellPermissionIdentity(); + Set bondedDevices = mAdapter.getBondedDevices(); + if (bondedDevices.contains(mRemoteLeDevice)) { + mRemoteLeDevice.removeBond(); + } + } @Test public void directConnectGattAfterClose() throws Exception { @@ -138,9 +163,12 @@ public class GattClientTest { } @Test - public void fullGattClientLifecycle() throws Exception { + public void fullGattClientLifecycle(@TestParameter boolean autoConnect) { + if (autoConnect) { + createLeBondAndWaitBonding(mRemoteLeDevice); + } BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); - BluetoothGatt gatt = connectGattAndWaitConnection(gattCallback); + BluetoothGatt gatt = connectGattAndWaitConnection(gattCallback, autoConnect); disconnectAndWaitDisconnection(gatt, gattCallback); } @@ -148,13 +176,10 @@ public class GattClientTest { public void reconnectExistingClient() throws Exception { advertiseWithBumble(); - BluetoothDevice device = - mAdapter.getRemoteLeDevice( - Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); InOrder inOrder = inOrder(gattCallback); - BluetoothGatt gatt = device.connectGatt(mContext, false, gattCallback); + BluetoothGatt gatt = mRemoteLeDevice.connectGatt(mContext, false, gattCallback); inOrder.verify(gattCallback, timeout(1000)) .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); @@ -465,30 +490,27 @@ public class GattClientTest { } private BluetoothGatt connectGattAndWaitConnection(BluetoothGattCallback callback) { + return connectGattAndWaitConnection(callback, /* autoConnect= */ false); + } + + private BluetoothGatt connectGattAndWaitConnection( + BluetoothGattCallback callback, boolean autoConnect) { final int status = GATT_SUCCESS; final int state = STATE_CONNECTED; advertiseWithBumble(); - BluetoothDevice device = - mAdapter.getRemoteLeDevice( - Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); - - BluetoothGatt gatt = device.connectGatt(mContext, false, callback); + BluetoothGatt gatt = mRemoteLeDevice.connectGatt(mContext, autoConnect, callback); verify(callback, timeout(1000)).onConnectionStateChange(eq(gatt), eq(status), eq(state)); return gatt; } /** Tries to connect GATT, it could fail and return null. */ - private BluetoothGatt tryConnectGatt(BluetoothGattCallback callback) { + private BluetoothGatt tryConnectGatt(BluetoothGattCallback callback, boolean autoConnect) { advertiseWithBumble(); - BluetoothDevice device = - mAdapter.getRemoteLeDevice( - Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); - - BluetoothGatt gatt = device.connectGatt(mContext, false, callback); + BluetoothGatt gatt = mRemoteLeDevice.connectGatt(mContext, autoConnect, callback); ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor stateCaptor = ArgumentCaptor.forClass(Integer.class); @@ -596,7 +618,6 @@ public class GattClientTest { @Test @RequiresFlagsEnabled(Flags.FLAG_GATT_CLIENT_DYNAMIC_ALLOCATION) public void connectGatt_multipleClients() { - advertiseWithBumble(); registerGattService(); List gatts = new ArrayList<>(); @@ -606,7 +627,7 @@ public class GattClientTest { try { for (int i = 0; i < repeatTimes; i++) { BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); - BluetoothGatt gatt = tryConnectGatt(gattCallback); + BluetoothGatt gatt = tryConnectGatt(gattCallback, false); // If it fails, close an existing gatt instance and try again. if (gatt == null) { failed = true; @@ -664,4 +685,9 @@ public class GattClientTest { gatt.close(); } } + + private void createLeBondAndWaitBonding(BluetoothDevice device) { + advertiseWithBumble(); + mHost.createBondAndVerify(device); + } } diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc index ca911dec784..d4c252efccd 100644 --- a/system/bta/gatt/bta_gattc_utils.cc +++ b/system/bta/gatt/bta_gattc_utils.cc @@ -691,9 +691,12 @@ 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; - p_cif_mask = &p_bg_tck->cif_mask; - - *p_cif_mask = ((tBTA_GATTC_CIF_MASK)1 << (client_if - 1)); + 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)); + } return true; } } @@ -719,9 +722,15 @@ 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 (((p_bg_tck->cif_mask & ((tBTA_GATTC_CIF_MASK)1 << (client_if - 1))) != 0) && - role == HCI_ROLE_CENTRAL) { - is_bg_conn = true; + 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; + } } } } -- GitLab From 94e3b26ef65d374b2342d365c571773b86220ab5 Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Fri, 4 Oct 2024 22:07:58 +0000 Subject: [PATCH 218/875] Pandora: Enable Bumble config modification at runtime Bug: 370701018 Bug: 370608988 Test: atest avatar - manual testing with avatar Change-Id: I9c190c70ca4e6c57bf97350cd5afb3bd32ac390c --- framework/tests/bumble/src/bumble_server.py | 22 +++--- .../pandora_experimental/bumble_config.proto | 60 +++++++++++++++ pandora/interfaces/python/Android.bp | 5 ++ .../bumble_experimental/bumble_config.py | 73 +++++++++++++++++++ 4 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 pandora/interfaces/pandora_experimental/bumble_config.proto create mode 100644 pandora/server/bumble_experimental/bumble_config.py diff --git a/framework/tests/bumble/src/bumble_server.py b/framework/tests/bumble/src/bumble_server.py index 8f5a39f8f27..c3c3943f61b 100644 --- a/framework/tests/bumble/src/bumble_server.py +++ b/framework/tests/bumble/src/bumble_server.py @@ -14,29 +14,29 @@ import argparse import asyncio -import logging import json +import logging +from typing import Any, Dict from bumble import pandora as bumble_server -from bumble.pandora import PandoraDevice, Config, serve - +from bumble.pandora import Config, PandoraDevice, serve from bumble_experimental.asha import AshaService +from bumble_experimental.avrcp import AvrcpService +from bumble_experimental.bumble_config import BumbleConfigService from bumble_experimental.dck import DckService from bumble_experimental.gatt import GATTService -from bumble_experimental.rfcomm import RFCOMMService -from bumble_experimental.avrcp import AvrcpService from bumble_experimental.hid import HIDService from bumble_experimental.oob import OOBService - +from bumble_experimental.rfcomm import RFCOMMService from pandora_experimental.asha_grpc_aio import add_AshaServicer_to_server +from pandora_experimental.avrcp_grpc_aio import add_AVRCPServicer_to_server +from pandora_experimental.bumble_config_grpc_aio import \ + add_BumbleConfigServicer_to_server from pandora_experimental.dck_grpc_aio import add_DckServicer_to_server from pandora_experimental.gatt_grpc_aio import add_GATTServicer_to_server -from pandora_experimental.rfcomm_grpc_aio import add_RFCOMMServicer_to_server -from pandora_experimental.avrcp_grpc_aio import add_AVRCPServicer_to_server from pandora_experimental.hid_grpc_aio import add_HIDServicer_to_server from pandora_experimental.oob_grpc_aio import add_OOBServicer_to_server - -from typing import Any, Dict +from pandora_experimental.rfcomm_grpc_aio import add_RFCOMMServicer_to_server BUMBLE_SERVER_GRPC_PORT = 7999 ROOTCANAL_PORT_CUTTLEFISH = 7300 @@ -89,6 +89,8 @@ def register_experimental_services() -> None: lambda bumble, _, server: add_HIDServicer_to_server(HIDService(bumble.device), server)) bumble_server.register_servicer_hook( lambda bumble, _, server: add_OOBServicer_to_server(OOBService(bumble.device), server)) + bumble_server.register_servicer_hook( + lambda bumble, config, server: add_BumbleConfigServicer_to_server(BumbleConfigService(bumble.device, config), server)) def retrieve_config(config: str) -> Dict[str, Any]: diff --git a/pandora/interfaces/pandora_experimental/bumble_config.proto b/pandora/interfaces/pandora_experimental/bumble_config.proto new file mode 100644 index 00000000000..438f2ba16b4 --- /dev/null +++ b/pandora/interfaces/pandora_experimental/bumble_config.proto @@ -0,0 +1,60 @@ +// Copyright 2024 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. + +syntax = "proto3"; + +option java_outer_classname = "BumbleConfigProto"; + +package pandora; + +import "google/protobuf/empty.proto"; +import "pandora/host.proto"; + +// This service provides runtime configuration for the Bumble Bluetooth stack. +// It allows overriding the initial configuration provided by the JSON file and +// the Security Service. This service should only be used by BumbleBluetoothTests. +service BumbleConfig { + // Override the initial Bumble configuration. This will erase any + // previous configuration set via JSON file or Security Service. + rpc Override(OverrideRequest) returns (google.protobuf.Empty); +} + +message PairingConfig { + bool sc = 1; + bool mitm = 2; + bool bonding = 3; + OwnAddressType identity_address_type = 4; +} + +enum IoCapability { + DISPLAY_ONLY = 0x00; + DISPLAY_YES_NO = 0x01; + KEYBOARD_ONLY = 0x02; + NO_OUTPUT_NO_INPUT = 0x03; + KEYBOARD_DISPLAY = 0x04; +} + +enum KeyDistribution { + ENCRYPTION_KEY = 0x00; + IDENTITY_KEY = 0x01; + SIGNING_KEY = 0x02; + LINK_KEY = 0x03; +} + +message OverrideRequest { + IoCapability io_capability = 1; + PairingConfig pairing_config = 2; + KeyDistribution initiator_key_distribution = 3; + KeyDistribution responder_key_distribution = 4; +} diff --git a/pandora/interfaces/python/Android.bp b/pandora/interfaces/python/Android.bp index 2abac309db9..d295f2cfd32 100644 --- a/pandora/interfaces/python/Android.bp +++ b/pandora/interfaces/python/Android.bp @@ -34,6 +34,10 @@ genrule { "pandora_experimental/avrcp_grpc_aio.py", "pandora_experimental/avrcp_pb2.py", "pandora_experimental/avrcp_pb2.pyi", + "pandora_experimental/bumble_config_grpc.py", + "pandora_experimental/bumble_config_grpc_aio.py", + "pandora_experimental/bumble_config_pb2.py", + "pandora_experimental/bumble_config_pb2.pyi", "pandora_experimental/dck_grpc.py", "pandora_experimental/dck_grpc_aio.py", "pandora_experimental/dck_pb2.py", @@ -109,6 +113,7 @@ filegroup { srcs: [ ":pandora_experimental-python-gen-src{pandora_experimental/asha_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/avrcp_pb2.pyi}", + ":pandora_experimental-python-gen-src{pandora_experimental/bumble_config_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/dck_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/gatt_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/hap_pb2.pyi}", diff --git a/pandora/server/bumble_experimental/bumble_config.py b/pandora/server/bumble_experimental/bumble_config.py new file mode 100644 index 00000000000..44354761981 --- /dev/null +++ b/pandora/server/bumble_experimental/bumble_config.py @@ -0,0 +1,73 @@ +# Copyright 2024 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 logging + +import grpc +from bumble.device import Connection as BumbleConnection +from bumble.device import Device +from bumble.pairing import PairingConfig +from bumble.pairing import PairingDelegate as BasePairingDelegate +from bumble.pandora import Config, utils +from bumble.pandora.security import PairingDelegate +from google.protobuf.empty_pb2 import Empty +from pandora.host_pb2 import PUBLIC +from pandora_experimental.bumble_config_grpc_aio import BumbleConfigServicer +from pandora_experimental.bumble_config_pb2 import (KeyDistribution, + OverrideRequest) + + +class BumbleConfigService(BumbleConfigServicer): + device: Device + + def __init__(self, device: Device, server_config: Config) -> None: + self.log = utils.BumbleServerLoggerAdapter(logging.getLogger(), {"service_name": "BumbleConfig", "device": device}) + self.device = device + self.server_config = server_config + + @utils.rpc + async def Override(self, request: OverrideRequest, context: grpc.ServicerContext) -> Empty: + + def parseProtoKeyDistribution(key: KeyDistribution,) -> BasePairingDelegate.KeyDistribution: + return [ + BasePairingDelegate.KeyDistribution.DISTRIBUTE_ENCRYPTION_KEY, + BasePairingDelegate.KeyDistribution.DISTRIBUTE_IDENTITY_KEY, + BasePairingDelegate.KeyDistribution.DISTRIBUTE_SIGNING_KEY, + BasePairingDelegate.KeyDistribution.DISTRIBUTE_LINK_KEY, + ][key] # type: ignore + + def pairing_config_factory(connection: BumbleConnection) -> PairingConfig: + pairing_delegate = PairingDelegate( + connection=connection, + io_capability=BasePairingDelegate.IoCapability(request.io_capability), + local_initiator_key_distribution=parseProtoKeyDistribution(request.initiator_key_distribution), + local_responder_key_distribution=parseProtoKeyDistribution(request.responder_key_distribution), + ) + + pc_req = request.pairing_config + pairing_config = PairingConfig( + sc=pc_req.sc, + mitm=pc_req.mitm, + bonding=pc_req.bonding, + identity_address_type=PairingConfig.AddressType.PUBLIC + if request.identity_address_type == PUBLIC else PairingConfig.AddressType.RANDOM, + delegate=pairing_delegate, + ) + self.log.debug(f"Override: {pairing_config}") + + return pairing_config + + self.device.pairing_config_factory = pairing_config_factory + + return Empty() -- GitLab From 26f3c1d2c95d92f37557d41199ad6295fdce8065 Mon Sep 17 00:00:00 2001 From: Pomai Ahlo Date: Tue, 8 Oct 2024 10:31:10 -0700 Subject: [PATCH 219/875] port_api: Remove function names from logs The log will already have the function name, this removes the redundant function names Bug: 345006660 Test: m com.android.btservices Flag: EXEMPT Logging change Change-Id: Ia7f6773162c590b53bb3967fdf62cc63dce0b191 --- system/stack/rfcomm/port_api.cc | 41 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc index 34af8e34548..6676eac7672 100644 --- a/system/stack/rfcomm/port_api.cc +++ b/system/stack/rfcomm/port_api.cc @@ -359,7 +359,7 @@ int RFCOMM_RemoveServer(uint16_t handle) { } int PORT_SetEventMaskAndCallback(uint16_t handle, uint32_t mask, tPORT_CALLBACK* p_port_cb) { - log::verbose("PORT_SetEventMask() handle:{} mask:0x{:x}", handle, mask); + log::verbose("handle:{} mask:0x{:x}", handle, mask); tPORT* p_port = get_port_from_handle(handle); if (p_port == nullptr) { log::error("Unable to get RFCOMM port control block bad handle:{}", handle); @@ -410,7 +410,7 @@ int PORT_ClearKeepHandleFlag(uint16_t handle) { * ******************************************************************************/ int PORT_SetDataCOCallback(uint16_t handle, tPORT_DATA_CO_CALLBACK* p_port_cb) { - log::verbose("PORT_SetDataCOCallback() handle:{} cb 0x{}", handle, fmt::ptr(p_port_cb)); + log::verbose("handle:{} cb 0x{}", handle, fmt::ptr(p_port_cb)); tPORT* p_port = get_port_from_handle(handle); if (p_port == nullptr) { @@ -575,7 +575,7 @@ bool PORT_IsCollisionDetected(RawAddress bd_addr) { int PORT_SetSettings(uint16_t handle, PortSettings* p_settings) { uint8_t baud_rate; - log::verbose("PORT_SetSettings() handle:{}", handle); + log::verbose("handle:{}", handle); tPORT* p_port = get_port_from_handle(handle); if (p_port == nullptr) { log::error("Unable to get RFCOMM port control block bad handle:{}", handle); @@ -590,7 +590,7 @@ int PORT_SetSettings(uint16_t handle, PortSettings* p_settings) { return PORT_LINE_ERR; } - log::verbose("PORT_SetSettings() handle:{} FC_TYPE:0x{:x}", handle, p_settings->fc_type); + log::verbose("handle:{} FC_TYPE:0x{:x}", handle, p_settings->fc_type); baud_rate = p_port->user_port_settings.baud_rate; p_port->user_port_settings = *p_settings; @@ -615,7 +615,7 @@ int PORT_SetSettings(uint16_t handle, PortSettings* p_settings) { * ******************************************************************************/ int PORT_GetSettings(uint16_t handle, PortSettings* p_settings) { - log::verbose("PORT_GetSettings() handle:{}", handle); + log::verbose("handle:{}", handle); tPORT* p_port = get_port_from_handle(handle); if (p_port == nullptr) { @@ -653,7 +653,7 @@ int PORT_FlowControl_MaxCredit(uint16_t handle, bool enable) { bool old_fc; uint32_t events; - log::verbose("PORT_FlowControl() handle:{} enable: {}", handle, enable); + log::verbose("handle:{} enable: {}", handle, enable); tPORT* p_port = get_port_from_handle(handle); if (p_port == nullptr) { @@ -720,7 +720,7 @@ int PORT_ReadData(uint16_t handle, char* p_data, uint16_t max_len, uint16_t* p_l BT_HDR* p_buf; uint16_t count; - log::verbose("PORT_ReadData() handle:{} max_len:{}", handle, max_len); + log::verbose("handle:{} max_len:{}", handle, max_len); /* Initialize this in case of an error */ *p_len = 0; @@ -793,10 +793,9 @@ int PORT_ReadData(uint16_t handle, char* p_data, uint16_t max_len, uint16_t* p_l } if (*p_len == 1) { - log::verbose("PORT_ReadData queue:{} returned:{} {:x}", p_port->rx.queue_size, *p_len, - p_data[0]); + log::verbose("queue:{} returned:{} {:x}", p_port->rx.queue_size, *p_len, p_data[0]); } else { - log::verbose("PORT_ReadData queue:{} returned:{}", p_port->rx.queue_size, *p_len); + log::verbose("queue:{} returned:{}", p_port->rx.queue_size, *p_len); } /* If rfcomm suspended traffic from the peer based on the rx_queue_size */ @@ -834,7 +833,7 @@ static int port_write(tPORT* p_port, BT_HDR* p_buf) { (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED))) { if ((p_port->tx.queue_size > PORT_TX_CRITICAL_WM) || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_CRITICAL_WM)) { - log::warn("PORT_Write: Queue size: {}", p_port->tx.queue_size); + log::warn("Queue size: {}", p_port->tx.queue_size); osi_free(p_buf); @@ -846,7 +845,7 @@ static int port_write(tPORT* p_port, BT_HDR* p_buf) { } log::verbose( - "PORT_Write : Data is enqueued. flow disabled {} peer_ready {} state {} ctrl_state " + "Data is enqueued. flow disabled {} peer_ready {} state {} ctrl_state " "{:x}", p_port->tx.peer_fc, p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready, p_port->rfc.state, p_port->port_ctrl); @@ -856,7 +855,7 @@ static int port_write(tPORT* p_port, BT_HDR* p_buf) { return PORT_CMD_PENDING; } else { - log::verbose("PORT_Write : Data is being sent"); + log::verbose("Data is being sent"); RFCOMM_DataReq(p_port->rfc.p_mcb, p_port->dlci, p_buf); return PORT_SUCCESS; @@ -881,7 +880,7 @@ int PORT_WriteDataCO(uint16_t handle, int* p_len) { int rc = 0; uint16_t length; - log::verbose("PORT_WriteDataCO() handle:{}", handle); + log::verbose("handle:{}", handle); *p_len = 0; tPORT* p_port = get_port_from_handle(handle); @@ -891,12 +890,12 @@ int PORT_WriteDataCO(uint16_t handle, int* p_len) { } if (!p_port->in_use || (p_port->state == PORT_CONNECTION_STATE_CLOSED)) { - log::warn("PORT_WriteDataByFd() no port state:{}", p_port->state); + log::warn("no port state:{}", p_port->state); return PORT_NOT_OPENED; } if (!p_port->peer_mtu) { - log::error("PORT_WriteDataByFd() peer_mtu:{}", p_port->peer_mtu); + log::error("peer_mtu:{}", p_port->peer_mtu); return PORT_UNKNOWN_ERROR; } int available = 0; @@ -983,7 +982,7 @@ int PORT_WriteDataCO(uint16_t handle, int* p_len) { return PORT_UNKNOWN_ERROR; } - log::verbose("PORT_WriteData {} bytes", length); + log::verbose("{} bytes", length); rc = port_write(p_port, p_buf); @@ -1035,7 +1034,7 @@ int PORT_WriteData(uint16_t handle, const char* p_data, uint16_t max_len, uint16 int rc = 0; uint16_t length; - log::verbose("PORT_WriteData() max_len:{}", max_len); + log::verbose("max_len:{}", max_len); *p_len = 0; @@ -1046,7 +1045,7 @@ int PORT_WriteData(uint16_t handle, const char* p_data, uint16_t max_len, uint16 } if (!p_port->in_use || (p_port->state == PORT_CONNECTION_STATE_CLOSED)) { - log::warn("PORT_WriteData() no port state:{}", p_port->state); + log::warn("no port state:{}", p_port->state); return PORT_NOT_OPENED; } @@ -1055,7 +1054,7 @@ int PORT_WriteData(uint16_t handle, const char* p_data, uint16_t max_len, uint16 } if (!max_len || !p_port->peer_mtu) { - log::error("PORT_WriteData() peer_mtu:{}", p_port->peer_mtu); + log::error("peer_mtu:{}", p_port->peer_mtu); return PORT_UNKNOWN_ERROR; } @@ -1107,7 +1106,7 @@ int PORT_WriteData(uint16_t handle, const char* p_data, uint16_t max_len, uint16 memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, length); - log::verbose("PORT_WriteData {} bytes", length); + log::verbose("{} bytes", length); rc = port_write(p_port, p_buf); -- GitLab From 68fffd415e45ec57cdcd67655bf06f70eae90ab1 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 8 Oct 2024 17:05:35 -0700 Subject: [PATCH 220/875] Flag: add aics_api Bug: 315241296 Bug: 372328699 Test: m . Flag: com.android.bluetooth.flags.aics_api Change-Id: I5f79c20b8ef8ec89883290a3c3f4c547d4b17813 --- flags/hap.aconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/flags/hap.aconfig b/flags/hap.aconfig index 860774b7881..0780daf2387 100644 --- a/flags/hap.aconfig +++ b/flags/hap.aconfig @@ -25,3 +25,12 @@ flag { purpose: PURPOSE_BUGFIX } } + + +flag { + name: "aics_api" + is_exported: true + namespace: "bluetooth" + description: "Expose new API to control AICS data" + bug: "372328699" +} -- GitLab From 97da86f8f6d7daf2c5b6c1e996660a5e905cc79c Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 8 Oct 2024 17:10:47 -0700 Subject: [PATCH 221/875] VolumeControl: Unify RequiresPermission Bug: 372328699 Test: m . Flag: Exempt refactor Change-Id: I1167d29662cec468f49f6fa8df4c459f8c57badc --- .../bluetooth/BluetoothVolumeControl.java | 60 ++++--------------- 1 file changed, 10 insertions(+), 50 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index 4d8c4b2a6ac..04c2d8cacb9 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -326,11 +326,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothVolumeControl service = getService(); @@ -413,11 +409,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void registerCallback( @NonNull @CallbackExecutor Executor executor, @NonNull Callback callback) { Objects.requireNonNull(executor, "executor cannot be null"); @@ -477,11 +469,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull Callback callback) { Objects.requireNonNull(callback, "callback cannot be null"); if (DBG) log("unregisterCallback"); @@ -518,11 +506,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @Deprecated @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void setVolumeOffset( @NonNull BluetoothDevice device, @IntRange(from = -255, to = 255) int volumeOffset) { final int defaultInstanceId = 1; @@ -544,11 +528,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void setVolumeOffset( @NonNull BluetoothDevice device, @IntRange(from = 1, to = 255) int instanceId, @@ -610,11 +590,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean isVolumeOffsetAvailable(@NonNull BluetoothDevice device) { if (DBG) log("isVolumeOffsetAvailable(" + device + ")"); final IBluetoothVolumeControl service = getService(); @@ -646,11 +622,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getNumberOfVolumeOffsetInstances(@NonNull BluetoothDevice device) { if (DBG) log("getNumberOfVolumeOffsetInstances(" + device + ")"); final IBluetoothVolumeControl service = getService(); @@ -688,11 +660,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy( @NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); @@ -725,11 +693,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothVolumeControl service = getService(); @@ -767,11 +731,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES) @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void setDeviceVolume( @NonNull BluetoothDevice device, @IntRange(from = 0, to = 255) int volume, -- GitLab From c53f58b53938244ffab4c46abdadeb7a0a4a92a4 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 8 Oct 2024 17:12:43 -0700 Subject: [PATCH 222/875] VolumeControl: remove VDBG & DBG & log & isEnabled Bug: 372328699 Test: m . Flag: Exempt refactor Change-Id: If4d64f069d83356b32bd93993e3396b7ec9c8e52 --- .../bluetooth/BluetoothVolumeControl.java | 94 ++++++++----------- 1 file changed, 37 insertions(+), 57 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index 04c2d8cacb9..d14bcb1ca57 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -61,8 +61,6 @@ import java.util.function.Consumer; @SystemApi public final class BluetoothVolumeControl implements BluetoothProfile, AutoCloseable { private static final String TAG = "BluetoothVolumeControl"; - private static final boolean DBG = true; - private static final boolean VDBG = false; private CloseGuard mCloseGuard; @@ -276,7 +274,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose */ @Override public void close() { - if (VDBG) log("close()"); + Log.v(TAG, "close()"); mAdapter.closeProfileProxy(this); } @@ -328,12 +326,11 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull List getConnectedDevices() { - if (DBG) log("getConnectedDevices()"); + Log.d(TAG, "getConnectedDevices()"); final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (isEnabled()) { + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { try { return Attributable.setAttributionSource( service.getConnectedDevices(mAttributionSource), mAttributionSource); @@ -353,12 +350,11 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public List getDevicesMatchingConnectionStates(int[] states) { - if (DBG) log("getDevicesMatchingStates()"); + Log.d(TAG, "getDevicesMatchingStates()"); final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (isEnabled()) { + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { try { return Attributable.setAttributionSource( service.getDevicesMatchingConnectionStates(states, mAttributionSource), @@ -379,12 +375,11 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { - if (DBG) log("getConnectionState(" + device + ")"); + Log.d(TAG, "getConnectionState(" + device + ")"); final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (isEnabled() && isValidDevice(device)) { + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { try { return service.getConnectionState(device, mAttributionSource); } catch (RemoteException e) { @@ -414,7 +409,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @NonNull @CallbackExecutor Executor executor, @NonNull Callback callback) { Objects.requireNonNull(executor, "executor cannot be null"); Objects.requireNonNull(callback, "callback cannot be null"); - if (DBG) log("registerCallback"); + Log.d(TAG, "registerCallback"); synchronized (mCallbackExecutorMap) { if (!mAdapter.isEnabled()) { /* If Bluetooth is off, just store callback and it will be registered @@ -472,7 +467,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull Callback callback) { Objects.requireNonNull(callback, "callback cannot be null"); - if (DBG) log("unregisterCallback"); + Log.d(TAG, "unregisterCallback"); synchronized (mCallbackExecutorMap) { if (mCallbackExecutorMap.remove(callback) == null) { throw new IllegalArgumentException("This callback has not been registered"); @@ -556,21 +551,19 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @NonNull BluetoothDevice device, @IntRange(from = 1, to = 255) int instanceId, @IntRange(from = -255, to = 255) int volumeOffset) { - if (DBG) { - log( - "setVolumeOffset(" - + device - + "/" - + instanceId - + " volumeOffset: " - + volumeOffset - + ")"); - } + Log.d( + TAG, + "setVolumeOffset(" + + device + + "/" + + instanceId + + " volumeOffset: " + + volumeOffset + + ")"); final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (isEnabled()) { + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { try { service.setVolumeOffset(device, instanceId, volumeOffset, mAttributionSource); } catch (RemoteException e) { @@ -592,15 +585,14 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean isVolumeOffsetAvailable(@NonNull BluetoothDevice device) { - if (DBG) log("isVolumeOffsetAvailable(" + device + ")"); + Log.d(TAG, "isVolumeOffsetAvailable(" + device + ")"); final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); return false; } - if (!isEnabled()) { + if (!mAdapter.isEnabled()) { return false; } @@ -624,17 +616,16 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getNumberOfVolumeOffsetInstances(@NonNull BluetoothDevice device) { - if (DBG) log("getNumberOfVolumeOffsetInstances(" + device + ")"); + Log.d(TAG, "getNumberOfVolumeOffsetInstances(" + device + ")"); final IBluetoothVolumeControl service = getService(); final int defaultValue = 0; if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); return defaultValue; } - if (!isEnabled()) { + if (!mAdapter.isEnabled()) { return defaultValue; } try { @@ -663,12 +654,11 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy( @NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { - if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); + Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (isEnabled() + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device) && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { @@ -695,12 +685,11 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { - if (VDBG) log("getConnectionPolicy(" + device + ")"); + Log.v(TAG, "getConnectionPolicy(" + device + ")"); final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (isEnabled() && isValidDevice(device)) { + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { try { return service.getConnectionPolicy(device, mAttributionSource); } catch (RemoteException e) { @@ -741,9 +730,8 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose } final IBluetoothVolumeControl service = getService(); if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (isEnabled()) { + Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { try { service.setDeviceVolume(device, volume, isGroupOperation, mAttributionSource); } catch (RemoteException e) { @@ -752,15 +740,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose } } - private boolean isEnabled() { - return mAdapter.getState() == BluetoothAdapter.STATE_ON; - } - private static boolean isValidDevice(@Nullable BluetoothDevice device) { return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } - - private static void log(String msg) { - Log.d(TAG, msg); - } } -- GitLab From 0f17790af4da02d12325bd97c6c5578284622c7f Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Wed, 9 Oct 2024 09:36:01 +0800 Subject: [PATCH 223/875] floss: Rename DelayedActions to AdapterActions This enum was first introduced for some actions that were really "delayed", but now they no longer exist. This patterns is now widely used in the project so let's follow the common naming. Bug: None Tag: #floss Test: mmm packages/modules/Bluetooth Flag: EXEMPT, Floss-only change Change-Id: I00b6fa2e506c7754566e0c6e97678fdd75913ef3 --- system/gd/rust/linux/stack/src/bluetooth.rs | 44 +++++++++------------ system/gd/rust/linux/stack/src/lib.rs | 11 +++--- system/gd/rust/linux/stack/src/suspend.rs | 6 +-- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index f2a91d929fc..b93f70c64ef 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -308,8 +308,8 @@ pub trait IBluetoothQALegacy { fn send_hid_data(&mut self, addr: RawAddress, data: String) -> BtStatus; } -/// Delayed actions from adapter events. -pub enum DelayedActions { +/// Action events from lib.rs +pub enum AdapterActions { /// Check whether the current set of found devices are still fresh. DeviceFreshnessCheck, @@ -1092,22 +1092,22 @@ impl Bluetooth { ); } - /// Handle some delayed and recurring actions within the adapter. - pub(crate) fn handle_delayed_actions(&mut self, action: DelayedActions) { + /// Handle adapter actions. + pub(crate) fn handle_actions(&mut self, action: AdapterActions) { match action { - DelayedActions::DeviceFreshnessCheck => { + AdapterActions::DeviceFreshnessCheck => { self.trigger_freshness_check(); } - DelayedActions::ConnectAllProfiles(device) => { + AdapterActions::ConnectAllProfiles(device) => { self.connect_all_enabled_profiles(device); } - DelayedActions::ConnectProfiles(uuids, device) => { + AdapterActions::ConnectProfiles(uuids, device) => { self.connect_profiles_internal(&uuids, device); } - DelayedActions::BleDiscoveryScannerRegistered(uuid, scanner_id, status) => { + AdapterActions::BleDiscoveryScannerRegistered(uuid, scanner_id, status) => { if let Some(app_uuid) = self.ble_scanner_uuid { if app_uuid == uuid { if status == GattStatus::Success { @@ -1119,7 +1119,7 @@ impl Bluetooth { } } - DelayedActions::BleDiscoveryScannerResult(result) => { + AdapterActions::BleDiscoveryScannerResult(result) => { // Generate a vector of properties from ScanResult. let properties = { let mut props = vec![]; @@ -1164,11 +1164,11 @@ impl Bluetooth { )); } - DelayedActions::ResetDiscoverable => { + AdapterActions::ResetDiscoverable => { self.set_discoverable(BtDiscMode::NonDiscoverable, 0); } - DelayedActions::CreateBond => { + AdapterActions::CreateBond => { if let Some((device, transport)) = self.pending_create_bond.take() { let status = self.create_bond(device, transport); if status != BtStatus::Success { @@ -1335,9 +1335,7 @@ impl Bluetooth { let tx = self.tx.clone(); tokio::spawn(async move { let _ = tx - .send(Message::DelayedAdapterActions(DelayedActions::ConnectProfiles( - new_uuids, device, - ))) + .send(Message::AdapterActions(AdapterActions::ConnectProfiles(new_uuids, device))) .await; }); } @@ -1668,9 +1666,7 @@ impl BtifBluetoothCallbacks for Bluetooth { loop { time::sleep(FOUND_DEVICE_FRESHNESS).await; let _ = txl - .send(Message::DelayedAdapterActions( - DelayedActions::DeviceFreshnessCheck, - )) + .send(Message::AdapterActions(AdapterActions::DeviceFreshnessCheck)) .await; } })); @@ -1821,7 +1817,7 @@ impl BtifBluetoothCallbacks for Bluetooth { debug!("Invoking delayed CreateBond"); let tx = self.tx.clone(); tokio::spawn(async move { - let _ = tx.send(Message::DelayedAdapterActions(DelayedActions::CreateBond)).await; + let _ = tx.send(Message::AdapterActions(AdapterActions::CreateBond)).await; }); } } @@ -2173,9 +2169,9 @@ impl IScannerCallback for BleDiscoveryCallbacks { let tx = self.tx.clone(); tokio::spawn(async move { let _ = tx - .send(Message::DelayedAdapterActions( - DelayedActions::BleDiscoveryScannerRegistered(uuid, scanner_id, status), - )) + .send(Message::AdapterActions(AdapterActions::BleDiscoveryScannerRegistered( + uuid, scanner_id, status, + ))) .await; }); } @@ -2184,7 +2180,7 @@ impl IScannerCallback for BleDiscoveryCallbacks { let tx = self.tx.clone(); tokio::spawn(async move { let _ = tx - .send(Message::DelayedAdapterActions(DelayedActions::BleDiscoveryScannerResult( + .send(Message::AdapterActions(AdapterActions::BleDiscoveryScannerResult( scan_result, ))) .await; @@ -2339,9 +2335,7 @@ impl IBluetooth for Bluetooth { let txl = self.tx.clone(); self.discoverable_timeout = Some(tokio::spawn(async move { time::sleep(Duration::from_secs(duration.into())).await; - let _ = txl - .send(Message::DelayedAdapterActions(DelayedActions::ResetDiscoverable)) - .await; + let _ = txl.send(Message::AdapterActions(AdapterActions::ResetDiscoverable)).await; })); } diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs index 5cce842c8cd..95cface1470 100644 --- a/system/gd/rust/linux/stack/src/lib.rs +++ b/system/gd/rust/linux/stack/src/lib.rs @@ -31,8 +31,8 @@ use crate::battery_manager::{BatteryManager, BatterySet}; use crate::battery_provider_manager::BatteryProviderManager; use crate::battery_service::{BatteryService, BatteryServiceActions}; use crate::bluetooth::{ - dispatch_base_callbacks, dispatch_hid_host_callbacks, dispatch_sdp_callbacks, Bluetooth, - BluetoothDevice, DelayedActions, IBluetooth, + dispatch_base_callbacks, dispatch_hid_host_callbacks, dispatch_sdp_callbacks, AdapterActions, + Bluetooth, BluetoothDevice, IBluetooth, }; use crate::bluetooth_admin::{AdminActions, BluetoothAdmin, IBluetoothAdmin}; use crate::bluetooth_adv::{dispatch_le_adv_callbacks, AdvertiserActions}; @@ -105,8 +105,7 @@ pub enum Message { AdapterCallbackDisconnected(u32), ConnectionCallbackDisconnected(u32), - // Some delayed actions for the adapter. - DelayedAdapterActions(DelayedActions), + AdapterActions(AdapterActions), // Follows IBluetooth's on_device_(dis)connected and bond_state callbacks // but doesn't require depending on Bluetooth. @@ -429,8 +428,8 @@ impl Stack { bluetooth.lock().unwrap().connection_callback_disconnected(id); } - Message::DelayedAdapterActions(action) => { - bluetooth.lock().unwrap().handle_delayed_actions(action); + Message::AdapterActions(action) => { + bluetooth.lock().unwrap().handle_actions(action); } // Any service needing an updated list of devices can have an diff --git a/system/gd/rust/linux/stack/src/suspend.rs b/system/gd/rust/linux/stack/src/suspend.rs index 04902c588c3..97dc4aa8797 100644 --- a/system/gd/rust/linux/stack/src/suspend.rs +++ b/system/gd/rust/linux/stack/src/suspend.rs @@ -1,6 +1,6 @@ //! Suspend/Resume API. -use crate::bluetooth::{Bluetooth, BluetoothDevice, BtifBluetoothCallbacks, DelayedActions}; +use crate::bluetooth::{AdapterActions, Bluetooth, BluetoothDevice, BtifBluetoothCallbacks}; use crate::bluetooth_media::BluetoothMedia; use crate::callbacks::Callbacks; use crate::{BluetoothGatt, Message, RPCProxy}; @@ -337,9 +337,7 @@ impl ISuspend for Suspend { // Queue up connections. for device in reconnect_list { let _unused: Option<()> = txl - .send(Message::DelayedAdapterActions(DelayedActions::ConnectAllProfiles( - device, - ))) + .send(Message::AdapterActions(AdapterActions::ConnectAllProfiles(device))) .await .ok(); } -- GitLab From 8536b37cee22c7c9b97701840ccc2134937ca644 Mon Sep 17 00:00:00 2001 From: Yi Kong Date: Thu, 3 Oct 2024 21:01:20 +0900 Subject: [PATCH 224/875] Fix build with fmtlib 11.0.2 Test: presubmit Test: m fmtlib Bug: 371149965 Change-Id: I72130decc245a9e52a9055685c96c78ebbb636bf --- system/log/include/bluetooth/log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/log/include/bluetooth/log.h b/system/log/include/bluetooth/log.h index 45ab7d93772..b8921c6f1cf 100644 --- a/system/log/include/bluetooth/log.h +++ b/system/log/include/bluetooth/log.h @@ -17,7 +17,7 @@ #pragma once #include -#include +#include #include #ifndef LOG_TAG -- GitLab From 63df5cecb55866d11293bfb43620d4b7de0ef264 Mon Sep 17 00:00:00 2001 From: Etienne Ruffieux Date: Thu, 3 Oct 2024 15:26:57 +0000 Subject: [PATCH 225/875] Handle error response for GetTotalNumberOfItems If no player has been set as addressed, we need to return an error response, same for browsed player. Bug: 346717077 Flag: exempt trivial Test: atest BluetoothInstrumentationTests Change-Id: I5f184e8fc2a4d5e10d3bc59a8adfe645c44824ba --- system/profile/avrcp/device.cc | 17 +++++++++++++++++ system/profile/avrcp/device.h | 1 + system/profile/avrcp/tests/avrcp_device_test.cc | 6 +++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index 1851e88d346..fccf820d77f 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -725,6 +725,7 @@ void Device::AddressedPlayerNotificationResponse(uint8_t label, bool interim, if (curr_browsed_player_id_ == -1) { curr_browsed_player_id_ = curr_player; } + curr_addressed_player_id_ = curr_player; auto response = RegisterNotificationResponseBuilder::MakeAddressedPlayerBuilder( interim, curr_player, 0x0000); @@ -937,6 +938,8 @@ void Device::HandleSetAddressedPlayer(uint8_t label, std::shared_ptr list) { log::verbose("num_items={}", list.size()); + if (curr_browsed_player_id_ == -1) { + auto response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::NO_AVAILABLE_PLAYERS, + 0x0000, 0); + send_message(label, true, std::move(response)); + return; + } + auto builder = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::NO_ERROR, 0x0000, list.size()); send_message(label, true, std::move(builder)); @@ -1135,6 +1145,13 @@ void Device::GetTotalNumberOfItemsNowPlayingResponse(uint8_t label, std::string std::vector list) { log::verbose("num_items={}", list.size()); + if (curr_addressed_player_id_ == -1) { + auto response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::NO_AVAILABLE_PLAYERS, + 0x0000, 0); + send_message(label, true, std::move(response)); + return; + } + auto builder = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::NO_ERROR, 0x0000, list.size()); send_message(label, true, std::move(builder)); diff --git a/system/profile/avrcp/device.h b/system/profile/avrcp/device.h index 437c85a94f7..67dffbad8bf 100644 --- a/system/profile/avrcp/device.h +++ b/system/profile/avrcp/device.h @@ -341,6 +341,7 @@ private: bool has_bip_client_; int curr_browsed_player_id_ = -1; + int curr_addressed_player_id_ = -1; std::stack current_path_; diff --git a/system/profile/avrcp/tests/avrcp_device_test.cc b/system/profile/avrcp/tests/avrcp_device_test.cc index 24cf0ff87df..a33046f7057 100644 --- a/system/profile/avrcp/tests/avrcp_device_test.cc +++ b/system/profile/avrcp/tests/avrcp_device_test.cc @@ -744,7 +744,7 @@ TEST_F(AvrcpDeviceTest, getTotalNumberOfItemsVFSTest) { EXPECT_CALL(interface, GetFolderItems(_, "", _)).Times(1).WillOnce(InvokeCb<2>(vfs_list)); auto expected_response = - GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::NO_ERROR, 0, vfs_list.size()); + GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::NO_AVAILABLE_PLAYERS, 0, 0); EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(expected_response)))).Times(1); SendBrowseMessage(1, TestBrowsePacket::Make(get_total_number_of_items_request_vfs)); @@ -763,8 +763,8 @@ TEST_F(AvrcpDeviceTest, getTotalNumberOfItemsNowPlayingTest) { EXPECT_CALL(interface, GetNowPlayingList(_)) .WillRepeatedly(InvokeCb<0>("test_id1", now_playing_list)); - auto expected_response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder( - Status::NO_ERROR, 0, now_playing_list.size()); + auto expected_response = + GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::NO_AVAILABLE_PLAYERS, 0, 0); EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(expected_response)))).Times(1); SendBrowseMessage(1, TestBrowsePacket::Make(get_total_number_of_items_request_now_playing)); -- GitLab From ee61f7e64ad4dde7e2b5c261cffad9b20f95d7fe Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Wed, 9 Oct 2024 15:42:20 +0800 Subject: [PATCH 226/875] floss: Mark controller as broken if we got INVALID_FD in Start() This avoid crashing on sendHciCommand Bug: 372336294 Tag: #floss Test: mmm packages/modules/Bluetooth Flag: EXEMPT, Floss-only change Change-Id: Ifa1c50fe5e0e5344a0e252d5a3132570929dd60c --- system/gd/hal/hci_hal_host.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc index 579d2183f72..c6bba6968ad 100644 --- a/system/gd/hal/hci_hal_host.cc +++ b/system/gd/hal/hci_hal_host.cc @@ -149,7 +149,7 @@ int waitHciDev(int hci_interface) { if (n < 0) { bluetooth::log::error("Error reading control channel: {}", strerror(errno)); break; - } else if (n == 0) { // unlikely to happen, just a safeguard. + } else if (n == 0) { // unlikely to happen, just a safeguard. bluetooth::log::error("Error reading control channel: EOF"); break; } @@ -339,6 +339,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); return; } -- GitLab From 2afc798522fb71273ac5d8879c491f2074053cd3 Mon Sep 17 00:00:00 2001 From: Bhakthavatsala Raghavendra Date: Wed, 25 Sep 2024 22:29:36 +0000 Subject: [PATCH 227/875] Add flag to avoid waiting for lea discovery when there is no le acl Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.wait_for_lea_disc_on_le_acl_stat Bug: 369687005 Bug: 315241296 Change-Id: I4e924210fd47340fbc4c1deb98d06922d6751dc8 --- flags/pairing.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig index 0aa5e694254..8acd9afbc72 100644 --- a/flags/pairing.aconfig +++ b/flags/pairing.aconfig @@ -177,3 +177,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "wait_for_lea_disc_on_le_acl_stat" + namespace: "bluetooth" + description: "Check for LE ACL status before waiting on LEA discovery" + bug: "369687005" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 45242a22cbc4dcb8a361095dfc9e68f18642268e Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Wed, 9 Oct 2024 17:41:16 +0000 Subject: [PATCH 228/875] mmi2grpc: remove typo in license Bug: 371207046 Test: atest pts-bot Change-Id: I0fa25eca8a9db9032f46532fc61a726f4ca06813 --- android/pandora/mmi2grpc/mmi2grpc/hap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/pandora/mmi2grpc/mmi2grpc/hap.py b/android/pandora/mmi2grpc/mmi2grpc/hap.py index 82b0ad92447..c69dea323bc 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/hap.py +++ b/android/pandora/mmi2grpc/mmi2grpc/hap.py @@ -10,7 +10,7 @@ # 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.ś +# limitations under the License. import threading import uuid -- GitLab From b58cae3d8cab0be3cacdad268c4e7c0d6eaa3e00 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Wed, 9 Oct 2024 16:25:47 +0000 Subject: [PATCH 229/875] Makes the ras code run in the BT main thread. Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 372468999 Test: m com.android.btservice Change-Id: If935b737d59ab1dc3b87d1eae9ca42c80ffb8652 --- system/bta/ras/ras_client.cc | 5 +++ system/bta/ras/ras_server.cc | 5 +++ .../main/shim/distance_measurement_manager.cc | 42 +++++++++++-------- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/system/bta/ras/ras_client.cc b/system/bta/ras/ras_client.cc index 093dfe02657..a486d118d51 100644 --- a/system/bta/ras/ras_client.cc +++ b/system/bta/ras/ras_client.cc @@ -26,6 +26,7 @@ #include "stack/include/bt_types.h" #include "stack/include/btm_ble_addr.h" #include "stack/include/gap_api.h" +#include "stack/include/main_thread.h" using namespace bluetooth; using namespace ::ras; @@ -102,6 +103,10 @@ public: }; void Initialize() override { + do_in_main_thread(base::BindOnce(&RasClientImpl::do_initialize, base::Unretained(this))); + } + + void do_initialize() { auto controller = bluetooth::shim::GetController(); if (controller && !controller->SupportsBleChannelSounding()) { log::info("controller does not support channel sounding."); diff --git a/system/bta/ras/ras_server.cc b/system/bta/ras/ras_server.cc index a9a290949ae..0ecf5ef1042 100644 --- a/system/bta/ras/ras_server.cc +++ b/system/bta/ras/ras_server.cc @@ -30,6 +30,7 @@ #include "os/logging/log_adapter.h" #include "stack/include/bt_types.h" #include "stack/include/btm_ble_addr.h" +#include "stack/include/main_thread.h" using namespace bluetooth; using namespace ::ras; @@ -77,6 +78,10 @@ public: }; void Initialize() override { + do_in_main_thread(base::BindOnce(&RasServerImpl::do_initialize, base::Unretained(this))); + } + + void do_initialize() { auto controller = bluetooth::shim::GetController(); if (controller && !controller->SupportsBleChannelSounding()) { log::info("controller does not support channel sounding."); diff --git a/system/main/shim/distance_measurement_manager.cc b/system/main/shim/distance_measurement_manager.cc index 0cc8ea429e9..2ecdbdc9431 100644 --- a/system/main/shim/distance_measurement_manager.cc +++ b/system/main/shim/distance_measurement_manager.cc @@ -41,8 +41,10 @@ public: void Init() { // Register callback bluetooth::shim::GetDistanceMeasurementManager()->RegisterDistanceMeasurementCallbacks(this); - bluetooth::ras::GetRasServer()->RegisterCallbacks(this); - bluetooth::ras::GetRasClient()->RegisterCallbacks(this); + do_in_main_thread(base::BindOnce(&bluetooth::ras::RasServer::RegisterCallbacks, + base::Unretained(bluetooth::ras::GetRasServer()), this)); + do_in_main_thread(base::BindOnce(&bluetooth::ras::RasClient::RegisterCallbacks, + base::Unretained(bluetooth::ras::GetRasClient()), this)); } /** @@ -50,7 +52,8 @@ public: * @param bd_addr could be random, rpa or identity address. * @return BLE ACL handle */ - uint16_t GetConnectionHandleAndRole(const RawAddress& bd_addr, hci::Role* hci_role = nullptr) { + static uint16_t GetConnectionHandleAndRole(const RawAddress& bd_addr, + hci::Role* hci_role = nullptr) { tBTM_SEC_DEV_REC* p_sec_dev_rec = btm_find_dev(bd_addr); if (p_sec_dev_rec != nullptr) { if (hci_role != nullptr) { @@ -71,8 +74,7 @@ public: } void DoStartDistanceMeasurement(RawAddress identity_addr, uint16_t interval, uint8_t method) { - DistanceMeasurementMethod distance_measurement_method = - static_cast(method); + auto distance_measurement_method = static_cast(method); hci::Role local_hci_role; uint16_t connection_handle = GetConnectionHandleAndRole(identity_addr, &local_hci_role); bluetooth::shim::GetDistanceMeasurementManager()->StartDistanceMeasurement( @@ -134,13 +136,15 @@ public: } void OnRasFragmentReady(bluetooth::hci::Address address, uint16_t procedure_counter, bool is_last, - std::vector raw_data) { - bluetooth::ras::GetRasServer()->PushProcedureData(bluetooth::ToRawAddress(address), - procedure_counter, is_last, raw_data); + std::vector raw_data) override { + do_in_main_thread(base::BindOnce(&bluetooth::ras::RasServer::PushProcedureData, + base::Unretained(bluetooth::ras::GetRasServer()), + bluetooth::ToRawAddress(address), procedure_counter, is_last, + std::move(raw_data))); } void OnVendorSpecificCharacteristics(std::vector - vendor_specific_characteristics) { + vendor_specific_characteristics) override { std::vector ras_vendor_specific_characteristics; for (auto& characteristic : vendor_specific_characteristics) { bluetooth::ras::VendorSpecificCharacteristic vendor_specific_characteristic; @@ -149,13 +153,14 @@ public: vendor_specific_characteristic.value_ = characteristic.value_; ras_vendor_specific_characteristics.emplace_back(vendor_specific_characteristic); } - bluetooth::ras::GetRasServer()->SetVendorSpecificCharacteristic( - ras_vendor_specific_characteristics); + do_in_main_thread(base::BindOnce(&bluetooth::ras::RasServer::SetVendorSpecificCharacteristic, + base::Unretained(bluetooth::ras::GetRasServer()), + std::move(ras_vendor_specific_characteristics))); } void OnVendorSpecificReply(bluetooth::hci::Address address, std::vector - vendor_specific_characteristics) { + vendor_specific_characteristics) override { std::vector ras_vendor_specific_characteristics; for (auto& characteristic : vendor_specific_characteristics) { bluetooth::ras::VendorSpecificCharacteristic vendor_specific_characteristic; @@ -164,13 +169,16 @@ public: vendor_specific_characteristic.value_ = characteristic.value_; ras_vendor_specific_characteristics.emplace_back(vendor_specific_characteristic); } - bluetooth::ras::GetRasClient()->SendVendorSpecificReply(bluetooth::ToRawAddress(address), - ras_vendor_specific_characteristics); + do_in_main_thread(base::BindOnce(&bluetooth::ras::RasClient::SendVendorSpecificReply, + base::Unretained(bluetooth::ras::GetRasClient()), + bluetooth::ToRawAddress(address), + std::move(ras_vendor_specific_characteristics))); } - void OnHandleVendorSpecificReplyComplete(bluetooth::hci::Address address, bool success) { - bluetooth::ras::GetRasServer()->HandleVendorSpecificReplyComplete( - bluetooth::ToRawAddress(address), success); + void OnHandleVendorSpecificReplyComplete(bluetooth::hci::Address address, bool success) override { + do_in_main_thread(base::BindOnce(&bluetooth::ras::RasServer::HandleVendorSpecificReplyComplete, + base::Unretained(bluetooth::ras::GetRasServer()), + bluetooth::ToRawAddress(address), success)); } // Must be called from main_thread -- GitLab From ffe765cffce4ec3815e4f8ccbdb6bfd305ef01d8 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 9 Oct 2024 10:48:05 -0700 Subject: [PATCH 230/875] system/btif: Remove unused method MediaCallbacks::SendActiveDeviceChanged Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: I5c77108fdb691f5ee4b6feb7940fff6335717105 --- system/btif/avrcp/avrcp_service.cc | 5 ----- system/btif/avrcp/avrcp_service.h | 1 - system/btif/test/btif_rc_test.cc | 1 - system/include/hardware/avrcp/avrcp.h | 2 -- 4 files changed, 9 deletions(-) diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc index 871177bff30..577628eb2b0 100644 --- a/system/btif/avrcp/avrcp_service.cc +++ b/system/btif/avrcp/avrcp_service.cc @@ -578,11 +578,6 @@ void AvrcpService::SendFolderUpdate(bool available_players, bool addressed_playe } } -// Send out the track changed info to update the playback state for each device -void AvrcpService::SendActiveDeviceChanged(const RawAddress& /*address*/) { - SendMediaUpdate(false, true, false); -} - void AvrcpService::SendPlayerSettingsChanged(std::vector attributes, std::vector values) { if (attributes.size() != values.size()) { diff --git a/system/btif/avrcp/avrcp_service.h b/system/btif/avrcp/avrcp_service.h index 956040c0617..5c4974ac97e 100644 --- a/system/btif/avrcp/avrcp_service.h +++ b/system/btif/avrcp/avrcp_service.h @@ -70,7 +70,6 @@ public: // Functions inherited from MediaCallbacks in order to receive updates void SendMediaUpdate(bool track_changed, bool play_state, bool queue) override; void SendFolderUpdate(bool available_players, bool addressed_player, bool queue) override; - void SendActiveDeviceChanged(const RawAddress& address) override; void SendPlayerSettingsChanged(std::vector attributes, std::vector values) override; diff --git a/system/btif/test/btif_rc_test.cc b/system/btif/test/btif_rc_test.cc index 7ac956920c9..0de07934294 100644 --- a/system/btif/test/btif_rc_test.cc +++ b/system/btif/test/btif_rc_test.cc @@ -43,7 +43,6 @@ AvrcpService* AvrcpService::instance_ = nullptr; void AvrcpService::SendMediaUpdate(bool /*track_changed*/, bool /*play_state*/, bool /*queue*/) {} void AvrcpService::SendFolderUpdate(bool /*available_players*/, bool /*addressed_players*/, bool /*uids*/) {} -void AvrcpService::SendActiveDeviceChanged(const RawAddress& /*address*/) {} void AvrcpService::SendPlayerSettingsChanged(std::vector /*attributes*/, std::vector /*values*/) {} void AvrcpService::ServiceInterfaceImpl::Init( diff --git a/system/include/hardware/avrcp/avrcp.h b/system/include/hardware/avrcp/avrcp.h index 2698cc9f9ab..13b937500c4 100644 --- a/system/include/hardware/avrcp/avrcp.h +++ b/system/include/hardware/avrcp/avrcp.h @@ -76,8 +76,6 @@ public: virtual void SendMediaUpdate(bool track_changed, bool play_state, bool queue) = 0; virtual void SendFolderUpdate(bool available_players, bool addressed_players, bool uids_changed) = 0; - virtual void SendActiveDeviceChanged(const RawAddress& address) = 0; - virtual void SendPlayerSettingsChanged(std::vector attributes, std::vector values) = 0; virtual ~MediaCallbacks() = default; -- GitLab From 88d714b94023ef3c950771256d6efa500ba67990 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 9 Oct 2024 11:40:52 -0700 Subject: [PATCH 231/875] system/bta: Remove no-op method bta_ar_avdt_conn Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: Ifb1081e83a2e468a25e1d2c7a75717a19070c126 --- system/bta/ar/bta_ar.cc | 15 --------------- system/bta/av/bta_av_aact.cc | 1 - system/bta/include/bta_ar_api.h | 14 -------------- system/test/mock/mock_bta_ar.cc | 4 ---- 4 files changed, 34 deletions(-) diff --git a/system/bta/ar/bta_ar.cc b/system/bta/ar/bta_ar.cc index 4602930ec9b..c3fade48b60 100644 --- a/system/bta/ar/bta_ar.cc +++ b/system/bta/ar/bta_ar.cc @@ -148,21 +148,6 @@ void bta_ar_dereg_avdt() { } } -/******************************************************************************* - * - * Function bta_ar_avdt_conn - * - * Description This function is called to let ar know that some AVDTP - * profile is connected for this sys_id. - * If the other sys modules started a timer for PENDING_EVT, - * the timer can be stopped now. - * - * Returns void - * - ******************************************************************************/ -void bta_ar_avdt_conn(tBTA_SYS_ID /*sys_id*/, const RawAddress& /*bd_addr*/, - uint8_t /*scb_index*/) {} - /******************************************************************************* * * Function bta_ar_reg_avct diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index 4adc3e2d6fa..4479296dd50 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -1227,7 +1227,6 @@ void bta_av_str_opened(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { } } } - bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr, p_scb->hdi); if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC) { open.starting = false; open.sep = AVDT_TSEP_SNK; diff --git a/system/bta/include/bta_ar_api.h b/system/bta/include/bta_ar_api.h index c6c95f2b56a..6cb74c0a335 100644 --- a/system/bta/include/bta_ar_api.h +++ b/system/bta/include/bta_ar_api.h @@ -72,20 +72,6 @@ void bta_ar_reg_avdt(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback); ******************************************************************************/ void bta_ar_dereg_avdt(); -/******************************************************************************* - * - * Function bta_ar_avdt_conn - * - * Description This function is called to let ar know that some AVDTP - * profile is connected for this sys_id. - * If the other sys modules started a timer for PENDING_EVT, - * the timer can be stopped now. - * - * Returns void - * - ******************************************************************************/ -void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr, uint8_t scb_index); - /******************************************************************************* * * Function bta_ar_reg_avct diff --git a/system/test/mock/mock_bta_ar.cc b/system/test/mock/mock_bta_ar.cc index a75e40fa055..b0b181e6d85 100644 --- a/system/test/mock/mock_bta_ar.cc +++ b/system/test/mock/mock_bta_ar.cc @@ -29,10 +29,6 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -void bta_ar_avdt_conn(tBTA_SYS_ID /* sys_id */, const RawAddress& /* bd_addr */, - uint8_t /* scb_index */) { - inc_func_call_count(__func__); -} void bta_ar_dereg_avct() { inc_func_call_count(__func__); } void bta_ar_dereg_avdt() { inc_func_call_count(__func__); } void bta_ar_dereg_avrc(uint16_t /* service_uuid */) { inc_func_call_count(__func__); } -- GitLab From 80ff0317b10dfc40ed8b9e3d3477225fcf43aade Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 9 Oct 2024 11:49:24 -0700 Subject: [PATCH 232/875] system/btif: Remove unused parameters Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: I4f6fc40d7e8eca439901025a565ef4ef8d96b745 --- system/bta/ag/bta_ag_cmd.cc | 8 ++++---- system/bta/ag/bta_ag_int.h | 4 ++-- system/bta/ag/bta_ag_sco.cc | 2 +- system/bta/ag/bta_ag_swb_aptx.cc | 4 ++-- system/btif/co/bta_av_co.cc | 2 +- system/btif/co/bta_av_co_peer.cc | 3 +-- system/btif/include/bta_av_co_peer.h | 4 +--- system/btif/src/btif_rc.cc | 2 -- 8 files changed, 12 insertions(+), 17 deletions(-) diff --git a/system/bta/ag/bta_ag_cmd.cc b/system/bta/ag/bta_ag_cmd.cc index 27ff562fb45..75e9bfb22a2 100644 --- a/system/bta/ag/bta_ag_cmd.cc +++ b/system/bta/ag/bta_ag_cmd.cc @@ -456,7 +456,7 @@ static uint8_t bta_ag_parse_chld(tBTA_AG_SCB* /* p_scb */, char* p_s) { * Returns Returns bitmap of supported codecs. * ******************************************************************************/ -static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB* /*p_scb*/, char* p_s, char* p_end) { +static tBTA_AG_PEER_CODEC bta_ag_parse_bac(char* p_s, char* p_end) { tBTA_AG_PEER_CODEC retval = BTM_SCO_CODEC_NONE; tBTA_AG_UUID_CODEC uuid_codec; char* p; @@ -1246,7 +1246,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB* p_scb, uint16_t cmd, uint8_t arg_type, cha /* store available codecs from the peer */ if ((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && (p_scb->features & BTA_AG_FEAT_CODEC)) { - p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg, p_end); + p_scb->peer_codecs = bta_ag_parse_bac(p_arg, p_end); p_scb->codec_updated = true; bool wbs_supported = hfp_hal_interface::get_wbs_supported(); @@ -1953,7 +1953,7 @@ void bta_ag_send_ring(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) { * Returns void * ******************************************************************************/ -void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* /*p_data*/) { +void bta_ag_send_qcs(tBTA_AG_SCB* p_scb) { tBTA_AG_UUID_CODEC codec_uuid; if (p_scb->codec_fallback) { if (p_scb->peer_codecs & BTM_SCO_CODEC_MSBC) { @@ -1978,7 +1978,7 @@ void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* /*p_data*/) { * Returns void * ******************************************************************************/ -void bta_ag_send_qac(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* /*p_data*/) { +void bta_ag_send_qac(tBTA_AG_SCB* p_scb) { if (!get_swb_codec_status(bluetooth::headset::BTHF_SWB_CODEC_VENDOR_APTX, &p_scb->peer_addr)) { log::verbose("send +QAC codecs unsupported"); bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_QAC, SWB_CODECS_UNSUPPORTED, 0); diff --git a/system/bta/ag/bta_ag_int.h b/system/bta/ag/bta_ag_int.h index 0b673a24d59..2173d86d62d 100644 --- a/system/bta/ag/bta_ag_int.h +++ b/system/bta/ag/bta_ag_int.h @@ -458,8 +458,8 @@ void bta_ag_set_sco_offload_enabled(bool value); void bta_ag_set_sco_allowed(bool value); const RawAddress& bta_ag_get_active_device(); void bta_clear_active_device(); -void bta_ag_send_qac(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data); -void bta_ag_send_qcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data); +void bta_ag_send_qac(tBTA_AG_SCB* p_scb); +void bta_ag_send_qcs(tBTA_AG_SCB* p_scb); /** * Check if SCO is managed by Audio is enabled. This is set via the system property * bluetooth.sco.managed_by_audio. diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index 4a7a58393ab..c9b30693cdc 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -716,7 +716,7 @@ void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb) { log::verbose("Sending +QCS, sco_codec={}, is_aptx_swb_codec={}", p_scb->sco_codec, p_scb->is_aptx_swb_codec); /* Send +QCS to the peer */ - bta_ag_send_qcs(p_scb, NULL); + bta_ag_send_qcs(p_scb); } else { if (aptx_voice) { p_scb->sco_codec = BTM_SCO_CODEC_MSBC; diff --git a/system/bta/ag/bta_ag_swb_aptx.cc b/system/bta/ag/bta_ag_swb_aptx.cc index 5090896050a..c0fbee80316 100644 --- a/system/bta/ag/bta_ag_swb_aptx.cc +++ b/system/bta/ag/bta_ag_swb_aptx.cc @@ -85,7 +85,7 @@ void bta_ag_swb_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t in case BTA_AG_AT_QAC_EVT: if (!get_swb_codec_status(bluetooth::headset::BTHF_SWB_CODEC_VENDOR_APTX, &p_scb->peer_addr)) { - bta_ag_send_qac(p_scb, NULL); + bta_ag_send_qac(p_scb); break; } log::verbose("BTA_AG_AT_QAC_EVT"); @@ -95,7 +95,7 @@ void bta_ag_swb_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t in } else if (p_scb->peer_codecs & BTM_SCO_CODEC_MSBC) { p_scb->sco_codec = BTM_SCO_CODEC_MSBC; } - bta_ag_send_qac(p_scb, NULL); + bta_ag_send_qac(p_scb); log::verbose("Received AT+QAC, updating sco codec to SWB: {}", p_scb->sco_codec); val->num = p_scb->peer_codecs; break; diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index 7805782e048..de0f9066046 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -91,7 +91,7 @@ void BtaAvCo::Init(const std::vector& codec_priorities // Reset the control block Reset(); - peer_cache_->Init(codec_priorities, supported_codecs); + peer_cache_->Init(codec_priorities); // Gather the supported codecs from the first peer context; // all contexes should be identical. diff --git a/system/btif/co/bta_av_co_peer.cc b/system/btif/co/bta_av_co_peer.cc index de3f41e10f7..5f9356cd4ca 100644 --- a/system/btif/co/bta_av_co_peer.cc +++ b/system/btif/co/bta_av_co_peer.cc @@ -97,8 +97,7 @@ void BtaAvCoPeer::setCodecConfig(const uint8_t* new_codec_config) { memcpy(codec_config, new_codec_config, AVDT_CODEC_SIZE); } -void BtaAvCoPeerCache::Init(const std::vector& codec_priorities, - std::vector* /*supported_codecs*/) { +void BtaAvCoPeerCache::Init(const std::vector& codec_priorities) { std::lock_guard lock(codec_lock_); codec_priorities_ = codec_priorities; diff --git a/system/btif/include/bta_av_co_peer.h b/system/btif/include/bta_av_co_peer.h index e421934501b..f66e86bc546 100644 --- a/system/btif/include/bta_av_co_peer.h +++ b/system/btif/include/bta_av_co_peer.h @@ -134,10 +134,8 @@ public: /** * Inits the cache with the appropriate data. * @param codec_priorities codec priorities. - * @param supported_codecs supported codecs by the stack. */ - void Init(const std::vector& codec_priorities, - std::vector* supported_codecs); + void Init(const std::vector& codec_priorities); /** * Resets the cache and the peer data. diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index 50ecb6a1402..cf6ffe20bce 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -513,8 +513,6 @@ void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs, } } -void rc_cleanup_sent_cmd(void* /*p_data*/) { log::verbose(""); } - void handle_rc_ctrl_features_all(btif_rc_device_cb_t* p_dev) { if (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCTG) && (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCCT) || -- GitLab From a2e3a18730c1e37ed1ffcbac2d7cb5e473dfa681 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Wed, 9 Oct 2024 15:08:36 +0200 Subject: [PATCH 233/875] Use default value instead of override for acl_create_le_connection_with_id Bug: 372202918 Test: mma -j32 Flag: EXEMPT, trivial Change-Id: If4b2d25fad63d1eecd696d780c6526e29c8691e8 --- system/stack/acl/btm_acl.cc | 4 ---- system/stack/include/l2cap_acl_interface.h | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 6d0e5d8a06c..c99ab7fcfc0 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -2494,10 +2494,6 @@ bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, return true; } -bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr) { - return acl_create_le_connection_with_id(id, bd_addr, BLE_ADDR_PUBLIC); -} - bool acl_create_le_connection(const RawAddress& bd_addr) { return acl_create_le_connection_with_id(CONN_MGR_ID_L2CAP, bd_addr); } diff --git a/system/stack/include/l2cap_acl_interface.h b/system/stack/include/l2cap_acl_interface.h index cb779da519c..026724817e1 100644 --- a/system/stack/include/l2cap_acl_interface.h +++ b/system/stack/include/l2cap_acl_interface.h @@ -26,9 +26,8 @@ // This header contains functions for L2cap-ACL to invoke // bool acl_create_le_connection(const RawAddress& bd_addr); -bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr); bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, - tBLE_ADDR_TYPE addr_type); + tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC); void acl_send_data_packet_br_edr(const RawAddress& bd_addr, BT_HDR* p_buf); void acl_send_data_packet_ble(const RawAddress& bd_addr, BT_HDR* p_buf); void acl_write_automatic_flush_timeout(const RawAddress& bd_addr, uint16_t flush_timeout); -- GitLab From 9a5b6b8dab52df8fbd99c57357fd03c7f080a1d6 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Wed, 9 Oct 2024 16:20:10 +0200 Subject: [PATCH 234/875] Remove acl_create_le_connection It's just another version of acl_create_le_connection_with_id. Having just one method with mocks for that is enough. Bug: 372202918 Test: mma -j32 Flag: EXEMPT, trivial Change-Id: If88160675537dbbe190f423bada13d67f6a36a41 --- system/stack/acl/btm_acl.cc | 4 ---- system/stack/fuzzers/l2cap_fuzzer.cc | 9 +++++---- system/stack/include/l2cap_acl_interface.h | 1 - system/stack/l2cap/l2c_ble.cc | 2 +- system/test/mock/mock_stack_acl.cc | 5 ----- system/test/mock/mock_stack_acl.h | 9 --------- 6 files changed, 6 insertions(+), 24 deletions(-) diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index c99ab7fcfc0..d88f4471605 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -2494,10 +2494,6 @@ bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, return true; } -bool acl_create_le_connection(const RawAddress& bd_addr) { - return acl_create_le_connection_with_id(CONN_MGR_ID_L2CAP, bd_addr); -} - void acl_rcv_acl_data(BT_HDR* p_msg) { acl_header_t acl_header{ .handle = HCI_INVALID_HANDLE, diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc index 74b3590a45a..d9793509b43 100644 --- a/system/stack/fuzzers/l2cap_fuzzer.cc +++ b/system/stack/fuzzers/l2cap_fuzzer.cc @@ -100,9 +100,10 @@ namespace { class FakeBtStack { public: FakeBtStack() { - test::mock::stack_acl::acl_create_le_connection.body = [](const RawAddress& /*bd_addr*/) { - return true; - }; + test::mock::stack_acl::acl_create_le_connection_with_id.body = + [](uint8_t /* id */, const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */) { + return true; + }; test::mock::stack_acl::acl_send_data_packet_br_edr.body = [](const RawAddress& /*bd_addr*/, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); @@ -131,7 +132,7 @@ public: } ~FakeBtStack() { - test::mock::stack_acl::acl_create_le_connection = {}; + test::mock::stack_acl::acl_create_le_connection_with_id = {}; 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; diff --git a/system/stack/include/l2cap_acl_interface.h b/system/stack/include/l2cap_acl_interface.h index 026724817e1..7e4a17dc466 100644 --- a/system/stack/include/l2cap_acl_interface.h +++ b/system/stack/include/l2cap_acl_interface.h @@ -25,7 +25,6 @@ // This header contains functions for L2cap-ACL to invoke // -bool acl_create_le_connection(const RawAddress& bd_addr); bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC); void acl_send_data_packet_br_edr(const RawAddress& bd_addr, BT_HDR* p_buf); diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index e2a1fbceff9..92753f8049b 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -926,7 +926,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { /** This function is to initate a direct connection. Returns true if connection * initiated, false otherwise. */ bool l2cble_create_conn(tL2C_LCB* p_lcb) { - if (!acl_create_le_connection(p_lcb->remote_bd_addr)) { + if (!acl_create_le_connection_with_id(CONN_MGR_ID_L2CAP, p_lcb->remote_bd_addr)) { return false; } diff --git a/system/test/mock/mock_stack_acl.cc b/system/test/mock/mock_stack_acl.cc index 22822f2f89c..c5989b3bbd0 100644 --- a/system/test/mock/mock_stack_acl.cc +++ b/system/test/mock/mock_stack_acl.cc @@ -48,7 +48,6 @@ struct BTM_IsAclConnectionUp BTM_IsAclConnectionUp; struct BTM_IsBleConnection BTM_IsBleConnection; struct BTM_ReadRemoteConnectionAddr BTM_ReadRemoteConnectionAddr; struct BTM_is_sniff_allowed_for BTM_is_sniff_allowed_for; -struct acl_create_le_connection acl_create_le_connection; struct acl_create_le_connection_with_id acl_create_le_connection_with_id; struct acl_is_role_switch_allowed acl_is_role_switch_allowed; struct acl_is_switch_role_idle acl_is_switch_role_idle; @@ -153,10 +152,6 @@ bool BTM_is_sniff_allowed_for(const RawAddress& peer_addr) { inc_func_call_count(__func__); return test::mock::stack_acl::BTM_is_sniff_allowed_for(peer_addr); } -bool acl_create_le_connection(const RawAddress& bd_addr) { - inc_func_call_count(__func__); - return test::mock::stack_acl::acl_create_le_connection(bd_addr); -} bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_acl.h b/system/test/mock/mock_stack_acl.h index d175d230a08..2f4dc13ca1a 100644 --- a/system/test/mock/mock_stack_acl.h +++ b/system/test/mock/mock_stack_acl.h @@ -97,15 +97,6 @@ struct acl_send_data_packet_br_edr { void operator()(const RawAddress& bd_addr, BT_HDR* p_buf) { return body(bd_addr, p_buf); } }; extern struct acl_send_data_packet_br_edr acl_send_data_packet_br_edr; -// Name: acl_create_le_connection -// Params: const RawAddress& bd_addr -// Returns: bool -struct acl_create_le_connection { - std::function body{ - [](const RawAddress& /* bd_addr */) { return false; }}; - bool operator()(const RawAddress& bd_addr) { return body(bd_addr); } -}; -extern struct acl_create_le_connection acl_create_le_connection; // Name: acl_create_le_connection_with_id // Params: uint8_t id, const RawAddress& bd_addr // Returns: bool -- GitLab From 8adbe408d3a34728796c4f1050df62d3a7fb56bc Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Wed, 9 Oct 2024 22:08:28 +0200 Subject: [PATCH 235/875] use_unified_connection_manager removal Unused, out of date Test: mma -j32 Bug: 290846969 Bug: 349469413 Bug: 372202918 Flag: EXEMPT, just delting unused code under flag Change-Id: Ie01c56f81d81affeed5c7285bcf8d712b6af59b0 --- flags/hci.aconfig | 10 - system/main/shim/acl.cc | 4 +- system/rust/Android.bp | 2 - system/rust/BUILD.gn | 1 - system/rust/src/connection.rs | 431 --------------- .../rust/src/connection/acceptlist_manager.rs | 366 ------------- system/rust/src/connection/attempt_manager.rs | 501 ------------------ system/rust/src/connection/ffi.rs | 242 --------- .../src/connection/ffi/connection_shim.cc | 169 ------ .../rust/src/connection/ffi/connection_shim.h | 72 --- system/rust/src/connection/le_manager.rs | 63 --- system/rust/src/connection/mocks.rs | 2 - .../src/connection/mocks/mock_le_manager.rs | 174 ------ system/rust/src/core/ffi.rs | 7 - system/rust/src/core/ffi/module.cc | 4 +- system/rust/src/core/mod.rs | 3 - system/rust/src/lib.rs | 10 - system/stack/acl/ble_acl.cc | 12 +- system/stack/acl/btm_acl.cc | 13 +- system/stack/btm/btm_dev.cc | 8 +- system/stack/gatt/gatt_api.cc | 34 +- system/stack/gatt/gatt_main.cc | 34 +- system/stack/gatt/gatt_utils.cc | 43 +- .../mock/mock_rust_ffi_connection_shim.cc | 36 -- 24 files changed, 40 insertions(+), 2201 deletions(-) delete mode 100644 system/rust/src/connection.rs delete mode 100644 system/rust/src/connection/acceptlist_manager.rs delete mode 100644 system/rust/src/connection/attempt_manager.rs delete mode 100644 system/rust/src/connection/ffi.rs delete mode 100644 system/rust/src/connection/ffi/connection_shim.cc delete mode 100644 system/rust/src/connection/ffi/connection_shim.h delete mode 100644 system/rust/src/connection/le_manager.rs delete mode 100644 system/rust/src/connection/mocks.rs delete mode 100644 system/rust/src/connection/mocks/mock_le_manager.rs delete mode 100644 system/test/mock/mock_rust_ffi_connection_shim.cc diff --git a/flags/hci.aconfig b/flags/hci.aconfig index 8c5180a2988..9c6d21d3a96 100644 --- a/flags/hci.aconfig +++ b/flags/hci.aconfig @@ -1,16 +1,6 @@ package: "com.android.bluetooth.flags" container: "com.android.btservices" -flag { - name: "unified_connection_manager" - namespace: "bluetooth" - description: "Manage connections centrally and remove the ACL shim layer" - bug: "349469413" - metadata { - purpose: PURPOSE_BUGFIX - } -} - flag { name: "encryption_change_v2" namespace: "bluetooth" diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc index 79d60320958..7f33da446fa 100644 --- a/system/main/shim/acl.cc +++ b/system/main/shim/acl.cc @@ -1009,9 +1009,7 @@ struct shim::Acl::impl { auto connection = handle_to_le_connection_map_.find(handle); if (connection != handle_to_le_connection_map_.end()) { auto remote_address_with_type = connection->second->GetRemoteAddressWithType(); - if (!com::android::bluetooth::flags::unified_connection_manager()) { - GetAclManager()->RemoveFromBackgroundList(remote_address_with_type); - } + GetAclManager()->RemoveFromBackgroundList(remote_address_with_type); connection->second->InitiateDisconnect(ToDisconnectReasonFromLegacy(reason)); log::debug("Disconnection initiated le remote:{} handle:{}", remote_address_with_type, handle); diff --git a/system/rust/Android.bp b/system/rust/Android.bp index f3fddcd3b99..9e4cca0736d 100644 --- a/system/rust/Android.bp +++ b/system/rust/Android.bp @@ -108,7 +108,6 @@ cc_library_static { "-Wno-missing-prototypes", ], srcs: [ - "src/connection/ffi/connection_shim.cc", "src/core/ffi/module.cc", "src/gatt/ffi/gatt_shim.cc", ], @@ -169,7 +168,6 @@ cc_library_static { filegroup { name: "libbluetooth_core_rs_ffi", srcs: [ - "src/connection/ffi.rs", "src/core/ffi.rs", "src/gatt/ffi.rs", ], diff --git a/system/rust/BUILD.gn b/system/rust/BUILD.gn index 5c386e5a0f7..f9c63f49860 100644 --- a/system/rust/BUILD.gn +++ b/system/rust/BUILD.gn @@ -22,7 +22,6 @@ cxxbridge_libheader("cxxlibheader") { static_library("core_rs") { sources = [ - "src/connection/ffi/connection_shim.cc", "src/core/ffi/module.cc", "src/gatt/ffi/gatt_shim.cc", ] diff --git a/system/rust/src/connection.rs b/system/rust/src/connection.rs deleted file mode 100644 index 99dc4c6cb39..00000000000 --- a/system/rust/src/connection.rs +++ /dev/null @@ -1,431 +0,0 @@ -//! This module manages LE connection requests and active -//! LE connections. In particular, it de-duplicates connection requests, -//! avoids duplicate connections to the same devices (even with different RPAs), -//! and retries failed connections - -use std::{ - cell::RefCell, collections::HashSet, fmt::Debug, future::Future, hash::Hash, ops::Deref, - time::Duration, -}; - -use crate::{ - core::{ - address::AddressWithType, - shared_box::{SharedBox, WeakBox, WeakBoxRef}, - }, - gatt::ids::ServerId, -}; - -use self::{ - acceptlist_manager::{determine_target_state, LeAcceptlistManager}, - attempt_manager::{ConnectionAttempts, ConnectionMode}, - le_manager::{ErrorCode, InactiveLeAclManager, LeAclManagerConnectionCallbacks}, -}; - -mod acceptlist_manager; -mod attempt_manager; -mod ffi; -pub mod le_manager; -mod mocks; - -pub use ffi::{register_callbacks, LeAclManagerImpl, LeAclManagerShim}; -use log::info; -use scopeguard::ScopeGuard; -use tokio::{task::spawn_local, time::timeout}; - -/// Possible errors returned when making a connection attempt -#[derive(Debug, PartialEq, Eq)] -pub enum CreateConnectionFailure { - /// This client is already making a connection of the same type - /// to the same address. - ConnectionAlreadyPending, -} - -/// Errors returned if a connection successfully starts but fails afterwards. -#[derive(Debug, PartialEq, Eq)] -pub enum ConnectionFailure { - /// The connection attempt was cancelled - Cancelled, - /// The connection completed but with an HCI error code - Error(ErrorCode), -} - -/// Errors returned if the client fails to cancel their connection attempt -#[derive(Debug, PartialEq, Eq)] -pub enum CancelConnectFailure { - /// The connection attempt does not exist - ConnectionNotPending, -} - -/// Unique identifiers for a client of the connection manager -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -pub enum ConnectionManagerClient { - /// A GATT client with given client ID - GattClient(u8), - /// A GATT server with given server ID - GattServer(ServerId), -} - -/// An active connection -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct LeConnection { - /// The address of the peer device, as reported in the connection complete event - /// This is guaranteed to be unique across active connections, so we can implement - /// PartialEq/Eq on this. - pub remote_address: AddressWithType, -} - -/// Responsible for managing the initiator state and the list of -/// devices on the filter accept list -#[derive(Debug)] -pub struct ConnectionManager { - state: RefCell, -} - -#[derive(Debug)] -struct ConnectionManagerState { - /// All pending connection attempts (unresolved direct + all background) - attempts: ConnectionAttempts, - /// The addresses we are currently connected to - current_connections: HashSet, - /// Tracks the state of the LE connect list, and updates it to drive to a - /// specified target state - acceptlist_manager: LeAcceptlistManager, -} - -struct ConnectionManagerCallbackHandler(WeakBox); - -const DIRECT_CONNECTION_TIMEOUT: Duration = Duration::from_secs( - 29, /* ugly hack to avoid fighting with le_impl timeout, until I remove that timeout */ -); - -impl LeAclManagerConnectionCallbacks for ConnectionManagerCallbackHandler { - fn on_le_connect(&self, address: AddressWithType, result: Result) { - self.with_manager(|manager| manager.on_le_connect(address, result)) - } - - fn on_disconnect(&self, address: AddressWithType) { - self.with_manager(|manager| manager.on_disconnect(address)) - } -} - -impl ConnectionManagerCallbackHandler { - fn with_manager(&self, f: impl FnOnce(&ConnectionManager)) { - self.0.with(|manager| f(manager.expect("got connection event after stack died").deref())) - } -} - -impl ConnectionManager { - /// Constructor - pub fn new(le_manager: impl InactiveLeAclManager) -> SharedBox { - SharedBox::new_cyclic(|weak| Self { - state: RefCell::new(ConnectionManagerState { - attempts: ConnectionAttempts::new(), - current_connections: HashSet::new(), - acceptlist_manager: LeAcceptlistManager::new( - le_manager.register_callbacks(ConnectionManagerCallbackHandler(weak)), - ), - }), - }) - } -} - -/// Make the state of the LeAcceptlistManager consistent with the attempts tracked in ConnectionAttempts -fn reconcile_state(state: &mut ConnectionManagerState) { - state - .acceptlist_manager - .drive_to_state(determine_target_state(&state.attempts.active_attempts())); -} - -impl WeakBoxRef<'_, ConnectionManager> { - /// Start a direct connection to a peer device from a specified client. If the peer - /// is connected, immediately resolve the attempt. - pub fn start_direct_connection( - &self, - client: ConnectionManagerClient, - address: AddressWithType, - ) -> Result<(), CreateConnectionFailure> { - spawn_local(timeout(DIRECT_CONNECTION_TIMEOUT, self.direct_connection(client, address)?)); - Ok(()) - } - - /// Start a direct connection to a peer device from a specified client. - /// - /// # Cancellation Safety - /// If this future is dropped, the connection attempt will be cancelled. It can also be cancelled - /// from the separate API ConnectionManager#cancel_connection. - fn direct_connection( - &self, - client: ConnectionManagerClient, - address: AddressWithType, - ) -> Result< - impl Future>, - CreateConnectionFailure, - > { - let mut state = self.state.borrow_mut(); - - // if connected, this is a no-op - let attempt_and_guard = if state.current_connections.contains(&address) { - None - } else { - let pending_attempt = state.attempts.register_direct_connection(client, address)?; - let attempt_id = pending_attempt.id; - reconcile_state(&mut state); - Some(( - pending_attempt, - scopeguard::guard(self.downgrade(), move |this| { - // remove the attempt after we are cancelled - this.with(|this| { - this.map(|this| { - info!("Cancelling attempt {attempt_id:?}"); - let mut state = this.state.borrow_mut(); - state.attempts.cancel_attempt_with_id(attempt_id); - reconcile_state(&mut state); - }) - }); - }), - )) - }; - - Ok(async move { - let Some((attempt, guard)) = attempt_and_guard else { - // if we did not make an attempt, the connection must be ready - return Ok(LeConnection { remote_address: address }); - }; - // otherwise, wait until the attempt resolves - let ret = attempt.await; - // defuse scopeguard (no need to cancel now) - ScopeGuard::into_inner(guard); - ret - }) - } -} - -impl ConnectionManager { - /// Start a background connection to a peer device with given parameters from a specified client. - pub fn add_background_connection( - &self, - client: ConnectionManagerClient, - address: AddressWithType, - ) -> Result<(), CreateConnectionFailure> { - let mut state = self.state.borrow_mut(); - state.attempts.register_background_connection(client, address)?; - reconcile_state(&mut state); - Ok(()) - } - - /// Cancel connection attempt from this client to the specified address with the specified mode. - pub fn cancel_connection( - &self, - client: ConnectionManagerClient, - address: AddressWithType, - mode: ConnectionMode, - ) -> Result<(), CancelConnectFailure> { - let mut state = self.state.borrow_mut(); - state.attempts.cancel_attempt(client, address, mode)?; - reconcile_state(&mut state); - Ok(()) - } - - /// Cancel all connection attempts to this address - pub fn cancel_unconditionally(&self, address: AddressWithType) { - let mut state = self.state.borrow_mut(); - state.attempts.remove_unconditionally(address); - reconcile_state(&mut state); - } - - /// Cancel all connection attempts from this client - pub fn remove_client(&self, client: ConnectionManagerClient) { - let mut state = self.state.borrow_mut(); - state.attempts.remove_client(client); - reconcile_state(&mut state); - } - - fn on_le_connect(&self, address: AddressWithType, result: Result) { - let mut state = self.state.borrow_mut(); - // record this connection while it exists - state.current_connections.insert(address); - // all completed connections remove the address from the direct list - state.acceptlist_manager.on_connect_complete(address); - // invoke any pending callbacks, update set of attempts - state.attempts.process_connection(address, result); - // update the acceptlist - reconcile_state(&mut state); - } - - fn on_disconnect(&self, address: AddressWithType) { - let mut state = self.state.borrow_mut(); - state.current_connections.remove(&address); - reconcile_state(&mut state); - } -} - -#[cfg(test)] -mod test { - use crate::{core::address::AddressType, utils::task::block_on_locally}; - - use super::{mocks::mock_le_manager::MockLeAclManager, *}; - - const CLIENT_1: ConnectionManagerClient = ConnectionManagerClient::GattClient(1); - const CLIENT_2: ConnectionManagerClient = ConnectionManagerClient::GattClient(2); - - const ADDRESS_1: AddressWithType = - AddressWithType { address: [1, 2, 3, 4, 5, 6], address_type: AddressType::Public }; - - const ERROR: ErrorCode = ErrorCode(1); - - #[test] - fn test_single_direct_connection() { - block_on_locally(async { - // arrange - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - - // act: initiate a direct connection - connection_manager.as_ref().start_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // assert: the direct connection is pending - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Direct)); - assert_eq!(mock_le_manager.current_acceptlist().len(), 1); - assert!(mock_le_manager.current_acceptlist().contains(&ADDRESS_1)); - }); - } - - #[test] - fn test_failed_direct_connection() { - block_on_locally(async { - // arrange: one pending direct connection - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - connection_manager.as_ref().start_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: the connection attempt fails - mock_le_manager.on_le_connect(ADDRESS_1, ERROR); - - // assert: the direct connection has stopped - assert_eq!(mock_le_manager.current_connection_mode(), None); - }); - } - - #[test] - fn test_single_background_connection() { - block_on_locally(async { - // arrange - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - - // act: initiate a background connection - connection_manager.as_ref().add_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // assert: the background connection is pending - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Background)); - assert_eq!(mock_le_manager.current_acceptlist().len(), 1); - assert!(mock_le_manager.current_acceptlist().contains(&ADDRESS_1)); - }); - } - - #[test] - fn test_resolved_connection() { - block_on_locally(async { - // arrange - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - - // act: initiate a direct connection, that succeeds - connection_manager.as_ref().start_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - mock_le_manager.on_le_connect(ADDRESS_1, ErrorCode::SUCCESS); - - // assert: no connection is pending - assert_eq!(mock_le_manager.current_connection_mode(), None); - }); - } - - #[test] - fn test_resolved_background_connection() { - block_on_locally(async { - // arrange - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - - // act: initiate a background connection, that succeeds - connection_manager.as_ref().add_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - mock_le_manager.on_le_connect(ADDRESS_1, ErrorCode::SUCCESS); - - // assert: no connection is pending - assert_eq!(mock_le_manager.current_connection_mode(), None); - }); - } - - #[test] - fn test_resolved_direct_connection_after_disconnect() { - block_on_locally(async { - // arrange - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - - // act: initiate a direct connection, that succeeds, then disconnects - connection_manager.as_ref().start_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - mock_le_manager.on_le_connect(ADDRESS_1, ErrorCode::SUCCESS); - mock_le_manager.on_le_disconnect(ADDRESS_1); - - // assert: no connection is pending - assert_eq!(mock_le_manager.current_connection_mode(), None); - }); - } - - #[test] - fn test_resolved_background_connection_after_disconnect() { - block_on_locally(async { - // arrange - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - - // act: initiate a background connection, that succeeds, then disconnects - connection_manager.as_ref().add_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - mock_le_manager.on_le_connect(ADDRESS_1, ErrorCode::SUCCESS); - mock_le_manager.on_le_disconnect(ADDRESS_1); - - // assert: the background connection has resumed - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Background)); - }); - } - - #[test] - fn test_direct_connection_timeout() { - block_on_locally(async { - // arrange: a pending direct connection - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - connection_manager.as_ref().start_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: let it timeout - tokio::time::sleep(DIRECT_CONNECTION_TIMEOUT).await; - // go forward one tick to ensure all timers are fired - // (since we are using fake time, this is not a race condition) - tokio::time::sleep(Duration::from_millis(1)).await; - - // assert: it is cancelled and we are idle again - assert_eq!(mock_le_manager.current_connection_mode(), None); - }); - } - - #[test] - fn test_stacked_direct_connections_timeout() { - block_on_locally(async { - // arrange - let mock_le_manager = MockLeAclManager::new(); - let connection_manager = ConnectionManager::new(mock_le_manager.clone()); - - // act: start a direct connection - connection_manager.as_ref().start_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - tokio::time::sleep(DIRECT_CONNECTION_TIMEOUT * 3 / 4).await; - // act: after some time, start a second one - connection_manager.as_ref().start_direct_connection(CLIENT_2, ADDRESS_1).unwrap(); - // act: wait for the first one (but not the second) to time out - tokio::time::sleep(DIRECT_CONNECTION_TIMEOUT * 3 / 4).await; - - // assert: we are still doing a direct connection - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Direct)); - }); - } -} diff --git a/system/rust/src/connection/acceptlist_manager.rs b/system/rust/src/connection/acceptlist_manager.rs deleted file mode 100644 index 4810640f3a4..00000000000 --- a/system/rust/src/connection/acceptlist_manager.rs +++ /dev/null @@ -1,366 +0,0 @@ -//! This module takes the set of attempts from the AttemptManager, determines -//! the target state of the LE manager, and drives it to this target state - -use std::collections::HashSet; - -use log::info; - -use crate::core::address::AddressWithType; - -use super::{ - attempt_manager::{ConnectionAttempt, ConnectionMode}, - le_manager::LeAclManager, -}; - -/// This struct represents the target state of the LeManager based on the -/// set of all active connection attempts -pub struct TargetState { - /// These addresses should go to the LE background connect list - pub background_list: HashSet, - /// These addresses should go to the direct list (we are not connected to any of them) - pub direct_list: HashSet, -} - -/// Takes a list of connection attempts, and determines the target state of the LE ACL manager -pub fn determine_target_state(attempts: &[ConnectionAttempt]) -> TargetState { - let background_list = attempts - .iter() - .filter(|attempt| attempt.mode == ConnectionMode::Background) - .map(|attempt| attempt.remote_address) - .collect(); - - let direct_list = attempts - .iter() - .filter(|attempt| attempt.mode == ConnectionMode::Direct) - .map(|attempt| attempt.remote_address) - .collect(); - - TargetState { background_list, direct_list } -} - -/// This struct monitors the state of the LE connect list, -/// and drives it to the target state. -#[derive(Debug)] -pub struct LeAcceptlistManager { - /// The connect list in the ACL manager - direct_list: HashSet, - /// The background connect list in the ACL manager - background_list: HashSet, - /// An interface into the LE ACL manager (le_impl.h) - le_manager: Box, -} - -impl LeAcceptlistManager { - /// Constructor - pub fn new(le_manager: impl LeAclManager + 'static) -> Self { - Self { - direct_list: HashSet::new(), - background_list: HashSet::new(), - le_manager: Box::new(le_manager), - } - } - - /// The state of the LE connect list (as per le_impl.h) updates on a completed connection - pub fn on_connect_complete(&mut self, address: AddressWithType) { - if address == AddressWithType::EMPTY { - return; - } - // le_impl pulls the device out of the direct connect list (but not the background list) on connection (regardless of status) - self.direct_list.remove(&address); - } - - /// Drive the state of the connect list to the target state - pub fn drive_to_state(&mut self, target: TargetState) { - // First, pull out anything in the ACL manager that we don't need - // recall that cancel_connect() removes addresses from *both* lists (!) - for address in self.direct_list.difference(&target.direct_list) { - info!("Cancelling connection attempt to {address:?}"); - self.le_manager.remove_from_all_lists(*address); - self.background_list.remove(address); - } - self.direct_list = self.direct_list.intersection(&target.direct_list).copied().collect(); - - for address in self.background_list.difference(&target.background_list) { - info!("Cancelling connection attempt to {address:?}"); - self.le_manager.remove_from_all_lists(*address); - self.direct_list.remove(address); - } - self.background_list = - self.background_list.intersection(&target.background_list).copied().collect(); - - // now everything extra has been removed, we can put things back in - for address in target.direct_list.difference(&self.direct_list) { - info!("Starting direct connection to {address:?}"); - self.le_manager.add_to_direct_list(*address); - } - for address in target.background_list.difference(&self.background_list) { - info!("Starting background connection to {address:?}"); - self.le_manager.add_to_background_list(*address); - } - - // we should now be in a consistent state! - self.direct_list = target.direct_list; - self.background_list = target.background_list; - } -} - -#[cfg(test)] -mod test { - use crate::{ - connection::{ - le_manager::ErrorCode, mocks::mock_le_manager::MockActiveLeAclManager, - ConnectionManagerClient, - }, - core::address::AddressType, - }; - - use super::*; - - const CLIENT: ConnectionManagerClient = ConnectionManagerClient::GattClient(1); - - const ADDRESS_1: AddressWithType = - AddressWithType { address: [1, 2, 3, 4, 5, 6], address_type: AddressType::Public }; - const ADDRESS_2: AddressWithType = - AddressWithType { address: [1, 2, 3, 4, 5, 6], address_type: AddressType::Random }; - const ADDRESS_3: AddressWithType = - AddressWithType { address: [1, 2, 3, 4, 5, 7], address_type: AddressType::Random }; - - #[test] - fn test_determine_target_state() { - let target = determine_target_state(&[ - ConnectionAttempt { - client: CLIENT, - mode: ConnectionMode::Background, - remote_address: ADDRESS_1, - }, - ConnectionAttempt { - client: CLIENT, - mode: ConnectionMode::Background, - remote_address: ADDRESS_1, - }, - ConnectionAttempt { - client: CLIENT, - mode: ConnectionMode::Background, - remote_address: ADDRESS_2, - }, - ConnectionAttempt { - client: CLIENT, - mode: ConnectionMode::Direct, - remote_address: ADDRESS_2, - }, - ConnectionAttempt { - client: CLIENT, - mode: ConnectionMode::Direct, - remote_address: ADDRESS_3, - }, - ]); - - assert_eq!(target.background_list.len(), 2); - assert!(target.background_list.contains(&ADDRESS_1)); - assert!(target.background_list.contains(&ADDRESS_2)); - assert_eq!(target.direct_list.len(), 2); - assert!(target.direct_list.contains(&ADDRESS_2)); - assert!(target.direct_list.contains(&ADDRESS_3)); - } - - #[test] - fn test_add_to_direct_list() { - // arrange - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - - // act: request a device to be present in the direct list - manager.drive_to_state(TargetState { - background_list: [].into(), - direct_list: [ADDRESS_1].into(), - }); - - // assert: that the device has been added - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Direct)); - assert_eq!(mock_le_manager.current_acceptlist().len(), 1); - assert!(mock_le_manager.current_acceptlist().contains(&ADDRESS_1)); - } - - #[test] - fn test_add_to_background_list() { - // arrange - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - - // act: request a device to be present in the direct list - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - - // assert: that the device has been added - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Background)); - assert_eq!(mock_le_manager.current_acceptlist().len(), 1); - assert!(mock_le_manager.current_acceptlist().contains(&ADDRESS_1)); - } - - #[test] - fn test_background_connection_upgrade_to_direct() { - // arrange: a pending background connection - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - - // act: initiate a direct connection to the same device - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [ADDRESS_1].into(), - }); - - // assert: we are now doing a direct connection - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Direct)); - } - - #[test] - fn test_direct_connection_cancel_while_background() { - // arrange: a pending background connection - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - - // act: initiate a direct connection to the same device, then remove it - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [ADDRESS_1].into(), - }); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - - // assert: we have returned to a background connection - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Background)); - } - - #[test] - fn test_direct_connection_cancel_then_resume_while_background() { - // arrange: a pending background connection - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - - // act: initiate a direct connection to the same device, cancel it, then resume - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [ADDRESS_1].into(), - }); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [ADDRESS_1].into(), - }); - - // assert: we have returned to a direct connection - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Direct)); - } - - #[test] - fn test_remove_background_connection_then_add() { - // arrange - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - - // act: add then remove a background connection - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - manager.drive_to_state(TargetState { background_list: [].into(), direct_list: [].into() }); - - // assert: we have stopped our connection - assert_eq!(mock_le_manager.current_connection_mode(), None); - } - - #[test] - fn test_background_connection_remove_then_add() { - // arrange - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - - // act: add, remove, then re-add a background connection - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - manager.drive_to_state(TargetState { background_list: [].into(), direct_list: [].into() }); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [].into(), - }); - - // assert: we resume our background connection - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Background)); - } - #[test] - fn test_retry_direct_connection_after_disconnect() { - // arrange - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - - // act: initiate a direct connection - manager.drive_to_state(TargetState { - background_list: [].into(), - direct_list: [ADDRESS_1].into(), - }); - // act: the connection succeeds (and later disconnects) - mock_le_manager.on_le_connect(ADDRESS_1, ErrorCode::SUCCESS); - manager.on_connect_complete(ADDRESS_1); - // the peer later disconnects - mock_le_manager.on_le_disconnect(ADDRESS_1); - // act: retry the direct connection - manager.drive_to_state(TargetState { - background_list: [].into(), - direct_list: [ADDRESS_1].into(), - }); - - // assert: we have resumed the direct connection - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Direct)); - assert_eq!(mock_le_manager.current_acceptlist().len(), 1); - assert!(mock_le_manager.current_acceptlist().contains(&ADDRESS_1)); - } - - #[test] - fn test_background_connection_remove_then_add_while_direct() { - // arrange: a pending direct connection - let mock_le_manager = MockActiveLeAclManager::new(); - let mut manager = LeAcceptlistManager::new(mock_le_manager.clone()); - manager.drive_to_state(TargetState { - background_list: [].into(), - direct_list: [ADDRESS_1].into(), - }); - - // act: add, remove, then re-add a background connection - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [ADDRESS_1].into(), - }); - manager.drive_to_state(TargetState { - background_list: [].into(), - direct_list: [ADDRESS_1].into(), - }); - manager.drive_to_state(TargetState { - background_list: [ADDRESS_1].into(), - direct_list: [ADDRESS_1].into(), - }); - - // assert: we remain doing our direct connection - assert_eq!(mock_le_manager.current_connection_mode(), Some(ConnectionMode::Direct)); - } -} diff --git a/system/rust/src/connection/attempt_manager.rs b/system/rust/src/connection/attempt_manager.rs deleted file mode 100644 index 54a2e66240b..00000000000 --- a/system/rust/src/connection/attempt_manager.rs +++ /dev/null @@ -1,501 +0,0 @@ -use std::{ - collections::{hash_map::Entry, HashMap}, - future::{Future, IntoFuture}, -}; - -use tokio::sync::oneshot; - -use crate::core::address::AddressWithType; - -use super::{ - le_manager::ErrorCode, CancelConnectFailure, ConnectionFailure, ConnectionManagerClient, - CreateConnectionFailure, LeConnection, -}; - -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -pub enum ConnectionMode { - Background, - Direct, -} - -#[derive(Debug)] -struct ConnectionAttemptData { - id: AttemptId, - conn_tx: Option>>, -} - -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -pub struct ConnectionAttempt { - pub client: ConnectionManagerClient, - pub mode: ConnectionMode, - pub remote_address: AddressWithType, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct AttemptId(u64); - -#[derive(Debug)] -pub struct ConnectionAttempts { - attempt_id: AttemptId, - attempts: HashMap, -} - -#[derive(Debug)] -pub struct PendingConnectionAttempt { - pub id: AttemptId, - f: F, -} - -impl IntoFuture for PendingConnectionAttempt -where - F: Future>, -{ - type Output = F::Output; - type IntoFuture = F; - - fn into_future(self) -> Self::IntoFuture { - self.f - } -} - -impl ConnectionAttempts { - /// Constructor - pub fn new() -> Self { - Self { attempt_id: AttemptId(0), attempts: HashMap::new() } - } - - fn new_attempt_id(&mut self) -> AttemptId { - let AttemptId(id) = self.attempt_id; - self.attempt_id = AttemptId(id.wrapping_add(1)); - AttemptId(id) - } - - /// Register a pending direct connection to the peer. Note that the peer MUST NOT be connected at this point. - /// Returns the AttemptId of this attempt, as well as a future resolving with the connection (once created) or an - /// error. - /// - /// Note that only one connection attempt from the same (client, address, mode) tuple can be pending at any time. - /// - /// # Cancellation Safety - /// If this future is cancelled, the attempt will NOT BE REMOVED! It must be cancelled explicitly. To avoid - /// cancelling the wrong future, the returned ID should be used. - pub fn register_direct_connection( - &mut self, - client: ConnectionManagerClient, - address: AddressWithType, - ) -> Result< - PendingConnectionAttempt>>, - CreateConnectionFailure, - > { - let attempt = - ConnectionAttempt { client, mode: ConnectionMode::Direct, remote_address: address }; - - let id = self.new_attempt_id(); - let Entry::Vacant(entry) = self.attempts.entry(attempt) else { - return Err(CreateConnectionFailure::ConnectionAlreadyPending); - }; - let (tx, rx) = oneshot::channel(); - entry.insert(ConnectionAttemptData { conn_tx: Some(tx), id }); - - Ok(PendingConnectionAttempt { - id, - f: async move { - rx.await - .map_err(|_| ConnectionFailure::Cancelled)? - .map_err(ConnectionFailure::Error) - }, - }) - } - - /// Register a pending background connection to the peer. Returns the AttemptId of this attempt. - /// - /// Note that only one connection attempt from the same (client, address, mode) tuple can be pending at any time. - pub fn register_background_connection( - &mut self, - client: ConnectionManagerClient, - address: AddressWithType, - ) -> Result { - let attempt = - ConnectionAttempt { client, mode: ConnectionMode::Background, remote_address: address }; - - let id = self.new_attempt_id(); - let Entry::Vacant(entry) = self.attempts.entry(attempt) else { - return Err(CreateConnectionFailure::ConnectionAlreadyPending); - }; - entry.insert(ConnectionAttemptData { conn_tx: None, id }); - - Ok(id) - } - - /// Cancel connection attempts with the specified mode from this client to the specified address. - pub fn cancel_attempt( - &mut self, - client: ConnectionManagerClient, - address: AddressWithType, - mode: ConnectionMode, - ) -> Result<(), CancelConnectFailure> { - let existing = - self.attempts.remove(&ConnectionAttempt { client, mode, remote_address: address }); - - if existing.is_some() { - // note: dropping the ConnectionAttemptData is sufficient to close the channel and send a cancellation error - Ok(()) - } else { - Err(CancelConnectFailure::ConnectionNotPending) - } - } - - /// Cancel the connection attempt with the given ID. - pub fn cancel_attempt_with_id(&mut self, id: AttemptId) { - self.attempts.retain(|_, attempt| attempt.id != id); - } - - /// Cancel all connection attempts to this address - pub fn remove_unconditionally(&mut self, address: AddressWithType) { - self.attempts.retain(|attempt, _| attempt.remote_address != address); - } - - /// Cancel all connection attempts from this client - pub fn remove_client(&mut self, client: ConnectionManagerClient) { - self.attempts.retain(|attempt, _| attempt.client != client); - } - - /// List all active connection attempts. Note that we can have active background (but NOT) direct - /// connection attempts to connected devices, as we will resume the connection attempt when the - /// peer disconnects from us. - pub fn active_attempts(&self) -> Vec { - self.attempts.keys().cloned().collect() - } - - /// Handle a successful connection by notifying clients and resolving direct connect attempts - pub fn process_connection( - &mut self, - address: AddressWithType, - result: Result, - ) { - let interested_clients = self - .attempts - .keys() - .filter(|attempt| attempt.remote_address == address) - .copied() - .collect::>(); - - for attempt in interested_clients { - if attempt.mode == ConnectionMode::Direct { - // TODO(aryarahul): clean up these unwraps - let _ = self.attempts.remove(&attempt).unwrap().conn_tx.unwrap().send(result); - } else { - // TODO(aryarahul): inform background clients of the connection - } - } - } -} - -#[cfg(test)] -mod test { - use crate::{ - core::address::AddressType, - utils::task::{block_on_locally, try_await}, - }; - - use super::*; - - const CLIENT_1: ConnectionManagerClient = ConnectionManagerClient::GattClient(1); - const CLIENT_2: ConnectionManagerClient = ConnectionManagerClient::GattClient(2); - - const ADDRESS_1: AddressWithType = - AddressWithType { address: [1, 2, 3, 4, 5, 6], address_type: AddressType::Public }; - const ADDRESS_2: AddressWithType = - AddressWithType { address: [1, 2, 3, 4, 5, 6], address_type: AddressType::Random }; - - const CONNECTION_1: LeConnection = LeConnection { remote_address: ADDRESS_1 }; - const CONNECTION_2: LeConnection = LeConnection { remote_address: ADDRESS_2 }; - - #[test] - fn test_direct_connection() { - block_on_locally(async { - // arrange - let mut attempts = ConnectionAttempts::new(); - - // act: start a pending direct connection - let _ = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // assert: this attempt is pending - assert_eq!(attempts.active_attempts().len(), 1); - assert_eq!(attempts.active_attempts()[0].client, CLIENT_1); - assert_eq!(attempts.active_attempts()[0].mode, ConnectionMode::Direct); - assert_eq!(attempts.active_attempts()[0].remote_address, ADDRESS_1); - }); - } - - #[test] - fn test_cancel_direct_connection() { - block_on_locally(async { - // arrange: one pending direct connection - let mut attempts = ConnectionAttempts::new(); - let pending_direct_connection = - attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: cancel it - attempts.cancel_attempt(CLIENT_1, ADDRESS_1, ConnectionMode::Direct).unwrap(); - let resp = pending_direct_connection.await; - - // assert: the original future resolved, and the attempt is cleared - assert_eq!(resp, Err(ConnectionFailure::Cancelled)); - assert!(attempts.active_attempts().is_empty()); - }); - } - - #[test] - fn test_multiple_direct_connections() { - block_on_locally(async { - // arrange - let mut attempts = ConnectionAttempts::new(); - - // act: start two direct connections - attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - attempts.register_direct_connection(CLIENT_2, ADDRESS_1).unwrap(); - - // assert: both attempts are pending - assert_eq!(attempts.active_attempts().len(), 2); - }); - } - - #[test] - fn test_two_direct_connection_cancel_one() { - block_on_locally(async { - // arrange: two pending direct connections - let mut attempts = ConnectionAttempts::new(); - attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - attempts.register_direct_connection(CLIENT_2, ADDRESS_1).unwrap(); - - // act: cancel one - attempts.cancel_attempt(CLIENT_1, ADDRESS_1, ConnectionMode::Direct).unwrap(); - - // assert: one attempt is still pending - assert_eq!(attempts.active_attempts().len(), 1); - assert_eq!(attempts.active_attempts()[0].client, CLIENT_2); - }); - } - - #[test] - fn test_drop_pending_connection_after_cancel_and_restart() { - // arrange - let mut attempts = ConnectionAttempts::new(); - - // act: start one pending direct connection, cancel it, restart it, and then drop the first future - let pending_1 = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - attempts.cancel_attempt(CLIENT_1, ADDRESS_1, ConnectionMode::Direct).unwrap(); - let _pending_2 = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - drop(pending_1); - - // assert: the restart is still pending - assert_eq!(attempts.active_attempts().len(), 1); - } - - #[test] - fn test_background_connection() { - block_on_locally(async { - // arrange - let mut attempts = ConnectionAttempts::new(); - - // act: start a pending background connection - attempts.register_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // assert: this attempt is pending - assert_eq!(attempts.active_attempts().len(), 1); - assert_eq!(attempts.active_attempts()[0].client, CLIENT_1); - assert_eq!(attempts.active_attempts()[0].mode, ConnectionMode::Background); - assert_eq!(attempts.active_attempts()[0].remote_address, ADDRESS_1); - }); - } - - #[test] - fn test_reject_duplicate_direct_connection() { - block_on_locally(async { - // arrange - let mut attempts = ConnectionAttempts::new(); - - // act: start two background connections with the same parameters - let _fut = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - let ret = attempts.register_direct_connection(CLIENT_1, ADDRESS_1); - - // assert: this attempt is pending - assert!(matches!(ret, Err(CreateConnectionFailure::ConnectionAlreadyPending))); - }); - } - - #[test] - fn test_reject_duplicate_background_connection() { - block_on_locally(async { - // arrange - let mut attempts = ConnectionAttempts::new(); - - // act: start two background connections with the same parameters - attempts.register_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - let ret = attempts.register_background_connection(CLIENT_1, ADDRESS_1); - - // assert: this attempt is pending - assert_eq!(ret, Err(CreateConnectionFailure::ConnectionAlreadyPending)); - }); - } - - #[test] - fn test_resolved_direct_connection() { - block_on_locally(async { - // arrange: one pending direct connection - let mut attempts = ConnectionAttempts::new(); - let pending_conn = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: resolve with an incoming connection - attempts.process_connection(ADDRESS_1, Ok(CONNECTION_1)); - - // assert: the attempt is resolved and is no longer active - assert_eq!(pending_conn.await.unwrap(), CONNECTION_1); - assert!(attempts.active_attempts().is_empty()); - }); - } - - #[test] - fn test_failed_direct_connection() { - block_on_locally(async { - // arrange: one pending direct connection - let mut attempts = ConnectionAttempts::new(); - let pending_conn = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: resolve with an incoming connection - attempts.process_connection(ADDRESS_1, Err(ErrorCode(1))); - - // assert: the attempt is resolved and is no longer active - assert_eq!(pending_conn.await, Err(ConnectionFailure::Error(ErrorCode(1)))); - assert!(attempts.active_attempts().is_empty()); - }); - } - - #[test] - fn test_resolved_background_connection() { - block_on_locally(async { - // arrange: one pending direct connection - let mut attempts = ConnectionAttempts::new(); - attempts.register_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: resolve with an incoming connection - attempts.process_connection(ADDRESS_1, Ok(CONNECTION_1)); - - // assert: the attempt is still active - assert_eq!(attempts.active_attempts().len(), 1); - }); - } - - #[test] - fn test_incoming_connection_while_another_is_pending() { - block_on_locally(async { - // arrange: one pending direct connection - let mut attempts = ConnectionAttempts::new(); - let pending_conn = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: an incoming connection arrives to a different address - attempts.process_connection(ADDRESS_2, Ok(CONNECTION_2)); - - // assert: the attempt is still pending - assert!(try_await(pending_conn).await.is_err()); - assert_eq!(attempts.active_attempts().len(), 1); - }); - } - - #[test] - fn test_incoming_connection_resolves_some_but_not_all() { - block_on_locally(async { - // arrange: one pending direct connection and one background connection to each of two addresses - let mut attempts = ConnectionAttempts::new(); - let pending_conn_1 = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - let pending_conn_2 = attempts.register_direct_connection(CLIENT_1, ADDRESS_2).unwrap(); - attempts.register_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - attempts.register_background_connection(CLIENT_1, ADDRESS_2).unwrap(); - - // act: an incoming connection arrives to the first address - attempts.process_connection(ADDRESS_1, Ok(CONNECTION_1)); - - // assert: one direct attempt is completed, one is still pending - assert_eq!(pending_conn_1.await, Ok(CONNECTION_1)); - assert!(try_await(pending_conn_2).await.is_err()); - // three attempts remain (the unresolved direct, and both background attempts) - assert_eq!(attempts.active_attempts().len(), 3); - }); - } - - #[test] - fn test_remove_background_connection() { - block_on_locally(async { - // arrange: one pending background connection - let mut attempts = ConnectionAttempts::new(); - attempts.register_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - - // act: remove it - attempts.cancel_attempt(CLIENT_1, ADDRESS_1, ConnectionMode::Background).unwrap(); - - // assert: no pending attempts - assert!(attempts.active_attempts().is_empty()); - }); - } - - #[test] - fn test_cancel_nonexistent_connection() { - block_on_locally(async { - // arrange - let mut attempts = ConnectionAttempts::new(); - - // act: cancel a nonexistent direct connection - let resp = attempts.cancel_attempt(CLIENT_1, ADDRESS_1, ConnectionMode::Direct); - - // assert: got an error - assert_eq!(resp, Err(CancelConnectFailure::ConnectionNotPending)); - }); - } - - #[test] - fn test_remove_unconditionally() { - block_on_locally(async { - // arrange: one pending direct connection, and one background connection, to each address - let mut attempts = ConnectionAttempts::new(); - let pending_conn_1 = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - let pending_conn_2 = attempts.register_direct_connection(CLIENT_1, ADDRESS_2).unwrap(); - attempts.register_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - attempts.register_background_connection(CLIENT_1, ADDRESS_2).unwrap(); - - // act: cancel all connections to the first address - attempts.remove_unconditionally(ADDRESS_1); - - // assert: one direct attempt is completed, one is still pending - assert_eq!(pending_conn_1.await, Err(ConnectionFailure::Cancelled)); - assert!(try_await(pending_conn_2).await.is_err()); - // assert: two attempts remain, both to the other address - assert_eq!(attempts.active_attempts().len(), 2); - assert_eq!(attempts.active_attempts()[0].remote_address, ADDRESS_2); - assert_eq!(attempts.active_attempts()[1].remote_address, ADDRESS_2); - }); - } - - #[test] - fn test_remove_client() { - block_on_locally(async { - // arrange: one pending direct connection, and one background connection, from each address - let mut attempts = ConnectionAttempts::new(); - let pending_conn_1 = attempts.register_direct_connection(CLIENT_1, ADDRESS_1).unwrap(); - let pending_conn_2 = attempts.register_direct_connection(CLIENT_2, ADDRESS_1).unwrap(); - attempts.register_background_connection(CLIENT_1, ADDRESS_1).unwrap(); - attempts.register_background_connection(CLIENT_2, ADDRESS_1).unwrap(); - - // act: remove the first client - attempts.remove_client(CLIENT_1); - - // assert: one direct attempt is completed, one is still pending - assert_eq!(pending_conn_1.await, Err(ConnectionFailure::Cancelled)); - assert!(try_await(pending_conn_2).await.is_err()); - // assert: two attempts remain, both from the second client - assert_eq!(attempts.active_attempts().len(), 2); - assert_eq!(attempts.active_attempts()[0].client, CLIENT_2); - assert_eq!(attempts.active_attempts()[1].client, CLIENT_2); - }); - } -} diff --git a/system/rust/src/connection/ffi.rs b/system/rust/src/connection/ffi.rs deleted file mode 100644 index 82a98582de5..00000000000 --- a/system/rust/src/connection/ffi.rs +++ /dev/null @@ -1,242 +0,0 @@ -//! FFI interfaces for the Connection module. - -use std::{fmt::Debug, pin::Pin}; - -use cxx::UniquePtr; -pub use inner::*; -use log::warn; -use tokio::{ - sync::mpsc::{unbounded_channel, UnboundedSender}, - task::spawn_local, -}; - -use crate::do_in_rust_thread; - -use super::{ - attempt_manager::ConnectionMode, - le_manager::{ErrorCode, InactiveLeAclManager, LeAclManager, LeAclManagerConnectionCallbacks}, - ConnectionManagerClient, LeConnection, -}; - -// SAFETY: `LeAclManagerShim` can be passed between threads. -unsafe impl Send for LeAclManagerShim {} - -#[cxx::bridge] -#[allow(clippy::needless_lifetimes)] -#[allow(clippy::needless_maybe_sized)] -#[allow(clippy::too_many_arguments)] -#[allow(missing_docs)] -#[allow(unsafe_op_in_unsafe_fn)] -mod inner { - impl UniquePtr {} - - #[namespace = "bluetooth::core"] - extern "C++" { - type AddressWithType = crate::core::address::AddressWithType; - } - - #[namespace = "bluetooth::connection"] - unsafe extern "C++" { - include!("src/connection/ffi/connection_shim.h"); - - /// This lets us send HCI commands, either directly, - /// or via the address manager - type LeAclManagerShim; - - /// Add address to direct/background connect list, if not already connected - /// If connected, then adding to direct list is a no-op, but adding to the - /// background list will still take place. - #[cxx_name = "CreateLeConnection"] - fn create_le_connection(&self, address: AddressWithType, is_direct: bool); - - /// Remove address from both direct + background connect lists - #[cxx_name = "CancelLeConnect"] - fn cancel_le_connect(&self, address: AddressWithType); - - /// Register Rust callbacks for connection events - /// - /// # Safety - /// - /// `callbacks` must be Send + Sync, since C++ moves it to a different thread and - /// invokes it from several others (GD + legacy threads). - #[allow(clippy::missing_safety_doc)] - #[cxx_name = "RegisterRustCallbacks"] - unsafe fn unchecked_register_rust_callbacks( - self: Pin<&mut Self>, - callbacks: Box, - ); - } - - #[namespace = "bluetooth::connection"] - extern "Rust" { - type LeAclManagerCallbackShim; - #[cxx_name = "OnLeConnectSuccess"] - fn on_le_connect_success(&self, address: AddressWithType); - #[cxx_name = "OnLeConnectFail"] - fn on_le_connect_fail(&self, address: AddressWithType, status: u8); - #[cxx_name = "OnLeDisconnection"] - fn on_disconnect(&self, address: AddressWithType); - } - - #[namespace = "bluetooth::connection"] - unsafe extern "C++" { - include!("stack/arbiter/acl_arbiter.h"); - - /// Register APIs exposed by Rust - fn RegisterRustApis( - start_direct_connection: fn(client_id: u8, address: AddressWithType), - stop_direct_connection: fn(client_id: u8, address: AddressWithType), - add_background_connection: fn(client_id: u8, address: AddressWithType), - remove_background_connection: fn(client_id: u8, address: AddressWithType), - remove_client: fn(client_id: u8), - stop_all_connections_to_device: fn(address: AddressWithType), - ); - } -} - -impl LeAclManagerShim { - fn register_rust_callbacks( - self: Pin<&mut LeAclManagerShim>, - callbacks: Box, - ) where - Box: Send + Sync, - { - // SAFETY: The requirements of this method are enforced - // by our own trait bounds. - unsafe { - self.unchecked_register_rust_callbacks(callbacks); - } - } -} - -/// Implementation of HciConnectProxy wrapping the corresponding C++ methods -pub struct LeAclManagerImpl(pub UniquePtr); - -pub struct LeAclManagerCallbackShim( - UnboundedSender>, -); - -impl LeAclManagerCallbackShim { - fn on_le_connect_success(&self, address: AddressWithType) { - let _ = self.0.send(Box::new(move |callback| { - callback.on_le_connect(address, Ok(LeConnection { remote_address: address })) - })); - } - - fn on_le_connect_fail(&self, address: AddressWithType, status: u8) { - let _ = self.0.send(Box::new(move |callback| { - callback.on_le_connect(address, Err(ErrorCode(status))) - })); - } - - fn on_disconnect(&self, address: AddressWithType) { - let _ = self.0.send(Box::new(move |callback| { - callback.on_disconnect(address); - })); - } -} - -impl InactiveLeAclManager for LeAclManagerImpl { - type ActiveManager = Self; - - fn register_callbacks( - mut self, - callbacks: impl LeAclManagerConnectionCallbacks + 'static, - ) -> Self::ActiveManager { - let (tx, mut rx) = unbounded_channel(); - - // only register callbacks if the feature is enabled - if bluetooth_aconfig_flags_rust::unified_connection_manager() { - self.0.pin_mut().register_rust_callbacks(Box::new(LeAclManagerCallbackShim(tx))); - } - - spawn_local(async move { - while let Some(f) = rx.recv().await { - f(&callbacks) - } - }); - self - } -} - -impl LeAclManager for LeAclManagerImpl { - fn add_to_direct_list(&self, address: AddressWithType) { - self.0.create_le_connection(address, /* is_direct= */ true) - } - - fn add_to_background_list(&self, address: AddressWithType) { - self.0.create_le_connection(address, /* is_direct= */ false) - } - - fn remove_from_all_lists(&self, address: AddressWithType) { - self.0.cancel_le_connect(address) - } -} - -impl Debug for LeAclManagerImpl { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("LeAclManagerImpl").finish() - } -} - -/// Registers all connection-manager callbacks into C++ dependencies -pub fn register_callbacks() { - RegisterRustApis( - |client, address| { - let client = ConnectionManagerClient::GattClient(client); - do_in_rust_thread(move |modules| { - let result = - modules.connection_manager.as_ref().start_direct_connection(client, address); - if let Err(err) = result { - warn!("Failed to start direct connection from {client:?} to {address:?} ({err:?})") - } - }); - }, - |client, address| { - let client = ConnectionManagerClient::GattClient(client); - do_in_rust_thread(move |modules| { - let result = modules.connection_manager.cancel_connection( - client, - address, - ConnectionMode::Direct, - ); - if let Err(err) = result { - warn!("Failed to cancel direct connection from {client:?} to {address:?} ({err:?})") - } - }) - }, - |client, address| { - let client = ConnectionManagerClient::GattClient(client); - do_in_rust_thread(move |modules| { - let result = modules.connection_manager.add_background_connection(client, address); - if let Err(err) = result { - warn!("Failed to add background connection from {client:?} to {address:?} ({err:?})") - } - }) - }, - |client, address| { - let client = ConnectionManagerClient::GattClient(client); - do_in_rust_thread(move |modules| { - let result = modules.connection_manager.cancel_connection( - client, - address, - ConnectionMode::Background, - ); - if let Err(err) = result { - warn!("Failed to remove background connection from {client:?} to {address:?} ({err:?})") - } - }) - }, - |client| { - let client = ConnectionManagerClient::GattClient(client); - do_in_rust_thread(move |modules| { - modules.connection_manager.remove_client(client); - }) - }, - |address| { - do_in_rust_thread(move |modules| { - modules.connection_manager.cancel_unconditionally(address); - }) - }, - ) -} diff --git a/system/rust/src/connection/ffi/connection_shim.cc b/system/rust/src/connection/ffi/connection_shim.cc deleted file mode 100644 index 1ff23b96295..00000000000 --- a/system/rust/src/connection/ffi/connection_shim.cc +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2023, 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 "connection_shim.h" - -#include - -#include -#include -#include -#include - -#include "hci/acl_manager.h" -#include "hci/address_with_type.h" -#include "hci/hci_packets.h" -#include "main/shim/entry.h" -#ifndef TARGET_FLOSS -#include "src/connection/ffi.rs.h" -#endif -#include "src/core/ffi/types.h" -#include "stack/btm/btm_dev.h" - -namespace bluetooth { -namespace connection { - -#ifdef TARGET_FLOSS -struct LeAclManagerCallbackShim { - void OnLeConnectSuccess(core::AddressWithType addr) const { - log::fatal("system/rust not available in Floss"); - } - void OnLeConnectFail(core::AddressWithType addr, uint8_t status) const { - log::fatal("system/rust not available in Floss"); - } - void OnLeDisconnection(core::AddressWithType addr) const { - log::fatal("system/rust not available in Floss"); - } -}; - -using BoxedLeAclManagerCallbackShim = std::unique_ptr; - -#else - -using BoxedLeAclManagerCallbackShim = ::rust::Box; - -#endif - -namespace { -hci::AddressWithType ToCppAddress(core::AddressWithType address) { - auto hci_address = hci::Address(); - hci_address.FromOctets(address.address.data()); - return hci::AddressWithType(hci_address, (hci::AddressType)address.address_type); -} - -core::AddressWithType ToRustAddress(hci::AddressWithType address) { - return core::AddressWithType{address.GetAddress().address, - (core::AddressType)address.GetAddressType()}; -} -} // namespace - -struct LeAclManagerShim::impl : hci::acl_manager::LeAcceptlistCallbacks { -public: - impl() { acl_manager_ = shim::GetAclManager(); } - - ~impl() { - if (callbacks_.has_value()) { - callbacks_.reset(); - auto promise = std::promise(); - auto future = promise.get_future(); - acl_manager_->UnregisterLeAcceptlistCallbacks(this, std::move(promise)); - future.wait(); - } - } - - void CreateLeConnection(core::AddressWithType address, bool is_direct) { - acl_manager_->CreateLeConnection(ToCppAddress(address), is_direct); - } - - void CancelLeConnect(core::AddressWithType address) { - acl_manager_->CancelLeConnect(ToCppAddress(address)); - } - -#ifndef TARGET_FLOSS - void RegisterRustCallbacks(BoxedLeAclManagerCallbackShim callbacks) { - callbacks_ = std::move(callbacks); - acl_manager_->RegisterLeAcceptlistCallbacks(this); - } -#endif - - // hci::acl_manager::LeAcceptlistCallbacks - virtual void OnLeConnectSuccess(hci::AddressWithType address) { - callbacks_.value()->OnLeConnectSuccess(ToRustAddress(address)); - } - - // hci::acl_manager::LeAcceptlistCallbacks - virtual void OnLeConnectFail(hci::AddressWithType address, hci::ErrorCode reason) { - callbacks_.value()->OnLeConnectFail(ToRustAddress(address), static_cast(reason)); - } - - // hci::acl_manager::LeAcceptlistCallbacks - virtual void OnLeDisconnection(hci::AddressWithType address) { - callbacks_.value()->OnLeDisconnection(ToRustAddress(address)); - } - - // hci::acl_manager::LeAcceptlistCallbacks - virtual void OnResolvingListChange() {} - -private: - std::optional callbacks_; - hci::AclManager* acl_manager_{}; -}; - -LeAclManagerShim::LeAclManagerShim() { pimpl_ = std::make_unique(); } - -LeAclManagerShim::~LeAclManagerShim() = default; - -void LeAclManagerShim::CreateLeConnection(core::AddressWithType address, bool is_direct) const { - pimpl_->CreateLeConnection(address, is_direct); -} - -void LeAclManagerShim::CancelLeConnect(core::AddressWithType address) const { - pimpl_->CancelLeConnect(address); -} - -#ifndef TARGET_FLOSS -void LeAclManagerShim::RegisterRustCallbacks(BoxedLeAclManagerCallbackShim callbacks) { - pimpl_->RegisterRustCallbacks(std::move(callbacks)); -} -#endif - -namespace { - -std::optional connection_manager; - -} // namespace - -RustConnectionManager& GetConnectionManager() { return connection_manager.value(); } - -void RegisterRustApis( - ::rust::Fn start_direct_connection, - ::rust::Fn stop_direct_connection, - ::rust::Fn - add_background_connection, - ::rust::Fn - remove_background_connection, - ::rust::Fn remove_client, - ::rust::Fn stop_all_connections_to_device) { - connection_manager = { - start_direct_connection, stop_direct_connection, add_background_connection, - remove_background_connection, remove_client, stop_all_connections_to_device}; -} - -core::AddressWithType ResolveRawAddress(RawAddress bd_addr) { - tBLE_BD_ADDR address = BTM_Sec_GetAddressWithType(bd_addr); - return core::ToRustAddress(address); -} - -} // namespace connection -} // namespace bluetooth diff --git a/system/rust/src/connection/ffi/connection_shim.h b/system/rust/src/connection/ffi/connection_shim.h deleted file mode 100644 index 5346c07db94..00000000000 --- a/system/rust/src/connection/ffi/connection_shim.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2023, 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 -#include - -#include "rust/cxx.h" -#include "rust/src/core/ffi/types.h" -#include "types/ble_address_with_type.h" - -namespace bluetooth { - -namespace connection { - -struct LeAclManagerCallbackShim; - -class LeAclManagerShim { -public: - LeAclManagerShim(); - ~LeAclManagerShim(); - - void CreateLeConnection(core::AddressWithType address, bool is_direct) const; - - void CancelLeConnect(core::AddressWithType address) const; - -#ifndef TARGET_FLOSS - void RegisterRustCallbacks(::rust::Box callbacks); -#endif - -private: - struct impl; - std::unique_ptr pimpl_; -}; - -void RegisterRustApis( - ::rust::Fn start_direct_connection, - ::rust::Fn stop_direct_connection, - ::rust::Fn - add_background_connection, - ::rust::Fn - remove_background_connection, - ::rust::Fn remove_client, - ::rust::Fn stop_all_connections_to_device); - -struct RustConnectionManager { - ::rust::Fn start_direct_connection; - ::rust::Fn stop_direct_connection; - ::rust::Fn add_background_connection; - ::rust::Fn remove_background_connection; - ::rust::Fn remove_client; - ::rust::Fn stop_all_connections_to_device; -}; - -RustConnectionManager& GetConnectionManager(); - -core::AddressWithType ResolveRawAddress(RawAddress bd_addr); - -} // namespace connection -} // namespace bluetooth diff --git a/system/rust/src/connection/le_manager.rs b/system/rust/src/connection/le_manager.rs deleted file mode 100644 index fa55118d08e..00000000000 --- a/system/rust/src/connection/le_manager.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! This trait represents the lower-level operations -//! made available to the connection manager. In particular, -//! we can add devices to either the "direct" or "background" -//! connect list, which are in turn mapped to an appropriate choice -//! of scan parameters / the filter accept list. -//! -//! Note that the ACL manager is unaware of address resolution, -//! so this must be handled by the connection manager. Conversely, the connection -//! manager does not need to consider the HCI state machine, and can send requests -//! at any time. -//! -//! In addition to the supplied API, when a connection completes to a peer device, -//! it is removed from the "direct" connect list (based on exact address match). - -use std::fmt::Debug; - -use crate::core::address::AddressWithType; - -use super::LeConnection; - -/// An HCI Error Code from the controller -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub struct ErrorCode(pub u8); - -impl ErrorCode { - /// Operation completed successfully - pub const SUCCESS: Self = ErrorCode(0); -} - -/// The LeAclManager before callbacks are registered -pub trait InactiveLeAclManager { - /// The type implementing LeAclManager once callbacks are registered - type ActiveManager: LeAclManager + 'static; - - /// Register callbacks for connection events, and produuce an ActiveManager - fn register_callbacks( - self, - callbacks: impl LeAclManagerConnectionCallbacks + 'static, - ) -> Self::ActiveManager; -} - -/// The operations provided by GD AclManager to the connection manager -pub trait LeAclManager: Debug { - /// Adds an address to the direct connect list, if not already connected. - /// WARNING: the connection timeout is set the FIRST time the address is added, and is - /// NOT RESET! TODO(aryarahul): remove connection timeout from le_impl since it belongs here instead - /// Precondition: Must NOT be currently connected to this adddress (if connected due to race, is a no-op) - fn add_to_direct_list(&self, address: AddressWithType); // CreateLeConnection(is_direct=true) - /// Adds an address to the background connect list - fn add_to_background_list(&self, address: AddressWithType); // CreateLeConnection(is_direct=false) - /// Removes address from both the direct + background connect lists - /// Due to races, it is possible to call this, and THEN get a connection complete with us as central - fn remove_from_all_lists(&self, address: AddressWithType); // CancelLeConnect -} - -/// The callbacks invoked by the LeAclManager in response to events from the controller -pub trait LeAclManagerConnectionCallbacks { - /// Invoked when an LE connection to a given address completes - fn on_le_connect(&self, address: AddressWithType, result: Result); - /// Invoked when a peer device disconnects from us. The address must match the address - /// supplied on the initial connection. - fn on_disconnect(&self, address: AddressWithType); -} diff --git a/system/rust/src/connection/mocks.rs b/system/rust/src/connection/mocks.rs deleted file mode 100644 index b50e621a896..00000000000 --- a/system/rust/src/connection/mocks.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(test)] -pub mod mock_le_manager; diff --git a/system/rust/src/connection/mocks/mock_le_manager.rs b/system/rust/src/connection/mocks/mock_le_manager.rs deleted file mode 100644 index 879acfac28a..00000000000 --- a/system/rust/src/connection/mocks/mock_le_manager.rs +++ /dev/null @@ -1,174 +0,0 @@ -//! This module mocks the behavior of le_impl in GD (excluding timers). -//! It tracks both the internal state of le_impl, as well as the connect list in the controller. -//! It also enforces all (implicit) invariants of le_impl as documented in le_manager.rs, and -//! asserts on violation. - -use std::{cell::RefCell, collections::HashSet, fmt::Debug, rc::Rc}; - -use crate::{ - connection::{ - attempt_manager::ConnectionMode, - le_manager::{ - ErrorCode, InactiveLeAclManager, LeAclManager, LeAclManagerConnectionCallbacks, - }, - LeConnection, - }, - core::address::AddressWithType, -}; - -#[derive(Clone)] -pub struct MockLeAclManager { - active: Rc>>>, - callbacks: Rc>>>, -} - -impl MockLeAclManager { - pub fn new() -> Self { - Self { active: Rc::new(RefCell::new(None)), callbacks: Rc::new(RefCell::new(None)) } - } - - fn inner(&self) -> Rc { - self.active.borrow().as_ref().unwrap().clone() - } - - pub fn current_acceptlist(&self) -> HashSet { - self.inner().current_acceptlist() - } - - pub fn current_connection_mode(&self) -> Option { - self.inner().current_connection_mode() - } - - pub fn on_le_connect(&self, address: AddressWithType, status: ErrorCode) { - let inner = self.inner(); - inner.on_le_connect(address, status); - drop(inner); - - if status == ErrorCode::SUCCESS { - self.callbacks - .borrow() - .as_deref() - .unwrap() - .on_le_connect(address, Ok(LeConnection { remote_address: address })); - } else { - self.callbacks.borrow().as_deref().unwrap().on_le_connect(address, Err(status)); - } - } - - pub fn on_le_disconnect(&self, address: AddressWithType) { - let inner = self.inner(); - inner.on_le_disconnect(address); - drop(inner); - - self.callbacks.borrow().as_deref().unwrap().on_disconnect(address); - } -} - -impl InactiveLeAclManager for MockLeAclManager { - type ActiveManager = Rc; - - fn register_callbacks( - self, - callbacks: impl LeAclManagerConnectionCallbacks + 'static, - ) -> Self::ActiveManager { - let out = MockActiveLeAclManager::new(); - *self.active.borrow_mut() = Some(out.clone()); - *self.callbacks.borrow_mut() = Some(Box::new(callbacks)); - out - } -} - -#[derive(Debug)] -pub struct MockActiveLeAclManager { - state: RefCell, -} - -#[derive(Clone, Debug)] -struct MockLeManagerInternalState { - direct_connect_list: HashSet, - background_connect_list: HashSet, - currently_connected: HashSet, -} - -impl MockActiveLeAclManager { - pub fn new() -> Rc { - Rc::new(MockActiveLeAclManager { - state: RefCell::new(MockLeManagerInternalState { - direct_connect_list: HashSet::new(), - background_connect_list: HashSet::new(), - currently_connected: HashSet::new(), - }), - }) - } - - pub fn current_acceptlist(&self) -> HashSet { - let state = self.state.borrow(); - &(&state.direct_connect_list | &state.background_connect_list) - - (&state.currently_connected) - } - - pub fn current_connection_mode(&self) -> Option { - let state = self.state.borrow(); - - if !state.direct_connect_list.is_empty() { - Some(ConnectionMode::Direct) - } else if state - .background_connect_list - .difference(&state.currently_connected) - .next() - .is_some() - { - Some(ConnectionMode::Background) - } else { - None - } - } - - pub fn on_le_connect(&self, address: AddressWithType, status: ErrorCode) { - let mut state = self.state.borrow_mut(); - state.direct_connect_list.remove(&address); - if status == ErrorCode::SUCCESS { - let ok = state.currently_connected.insert(address); - assert!(ok, "Already connected"); - } - } - - pub fn on_le_disconnect(&self, address: AddressWithType) { - let mut state = self.state.borrow_mut(); - let ok = state.currently_connected.remove(&address); - assert!(ok, "Not connected"); - } -} - -impl LeAclManager for Rc { - fn add_to_direct_list(&self, address: AddressWithType) { - let mut state = self.state.borrow_mut(); - assert!( - !state.currently_connected.contains(&address), - "Must NOT be currently connected to this address" - ); - let ok = state.direct_connect_list.insert(address); - assert!(ok, "Already in direct connect list"); - } - - fn add_to_background_list(&self, address: AddressWithType) { - let mut state = self.state.borrow_mut(); - assert!( - !state.currently_connected.contains(&address), - "Must NOT be currently connected to this address" - ); - let ok = state.background_connect_list.insert(address); - assert!(ok, "Already in background connect list"); - } - - fn remove_from_all_lists(&self, address: AddressWithType) { - let mut state = self.state.borrow_mut(); - assert!( - !state.currently_connected.contains(&address), - "Must NOT be currently connected to this address" - ); - let ok1 = state.direct_connect_list.remove(&address); - let ok2 = state.background_connect_list.remove(&address); - assert!(ok1 || ok2, "Present in neither direct nor background connect list"); - } -} diff --git a/system/rust/src/core/ffi.rs b/system/rust/src/core/ffi.rs index e69002def94..c81235d7f13 100644 --- a/system/rust/src/core/ffi.rs +++ b/system/rust/src/core/ffi.rs @@ -75,17 +75,10 @@ mod inner { type GattServerCallbacks = crate::gatt::GattServerCallbacks; } - #[namespace = "bluetooth::connection"] - unsafe extern "C++" { - include!("src/connection/ffi/connection_shim.h"); - type LeAclManagerShim = crate::connection::LeAclManagerShim; - } - #[namespace = "bluetooth::rust_shim"] extern "Rust" { fn start( gatt_server_callbacks: UniquePtr, - le_acl_manager: UniquePtr, on_started: Pin<&'static mut Future>, ); diff --git a/system/rust/src/core/ffi/module.cc b/system/rust/src/core/ffi/module.cc index f43e19a1f8c..5e79d143fad 100644 --- a/system/rust/src/core/ffi/module.cc +++ b/system/rust/src/core/ffi/module.cc @@ -22,7 +22,6 @@ #include "btcore/include/module.h" #include "os/log.h" #ifndef TARGET_FLOSS -#include "src/connection/ffi/connection_shim.h" #include "src/core/ffi.rs.h" #include "src/gatt/ffi.rs.h" #endif @@ -65,8 +64,7 @@ future_t* Start() { return fut; } bluetooth::rust_shim::start( - std::make_unique(*callbacks->server), - std::make_unique(), *fut); + std::make_unique(*callbacks->server), *fut); return fut; } diff --git a/system/rust/src/core/mod.rs b/system/rust/src/core/mod.rs index 2f48f196192..3d25dae585c 100644 --- a/system/rust/src/core/mod.rs +++ b/system/rust/src/core/mod.rs @@ -11,7 +11,6 @@ use std::{pin::Pin, rc::Rc, thread}; use cxx::UniquePtr; use crate::{ - connection::{LeAclManagerImpl, LeAclManagerShim}, gatt::ffi::{AttTransportImpl, GattCallbacksImpl}, GlobalModuleRegistry, MainThreadTxMessage, GLOBAL_MODULE_REGISTRY, }; @@ -20,14 +19,12 @@ use self::ffi::{future_ready, Future, GattServerCallbacks}; fn start( gatt_server_callbacks: UniquePtr, - le_acl_manager: UniquePtr, on_started: Pin<&'static mut Future>, ) { thread::spawn(move || { GlobalModuleRegistry::start( Rc::new(GattCallbacksImpl(gatt_server_callbacks)), Rc::new(AttTransportImpl()), - LeAclManagerImpl(le_acl_manager), || { future_ready(on_started); }, diff --git a/system/rust/src/lib.rs b/system/rust/src/lib.rs index b8154a1cd97..adfb665de3f 100644 --- a/system/rust/src/lib.rs +++ b/system/rust/src/lib.rs @@ -15,18 +15,15 @@ //! The core event loop for Rust modules. Here Rust modules are started in //! dependency order. -use connection::le_manager::InactiveLeAclManager; use gatt::{channel::AttTransport, GattCallbacks}; use log::{info, warn}; use tokio::task::LocalSet; -use self::core::shared_box::SharedBox; use std::{rc::Rc, sync::Mutex}; use tokio::runtime::Builder; use tokio::sync::mpsc; -pub mod connection; pub mod core; pub mod gatt; pub mod packets; @@ -47,8 +44,6 @@ pub struct ModuleViews<'a> { pub gatt_incoming_callbacks: Rc, /// Proxies calls into GATT server pub gatt_module: &'a mut gatt::server::GattModule, - /// Proxies calls into connection manager - pub connection_manager: SharedBox, } static GLOBAL_MODULE_REGISTRY: Mutex> = Mutex::new(None); @@ -61,7 +56,6 @@ impl GlobalModuleRegistry { pub fn start( gatt_callbacks: Rc, att_transport: Rc, - le_acl_manager: impl InactiveLeAclManager, on_started: impl FnOnce(), ) { info!("starting Rust modules"); @@ -79,7 +73,6 @@ impl GlobalModuleRegistry { // First, setup FFI and C++ modules let arbiter = gatt::arbiter::initialize_arbiter(); - connection::register_callbacks(); // Now enter the runtime local.block_on(&rt, async move { @@ -88,15 +81,12 @@ impl GlobalModuleRegistry { Rc::new(gatt::callbacks::CallbackTransactionManager::new(gatt_callbacks.clone())); let gatt_module = &mut gatt::server::GattModule::new(att_transport.clone(), arbiter); - let connection_manager = connection::ConnectionManager::new(le_acl_manager); - // All modules that are visible from incoming JNI / top-level interfaces should // be exposed here let mut modules = ModuleViews { gatt_outgoing_callbacks: gatt_callbacks, gatt_incoming_callbacks, gatt_module, - connection_manager, }; // notify upper layer that we are ready to receive messages diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index c7ad2adbbd4..1f5d5b580c3 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -52,9 +52,7 @@ static bool acl_ble_common_connection(const tBLE_BD_ADDR& address_with_type, uin } // Inform any applications that a connection has completed. - if (!com::android::bluetooth::flags::unified_connection_manager()) { - connection_manager::on_connection_complete(address_with_type.bda); - } + connection_manager::on_connection_complete(address_with_type.bda); // Allocate or update the security device record for this device btm_ble_connected(address_with_type.bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, @@ -111,9 +109,7 @@ void acl_ble_enhanced_connection_complete_from_shim( uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout, const RawAddress& local_rpa, const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type, bool can_read_discoverable_characteristics) { - if (!com::android::bluetooth::flags::unified_connection_manager()) { - connection_manager::on_connection_complete(address_with_type.bda); - } + connection_manager::on_connection_complete(address_with_type.bda); tBLE_BD_ADDR resolved_address_with_type; const bool is_in_security_db = @@ -139,9 +135,7 @@ void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type, uint16_t /* btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT); tBLE_BD_ADDR resolved_address_with_type; maybe_resolve_received_address(address_with_type, &resolved_address_with_type); - if (!com::android::bluetooth::flags::unified_connection_manager()) { - connection_manager::on_connection_timed_out_from_shim(resolved_address_with_type.bda); - } + connection_manager::on_connection_timed_out_from_shim(resolved_address_with_type.bda); log::warn("LE connection fail peer:{} bd_addr:{} hci_status:{}", address_with_type, resolved_address_with_type.bda, hci_status_code_text(status)); } else { diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index d88f4471605..fc4a4dcd6c5 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -54,8 +54,6 @@ #include "osi/include/allocator.h" #include "osi/include/properties.h" #include "osi/include/stack_power_telemetry.h" -#include "rust/src/connection/ffi/connection_shim.h" -#include "rust/src/core/ffi/types.h" #include "stack/acl/acl.h" #include "stack/acl/peer_packet_types.h" #include "stack/btm/btm_ble_int.h" @@ -2464,7 +2462,7 @@ void acl_write_automatic_flush_timeout(const RawAddress& bd_addr, uint16_t flush btsnd_hcic_write_auto_flush_tout(p_acl->hci_handle, flush_timeout_in_ticks); } -bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, +bool acl_create_le_connection_with_id(uint8_t /* id */, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type) { tBLE_BD_ADDR address_with_type{ .type = addr_type, @@ -2484,13 +2482,8 @@ bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, return false; } - if (com::android::bluetooth::flags::unified_connection_manager()) { - bluetooth::connection::GetConnectionManager().start_direct_connection( - id, bluetooth::core::ToRustAddress(address_with_type)); - } else { - bluetooth::shim::ACL_AcceptLeConnectionFrom(address_with_type, - /* is_direct */ true); - } + bluetooth::shim::ACL_AcceptLeConnectionFrom(address_with_type, + /* is_direct */ true); return true; } diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc index af7869423f1..cdc7e27f91b 100644 --- a/system/stack/btm/btm_dev.cc +++ b/system/stack/btm/btm_dev.cc @@ -39,7 +39,6 @@ #include "main/shim/acl_api.h" #include "main/shim/dumpsys.h" #include "osi/include/allocator.h" -#include "rust/src/connection/ffi/connection_shim.h" #include "stack/btm/btm_sec.h" #include "stack/include/acl_api.h" #include "stack/include/bt_octets.h" @@ -182,12 +181,7 @@ bool BTM_SecDeleteDevice(const RawAddress& bd_addr) { RawAddress bda = p_dev_rec->bd_addr; log::info("Remove device {} from filter accept list before delete record", bd_addr); - if (com::android::bluetooth::flags::unified_connection_manager()) { - bluetooth::connection::GetConnectionManager().stop_all_connections_to_device( - bluetooth::connection::ResolveRawAddress(bda)); - } else { - bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bda)); - } + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bda)); const auto device_type = p_dev_rec->device_type; const auto bond_type = p_dev_rec->sec_rec.bond_type; diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index a5a863708f1..cf723d1e1e1 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -35,7 +35,6 @@ #include "internal_include/stack_config.h" #include "os/system_properties.h" #include "osi/include/allocator.h" -#include "rust/src/connection/ffi/connection_shim.h" #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" #include "stack/gatt/connection_manager.h" @@ -1378,11 +1377,7 @@ void GATT_Deregister(tGATT_IF gatt_if) { } } - if (com::android::bluetooth::flags::unified_connection_manager()) { - bluetooth::connection::GetConnectionManager().remove_client(gatt_if); - } else { - connection_manager::on_app_deregistered(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); @@ -1506,20 +1501,10 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE ad ret = false; } else { log::debug("Adding to background connect to device:{}", bd_addr); - if (com::android::bluetooth::flags::unified_connection_manager()) { - if (connection_type == BTM_BLE_BKG_CONNECT_ALLOW_LIST) { - bluetooth::connection::GetConnectionManager().add_background_connection( - gatt_if, bluetooth::connection::ResolveRawAddress(bd_addr)); - ret = true; // TODO(aryarahul): error handling - } else { - log::fatal("unimplemented, TODO(aryarahul)"); - } + if (connection_type == BTM_BLE_BKG_CONNECT_ALLOW_LIST) { + ret = connection_manager::background_connect_add(gatt_if, bd_addr); } else { - if (connection_type == BTM_BLE_BKG_CONNECT_ALLOW_LIST) { - ret = connection_manager::background_connect_add(gatt_if, bd_addr); - } else { - ret = connection_manager::background_connect_targeted_announcement_add(gatt_if, bd_addr); - } + ret = connection_manager::background_connect_targeted_announcement_add(gatt_if, bd_addr); } } } @@ -1602,14 +1587,9 @@ bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_dir } } - if (com::android::bluetooth::flags::unified_connection_manager()) { - bluetooth::connection::GetConnectionManager().stop_all_connections_to_device( - bluetooth::connection::ResolveRawAddress(bd_addr)); - } else { - if (!connection_manager::remove_unconditional(bd_addr)) { - log::error("no app associated with the bg device for unconditional removal"); - return false; - } + if (!connection_manager::remove_unconditional(bd_addr)) { + log::error("no app associated with the bg device for unconditional removal"); + return false; } return true; diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index 299b847c5a4..7c8a2566100 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -35,7 +35,6 @@ #include "main/shim/acl_api.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" -#include "rust/src/connection/ffi/connection_shim.h" #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" @@ -261,20 +260,14 @@ void gatt_cancel_connect(const RawAddress& bd_addr, tBT_TRANSPORT transport) { /* This shall be call only when device is not connected */ log::debug("{}, transport {}", bd_addr, transport); - if (com::android::bluetooth::flags::unified_connection_manager()) { - // TODO(aryarahul): this might not be necessary now that the connection - // manager handles GATT client closure correctly in GATT_Deregister - bluetooth::connection::GetConnectionManager().stop_all_connections_to_device( - bluetooth::connection::ResolveRawAddress(bd_addr)); - } else { - if (!connection_manager::direct_connect_remove(CONN_MGR_ID_L2CAP, bd_addr)) { - bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bd_addr)); - log::info( - "GATT connection manager has no record but removed filter " - "acceptlist gatt_if:{} peer:{}", - static_cast(CONN_MGR_ID_L2CAP), bd_addr); - } + if (!connection_manager::direct_connect_remove(CONN_MGR_ID_L2CAP, bd_addr)) { + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bd_addr)); + log::info( + "GATT connection manager has no record but removed filter " + "acceptlist gatt_if:{} peer:{}", + static_cast(CONN_MGR_ID_L2CAP), bd_addr); } + gatt_cleanup_upon_disc(bd_addr, GATT_CONN_TERMINATE_LOCAL_HOST, transport); } @@ -1010,14 +1003,7 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) { tGATT_REG* p_reg; tCONN_ID conn_id; - std::set apps = {}; - if (com::android::bluetooth::flags::unified_connection_manager()) { - // TODO(aryarahul): this should be done via callbacks passed into the - // connection manager - apps = {}; - } else { - apps = connection_manager::get_apps_connecting_to(p_tcb->peer_bda); - } + std::set apps = connection_manager::get_apps_connecting_to(p_tcb->peer_bda); /* notifying all applications for the connection up event */ @@ -1070,9 +1056,7 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) { } /* Remove the direct connection */ - if (!com::android::bluetooth::flags::unified_connection_manager()) { - connection_manager::on_connection_complete(p_tcb->peer_bda); - } + connection_manager::on_connection_complete(p_tcb->peer_bda); if (p_tcb->att_lcid == L2CAP_ATT_CID) { if (!p_tcb->app_hold_link.empty()) { diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index ec449c0ecdd..57dbb6e71aa 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -36,7 +36,6 @@ #include "main/shim/dumpsys.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" -#include "rust/src/connection/ffi/connection_shim.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" #include "stack/eatt/eatt.h" @@ -1661,26 +1660,21 @@ bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) { gatt_disconnect(p_tcb); } - if (com::android::bluetooth::flags::unified_connection_manager()) { - bluetooth::connection::GetConnectionManager().stop_direct_connection( - gatt_if, bluetooth::connection::ResolveRawAddress(bda)); - } else { - if (!connection_manager::direct_connect_remove(gatt_if, bda)) { - if (!connection_manager::is_background_connection(bda)) { - if (!com::android::bluetooth::flags::gatt_fix_multiple_direct_connect() || - p_tcb->app_hold_link.empty()) { - bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bda)); - } - log::info( - "Gatt connection manager has no background record but removed " - "filter acceptlist gatt_if:{} peer:{}", - gatt_if, bda); - } else { - log::info( - "Gatt connection manager maintains a background record preserving " - "filter acceptlist gatt_if:{} peer:{}", - gatt_if, bda); + if (!connection_manager::direct_connect_remove(gatt_if, bda)) { + if (!connection_manager::is_background_connection(bda)) { + if (!com::android::bluetooth::flags::gatt_fix_multiple_direct_connect() || + p_tcb->app_hold_link.empty()) { + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bda)); } + log::info( + "Gatt connection manager has no background record but removed " + "filter acceptlist gatt_if:{} peer:{}", + gatt_if, bda); + } else { + log::info( + "Gatt connection manager maintains a background record preserving " + "filter acceptlist gatt_if:{} peer:{}", + gatt_if, bda); } } @@ -1979,14 +1973,7 @@ bool gatt_auto_connect_dev_remove(tGATT_IF gatt_if, const RawAddress& bd_addr) { if (p_tcb) { gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false); } - if (com::android::bluetooth::flags::unified_connection_manager()) { - bluetooth::connection::GetConnectionManager().remove_background_connection( - gatt_if, bluetooth::connection::ResolveRawAddress(bd_addr)); - // TODO(aryarahul): handle failure case - return true; - } else { - return connection_manager::background_connect_remove(gatt_if, bd_addr); - } + return connection_manager::background_connect_remove(gatt_if, bd_addr); } tCONN_ID gatt_create_conn_id(tTCB_IDX tcb_idx, tGATT_IF gatt_if) { diff --git a/system/test/mock/mock_rust_ffi_connection_shim.cc b/system/test/mock/mock_rust_ffi_connection_shim.cc deleted file mode 100644 index aeb62182ba4..00000000000 --- a/system/test/mock/mock_rust_ffi_connection_shim.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2023 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 "rust/src/connection/ffi/connection_shim.h" -#include "test/common/mock_functions.h" - -namespace bluetooth { - -namespace connection { - -RustConnectionManager& GetConnectionManager() { - static RustConnectionManager manager = {}; - inc_func_call_count(__func__); - return manager; -} - -core::AddressWithType ResolveRawAddress(RawAddress /* bd_addr */) { - inc_func_call_count(__func__); - return {}; -} - -} // namespace connection -} // namespace bluetooth -- GitLab From ebd218b0368be7d80b9d38fae657b98cf5faaef6 Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Wed, 9 Oct 2024 17:56:21 +0000 Subject: [PATCH 236/875] mmi2grpc: run isort and format on mmi2grpc Bug: 371207046 Test: atest pts-bot Change-Id: Ib60a0e2c7d9c2063dd990e4cc0df531dabeb8214 --- android/pandora/mmi2grpc/mmi2grpc/__init__.py | 14 +++---- android/pandora/mmi2grpc/mmi2grpc/_helpers.py | 2 +- android/pandora/mmi2grpc/mmi2grpc/_proxy.py | 4 +- .../pandora/mmi2grpc/mmi2grpc/_rootcanal.py | 2 +- android/pandora/mmi2grpc/mmi2grpc/a2dp.py | 3 +- android/pandora/mmi2grpc/mmi2grpc/avrcp.py | 5 +-- android/pandora/mmi2grpc/mmi2grpc/gap.py | 17 +++++---- android/pandora/mmi2grpc/mmi2grpc/gatt.py | 37 +++++-------------- android/pandora/mmi2grpc/mmi2grpc/hap.py | 18 +++++---- android/pandora/mmi2grpc/mmi2grpc/hfp.py | 15 ++++---- android/pandora/mmi2grpc/mmi2grpc/hid.py | 4 +- android/pandora/mmi2grpc/mmi2grpc/hogp.py | 7 ++-- android/pandora/mmi2grpc/mmi2grpc/l2cap.py | 9 ++--- android/pandora/mmi2grpc/mmi2grpc/map.py | 1 - android/pandora/mmi2grpc/mmi2grpc/opp.py | 1 - android/pandora/mmi2grpc/mmi2grpc/pan.py | 3 +- android/pandora/mmi2grpc/mmi2grpc/pbap.py | 1 - android/pandora/mmi2grpc/mmi2grpc/rfcomm.py | 13 +++---- android/pandora/mmi2grpc/mmi2grpc/sdp.py | 12 +++--- android/pandora/mmi2grpc/mmi2grpc/sm.py | 9 ++--- android/pandora/mmi2grpc/mmi2grpc/vcp.py | 5 +-- 21 files changed, 74 insertions(+), 108 deletions(-) diff --git a/android/pandora/mmi2grpc/mmi2grpc/__init__.py b/android/pandora/mmi2grpc/mmi2grpc/__init__.py index 1c24ef4bd0c..00e3094965e 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/__init__.py +++ b/android/pandora/mmi2grpc/mmi2grpc/__init__.py @@ -15,17 +15,19 @@ __version__ = "0.0.1" +import sys +import time from threading import Thread from typing import List -import time -import sys import grpc - +from mmi2grpc._helpers import format_proxy +from mmi2grpc._modem import Modem +from mmi2grpc._rootcanal import RootCanal from mmi2grpc.a2dp import A2DPProxy from mmi2grpc.avrcp import AVRCPProxy -from mmi2grpc.gatt import GATTProxy from mmi2grpc.gap import GAPProxy +from mmi2grpc.gatt import GATTProxy from mmi2grpc.hap import HAPProxy from mmi2grpc.hfp import HFPProxy from mmi2grpc.hid import HIDProxy @@ -39,10 +41,6 @@ from mmi2grpc.rfcomm import RFCOMMProxy from mmi2grpc.sdp import SDPProxy from mmi2grpc.sm import SMProxy from mmi2grpc.vcp import VCPProxy -from mmi2grpc._helpers import format_proxy -from mmi2grpc._rootcanal import RootCanal -from mmi2grpc._modem import Modem - from pandora.host_grpc import Host PANDORA_SERVER_PORT = 8999 diff --git a/android/pandora/mmi2grpc/mmi2grpc/_helpers.py b/android/pandora/mmi2grpc/mmi2grpc/_helpers.py index 9bc9dc0b026..8a5013113af 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/_helpers.py +++ b/android/pandora/mmi2grpc/mmi2grpc/_helpers.py @@ -17,9 +17,9 @@ Facilitates the implementation of a new profile proxy or a PTS MMI. """ import functools +import re import textwrap import unittest -import re DOCSTRING_WIDTH = 80 - 8 # 80 cols - 8 indentation spaces diff --git a/android/pandora/mmi2grpc/mmi2grpc/_proxy.py b/android/pandora/mmi2grpc/mmi2grpc/_proxy.py index 711b1c9aeec..77ca52d3fa4 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/_proxy.py +++ b/android/pandora/mmi2grpc/mmi2grpc/_proxy.py @@ -13,9 +13,7 @@ # limitations under the License. """Profile proxy base module.""" -from mmi2grpc._helpers import format_function -from mmi2grpc._helpers import assert_description - +from mmi2grpc._helpers import assert_description, format_function from pandora_experimental.os_grpc import Os diff --git a/android/pandora/mmi2grpc/mmi2grpc/_rootcanal.py b/android/pandora/mmi2grpc/mmi2grpc/_rootcanal.py index e346647dd77..42ef33f68bf 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/_rootcanal.py +++ b/android/pandora/mmi2grpc/mmi2grpc/_rootcanal.py @@ -15,8 +15,8 @@ Copied from tools/rootcanal/scripts/test_channel.py """ -import socket import enum +import socket from time import sleep diff --git a/android/pandora/mmi2grpc/mmi2grpc/a2dp.py b/android/pandora/mmi2grpc/mmi2grpc/a2dp.py index e4a03bff35e..5426e6bc7df 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/a2dp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/a2dp.py @@ -17,12 +17,11 @@ import time from typing import Optional from grpc import RpcError - from mmi2grpc._audio import AudioSignal from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from pandora.a2dp_grpc import A2DP -from pandora.a2dp_pb2 import Sink, Source, PlaybackAudioRequest +from pandora.a2dp_pb2 import PlaybackAudioRequest, Sink, Source from pandora.host_grpc import Host from pandora.host_pb2 import Connection diff --git a/android/pandora/mmi2grpc/mmi2grpc/avrcp.py b/android/pandora/mmi2grpc/mmi2grpc/avrcp.py index 3ed97ce97e4..9fbc55d56c9 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/avrcp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/avrcp.py @@ -17,17 +17,16 @@ import time from typing import Optional from grpc import RpcError - from mmi2grpc._audio import AudioSignal from mmi2grpc._helpers import assert_description from mmi2grpc._proxy import ProfileProxy from pandora.a2dp_grpc import A2DP from pandora.a2dp_pb2 import Sink, Source -from pandora_experimental.avrcp_grpc import AVRCP from pandora.host_grpc import Host from pandora.host_pb2 import Connection +from pandora_experimental.avrcp_grpc import AVRCP from pandora_experimental.mediaplayer_grpc import MediaPlayer -from pandora_experimental.mediaplayer_pb2 import NONE, ALL, GROUP +from pandora_experimental.mediaplayer_pb2 import ALL, GROUP, NONE class AVRCPProxy(ProfileProxy): diff --git a/android/pandora/mmi2grpc/mmi2grpc/gap.py b/android/pandora/mmi2grpc/mmi2grpc/gap.py index 4fd58b94bbd..8ea6a7841fc 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/gap.py +++ b/android/pandora/mmi2grpc/mmi2grpc/gap.py @@ -12,19 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. +import sys from threading import Thread -from mmi2grpc._helpers import assert_description, match_description -from mmi2grpc._rootcanal import Dongle -from mmi2grpc._proxy import ProfileProxy from time import sleep -import sys -from pandora_experimental.gatt_grpc import GATT -from pandora_experimental.gatt_pb2 import GattServiceParams, GattCharacteristicParams +from mmi2grpc._helpers import assert_description, match_description +from mmi2grpc._proxy import ProfileProxy +from mmi2grpc._rootcanal import Dongle from pandora.host_grpc import Host -from pandora.host_pb2 import PUBLIC, RANDOM, DISCOVERABLE_GENERAL, NOT_DISCOVERABLE, DISCOVERABLE_LIMITED, NOT_CONNECTABLE, DataTypes +from pandora.host_pb2 import (DISCOVERABLE_GENERAL, DISCOVERABLE_LIMITED, NOT_CONNECTABLE, NOT_DISCOVERABLE, PUBLIC, + RANDOM, DataTypes) from pandora.security_grpc import Security, SecurityStorage -from pandora.security_pb2 import LEVEL1, LEVEL2, LE_LEVEL3, PairingEventAnswer +from pandora.security_pb2 import LE_LEVEL3, LEVEL1, LEVEL2, PairingEventAnswer +from pandora_experimental.gatt_grpc import GATT +from pandora_experimental.gatt_pb2 import (GattCharacteristicParams, GattServiceParams) class GAPProxy(ProfileProxy): diff --git a/android/pandora/mmi2grpc/mmi2grpc/gatt.py b/android/pandora/mmi2grpc/mmi2grpc/gatt.py index 5593f59dc22..86cafe5ea57 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/gatt.py +++ b/android/pandora/mmi2grpc/mmi2grpc/gatt.py @@ -20,38 +20,19 @@ from threading import Thread from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from mmi2grpc._rootcanal import Dongle - -from pandora_experimental.gatt_grpc import GATT from pandora.host_grpc import Host from pandora.host_pb2 import PUBLIC, RANDOM from pandora.security_grpc import Security, SecurityStorage from pandora.security_pb2 import PairingEventAnswer -from pandora_experimental.gatt_pb2 import ( - INVALID_HANDLE, - READ_NOT_PERMITTED, - UNKNOWN_ERROR, - INSUFFICIENT_AUTHENTICATION, - ATTRIBUTE_NOT_FOUND, - APPLICATION_ERROR, - INVALID_ATTRIBUTE_LENGTH, - WRITE_NOT_PERMITTED, - PERMISSION_NONE, - PROPERTY_READ, - PROPERTY_WRITE, - PERMISSION_READ, - PERMISSION_WRITE, - PERMISSION_READ_ENCRYPTED, - PERMISSION_READ_ENCRYPTED_MITM, - PERMISSION_WRITE_ENCRYPTED, - PERMISSION_WRITE_ENCRYPTED_MITM, - ENABLE_NOTIFICATION_VALUE, - ENABLE_INDICATION_VALUE, -) -from pandora_experimental.gatt_pb2 import GattServiceParams -from pandora_experimental.gatt_pb2 import GattCharacteristicParams -from pandora_experimental.gatt_pb2 import GattDescriptorParams -from pandora_experimental.gatt_pb2 import ReadCharacteristicResponse -from pandora_experimental.gatt_pb2 import ReadCharacteristicsFromUuidResponse +from pandora_experimental.gatt_grpc import GATT +from pandora_experimental.gatt_pb2 import (APPLICATION_ERROR, ATTRIBUTE_NOT_FOUND, ENABLE_INDICATION_VALUE, + ENABLE_NOTIFICATION_VALUE, INSUFFICIENT_AUTHENTICATION, + INVALID_ATTRIBUTE_LENGTH, INVALID_HANDLE, PERMISSION_NONE, PERMISSION_READ, + PERMISSION_READ_ENCRYPTED, PERMISSION_READ_ENCRYPTED_MITM, PERMISSION_WRITE, + PERMISSION_WRITE_ENCRYPTED, PERMISSION_WRITE_ENCRYPTED_MITM, PROPERTY_READ, + PROPERTY_WRITE, READ_NOT_PERMITTED, UNKNOWN_ERROR, WRITE_NOT_PERMITTED, + GattCharacteristicParams, GattDescriptorParams, GattServiceParams, + ReadCharacteristicResponse, ReadCharacteristicsFromUuidResponse) # Tests that need GATT cache cleared before discovering services. NEEDS_CACHE_CLEARED = { diff --git a/android/pandora/mmi2grpc/mmi2grpc/hap.py b/android/pandora/mmi2grpc/mmi2grpc/hap.py index c69dea323bc..98439910c2c 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/hap.py +++ b/android/pandora/mmi2grpc/mmi2grpc/hap.py @@ -12,22 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -import threading -import uuid -import string import random +import string +import threading import time +import uuid from mmi2grpc._audio import AudioSignal from mmi2grpc._helpers import assert_description, match_description -from mmi2grpc._rootcanal import Dongle from mmi2grpc._proxy import ProfileProxy +from mmi2grpc._rootcanal import Dongle from pandora.host_grpc import Host from pandora.host_pb2 import RANDOM from pandora.security_grpc import Security from pandora.security_pb2 import LE_LEVEL3, PairingEventAnswer -from pandora_experimental.hap_grpc import HAP from pandora_experimental.gatt_grpc import GATT +from pandora_experimental.hap_grpc import HAP from pandora_experimental.hap_pb2 import HaPlaybackAudioRequest BASE_UUID = uuid.UUID("00000000-0000-1000-8000-00805F9B34FB") @@ -40,9 +40,11 @@ CCCD_UUID = 0x2902 AUDIO_SIGNAL_AMPLITUDE = 0.8 AUDIO_SIGNAL_SAMPLING_RATE = 44100 + def short_uuid(full: uuid.UUID) -> int: return (uuid.UUID(full).int - BASE_UUID.int) >> 96 + class HAPProxy(ProfileProxy): def __init__(self, channel, rootcanal): @@ -88,7 +90,7 @@ class HAPProxy(ProfileProxy): # This MMI can be called multiple times, wait only for the first time if not self.preset_list: - # Android reads all presets after device is paired. Wait for initial preset record before sending next request. + # Android reads all presets after device is paired. Wait for initial preset record before sending next request. self.preset_list = self.hap.WaitPresetChanged().preset_record_list assert self.preset_list @@ -214,11 +216,11 @@ class HAPProxy(ProfileProxy): @assert_description def IUT_CONFIRM_READY_TO_RECEIVE_PRESET_CHANGED(self, test: str, **kwargs): - """ + """ Please click OK when IUT is ready to receive Preset Changed message. """ - return "OK" + return "OK" @match_description def IUT_ORDER_WRITE_SET_ACTIVE_PRESET_INDEX(self, test: str, index: str, **kwargs): diff --git a/android/pandora/mmi2grpc/mmi2grpc/hfp.py b/android/pandora/mmi2grpc/mmi2grpc/hfp.py index 5fdfe023fbd..bc4ac603daa 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/hfp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/hfp.py @@ -13,19 +13,18 @@ # limitations under the License. """HFP proxy module.""" +import sys +import threading +import time + from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy - -from pandora_experimental.hfp_grpc import HFP from pandora.host_grpc import Host -from pandora.host_pb2 import DISCOVERABLE_GENERAL, CONNECTABLE +from pandora.host_pb2 import CONNECTABLE, DISCOVERABLE_GENERAL from pandora.security_grpc import Security, SecurityStorage from pandora.security_pb2 import PairingEventAnswer -from pandora_experimental.hfp_pb2 import AUDIO_PATH_HANDSFREE, AUDIO_PATH_SPEAKERS - -import sys -import threading -import time +from pandora_experimental.hfp_grpc import HFP +from pandora_experimental.hfp_pb2 import (AUDIO_PATH_HANDSFREE, AUDIO_PATH_SPEAKERS) # Standard time to wait before asking for waitConnection WAIT_DELAY_BEFORE_CONNECTION = 2 diff --git a/android/pandora/mmi2grpc/mmi2grpc/hid.py b/android/pandora/mmi2grpc/mmi2grpc/hid.py index 421da8683f3..6a65cf8c3d8 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/hid.py +++ b/android/pandora/mmi2grpc/mmi2grpc/hid.py @@ -14,11 +14,11 @@ from threading import Thread from time import sleep + from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy - -from pandora_experimental.hid_grpc import HID from pandora.host_grpc import Host +from pandora_experimental.hid_grpc import HID from pandora_experimental.hid_pb2 import HID_REPORT_TYPE_OUTPUT diff --git a/android/pandora/mmi2grpc/mmi2grpc/hogp.py b/android/pandora/mmi2grpc/mmi2grpc/hogp.py index 7f4e56dedef..983eed6e7f7 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/hogp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/hogp.py @@ -12,16 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -import threading -import textwrap -import uuid import re import sys +import textwrap +import threading +import uuid from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from mmi2grpc._rootcanal import Dongle - from pandora.host_grpc import Host from pandora.host_pb2 import RANDOM from pandora.security_grpc import Security diff --git a/android/pandora/mmi2grpc/mmi2grpc/l2cap.py b/android/pandora/mmi2grpc/mmi2grpc/l2cap.py index 09136bedb8a..1648d20511b 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/l2cap.py +++ b/android/pandora/mmi2grpc/mmi2grpc/l2cap.py @@ -13,20 +13,17 @@ # limitations under the License. import sys +from typing import Dict, Optional -from mmi2grpc._helpers import assert_description -from mmi2grpc._helpers import match_description +from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from mmi2grpc._rootcanal import Dongle - from pandora.host_grpc import Host from pandora.host_pb2 import PUBLIC, RANDOM, Connection from pandora.l2cap_grpc import L2CAP from pandora.l2cap_pb2 import CreditBasedChannelRequest -from pandora.security_pb2 import PairingEventAnswer from pandora.security_grpc import Security - -from typing import Optional, Dict +from pandora.security_pb2 import PairingEventAnswer class L2CAPProxy(ProfileProxy): diff --git a/android/pandora/mmi2grpc/mmi2grpc/map.py b/android/pandora/mmi2grpc/mmi2grpc/map.py index 04bdcbb139a..f08f1d634a9 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/map.py +++ b/android/pandora/mmi2grpc/mmi2grpc/map.py @@ -17,7 +17,6 @@ from typing import Optional from mmi2grpc._helpers import assert_description from mmi2grpc._proxy import ProfileProxy - from pandora.host_grpc import Host from pandora.host_pb2 import Connection from pandora_experimental.map_grpc import Map as MapProfile diff --git a/android/pandora/mmi2grpc/mmi2grpc/opp.py b/android/pandora/mmi2grpc/mmi2grpc/opp.py index 29af9924e79..5f9179075f8 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/opp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/opp.py @@ -17,7 +17,6 @@ from typing import Optional from mmi2grpc._helpers import assert_description from mmi2grpc._proxy import ProfileProxy - from pandora.host_grpc import Host from pandora.host_pb2 import Connection from pandora_experimental.opp_grpc import Opp diff --git a/android/pandora/mmi2grpc/mmi2grpc/pan.py b/android/pandora/mmi2grpc/mmi2grpc/pan.py index 7654658f194..2d79a547a38 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/pan.py +++ b/android/pandora/mmi2grpc/mmi2grpc/pan.py @@ -17,10 +17,9 @@ import sys from mmi2grpc._helpers import assert_description from mmi2grpc._proxy import ProfileProxy - from pandora.host_grpc import Host -from pandora_experimental.pan_grpc import PAN from pandora_experimental.os_grpc import Os +from pandora_experimental.pan_grpc import PAN # IP address of PTS TSPX_PTS_IP_ADDRESS = "192.168.168.100" diff --git a/android/pandora/mmi2grpc/mmi2grpc/pbap.py b/android/pandora/mmi2grpc/mmi2grpc/pbap.py index 1453e7edac8..8072ed7c059 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/pbap.py +++ b/android/pandora/mmi2grpc/mmi2grpc/pbap.py @@ -16,7 +16,6 @@ from typing import Optional from grpc import RpcError - from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from pandora.host_grpc import Host diff --git a/android/pandora/mmi2grpc/mmi2grpc/rfcomm.py b/android/pandora/mmi2grpc/mmi2grpc/rfcomm.py index 6c3eb58f407..667cbe1ca62 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/rfcomm.py +++ b/android/pandora/mmi2grpc/mmi2grpc/rfcomm.py @@ -13,16 +13,15 @@ # limitations under the License. """Rfcomm proxy module.""" +import os +import socket +import sys +import threading + from mmi2grpc._helpers import assert_description from mmi2grpc._proxy import ProfileProxy - -from pandora_experimental.rfcomm_grpc import RFCOMM from pandora.host_grpc import Host - -import sys -import threading -import os -import socket +from pandora_experimental.rfcomm_grpc import RFCOMM class RFCOMMProxy(ProfileProxy): diff --git a/android/pandora/mmi2grpc/mmi2grpc/sdp.py b/android/pandora/mmi2grpc/mmi2grpc/sdp.py index 957d0f6ddb3..998b99e28b1 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/sdp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/sdp.py @@ -13,16 +13,16 @@ # limitations under the License. """SDP proxy module.""" -from mmi2grpc._helpers import assert_description, match_description -from mmi2grpc._proxy import ProfileProxy - -import sys -import unittest -import threading import os import socket +import sys +import threading +import unittest from itertools import filterfalse +from mmi2grpc._helpers import assert_description, match_description +from mmi2grpc._proxy import ProfileProxy + # As per Bluetooth Assigned Numbers UUID_TO_SERVICE_NAME = { # Service Classes and Profiles diff --git a/android/pandora/mmi2grpc/mmi2grpc/sm.py b/android/pandora/mmi2grpc/mmi2grpc/sm.py index 09bd855a256..25790cbf157 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/sm.py +++ b/android/pandora/mmi2grpc/mmi2grpc/sm.py @@ -12,19 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. """SMP proxy module.""" +import asyncio +import sys from queue import Empty, Queue from threading import Thread -import sys -import asyncio from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from mmi2grpc._rootcanal import Dongle - -from pandora.security_grpc import Security -from pandora.security_pb2 import LE_LEVEL3, PairingEventAnswer from pandora.host_grpc import Host from pandora.host_pb2 import PUBLIC, RANDOM +from pandora.security_grpc import Security +from pandora.security_pb2 import LE_LEVEL3, PairingEventAnswer def debug(*args, **kwargs): diff --git a/android/pandora/mmi2grpc/mmi2grpc/vcp.py b/android/pandora/mmi2grpc/mmi2grpc/vcp.py index f952024d27a..905f5519169 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/vcp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/vcp.py @@ -17,11 +17,10 @@ import threading from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from mmi2grpc._rootcanal import Dongle - -from pandora.security_grpc import Security -from pandora.security_pb2 import LE_LEVEL3, PairingEventAnswer from pandora.host_grpc import Host from pandora.host_pb2 import PUBLIC, RANDOM +from pandora.security_grpc import Security +from pandora.security_pb2 import LE_LEVEL3, PairingEventAnswer from pandora_experimental.le_audio_grpc import LeAudio -- GitLab From ea4834880f8fcdf7959487a9bca3301c85e0d7ff Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Wed, 9 Oct 2024 21:14:27 +0000 Subject: [PATCH 237/875] Revert "Modified LeAudioServiceDiscoveryTest" Revert submission 3283939 Reason for revert: b/372518178 Reverted changes: /q/submissionid:3283939 Change-Id: I0017ea6ebc6dca4994f2e88475c529e76ad5925e --- .../service_discovery/LeAudioServiceDiscoveryTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java index 541ea815ff4..27b0f106e45 100644 --- a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java +++ b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java @@ -269,11 +269,13 @@ public class LeAudioServiceDiscoveryTest { BluetoothDevice.EXTRA_UUID, Matchers.allOf( Matchers.hasItemInArray(BluetoothUuid.HFP), + Matchers.hasItemInArray(BluetoothUuid.HID), Matchers.hasItemInArray(BluetoothUuid.A2DP_SOURCE), Matchers.hasItemInArray(BluetoothUuid.A2DP_SINK), Matchers.hasItemInArray(BluetoothUuid.AVRCP), Matchers.hasItemInArray(BluetoothUuid.LE_AUDIO), - Matchers.hasItemInArray(BluetoothUuid.BATTERY)))); + Matchers.hasItemInArray(BluetoothUuid.BATTERY), + Matchers.hasItemInArray(BluetoothUuid.HOGP)))); unregisterIntentActions( BluetoothDevice.ACTION_UUID, BluetoothDevice.ACTION_ACL_CONNECTED, -- GitLab From 5a0e94248057fa2e7d2f9fdb99d4c33be6315130 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Wed, 9 Oct 2024 21:14:27 +0000 Subject: [PATCH 238/875] Revert "Modified HidHostDualModeTest as per new hid rpc call" Revert submission 3283939 Reason for revert: b/372518178 Reverted changes: /q/submissionid:3283939 Change-Id: I34e66f424ad310dee5e96a8a3689b8cdda293b3e --- .../src/android/bluetooth/hid/HidHostDualModeTest.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java index bcc2cac8b3c..778fc239e07 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java @@ -83,9 +83,6 @@ import org.mockito.MockitoAnnotations; import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.stubbing.Answer; -import pandora.HIDGrpc; -import pandora.HidProto.HidServiceType; -import pandora.HidProto.ServiceRequest; import pandora.HostProto.AdvertiseRequest; import pandora.HostProto.OwnAddressType; @@ -109,7 +106,6 @@ public class HidHostDualModeTest { InstrumentationRegistry.getInstrumentation().getTargetContext(); private final BluetoothAdapter mAdapter = mContext.getSystemService(BluetoothManager.class).getAdapter(); - private HIDGrpc.HIDBlockingStub mHidBlockingStub; @Rule(order = 0) public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -276,11 +272,6 @@ public class HidHostDualModeTest { mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.HEADSET); BluetoothHeadset hfpService = (BluetoothHeadset) verifyProfileServiceConnected(BluetoothProfile.HEADSET); - mHidBlockingStub = mBumble.hidBlocking(); - mHidBlockingStub.registerService( - ServiceRequest.newBuilder() - .setServiceType(HidServiceType.SERVICE_TYPE_BOTH) - .build()); AdvertiseRequest request = AdvertiseRequest.newBuilder() -- GitLab From fe984d0365dfd1feb3a2b42874147e7df017bf9d Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Wed, 9 Oct 2024 21:14:27 +0000 Subject: [PATCH 239/875] Revert "Modified HidHostTest as per new hid rpc call" Revert submission 3283939 Reason for revert: b/372518178 Reverted changes: /q/submissionid:3283939 Change-Id: I4ed85b0e0027996d2c5cbd7b9e0276ad1814a634 --- .../tests/bumble/src/android/bluetooth/hid/HidHostTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java index 835480b7b2f..4e11e4d4af8 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java @@ -44,10 +44,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import pandora.HIDGrpc; -import pandora.HidProto.HidServiceType; import pandora.HidProto.ProtocolModeEvent; import pandora.HidProto.ReportEvent; -import pandora.HidProto.ServiceRequest; import java.time.Duration; import java.util.Iterator; @@ -235,10 +233,6 @@ public class HidHostTest { mAdapter.getProfileProxy( mContext, mBluetoothProfileServiceListener, BluetoothProfile.HEADSET); mHidBlockingStub = mBumble.hidBlocking(); - mHidBlockingStub.registerService( - ServiceRequest.newBuilder() - .setServiceType(HidServiceType.SERVICE_TYPE_HID) - .build()); mFutureConnectionIntent = SettableFuture.create(); mDevice = mBumble.getRemoteDevice(); -- GitLab From f215738226b813a78072d8f2313b6dc4288defef Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Wed, 9 Oct 2024 21:14:27 +0000 Subject: [PATCH 240/875] Revert "Bumble Java Android Headtracker Test Infra Changes" Revert submission 3283939 Reason for revert: b/372518178 Reverted changes: /q/submissionid:3283939 Change-Id: I33951cb4b79b0c442ad87b6f0c1c348e803060cd --- .../interfaces/pandora_experimental/hid.proto | 11 ----- pandora/server/bumble_experimental/hid.py | 46 ++++++------------- 2 files changed, 14 insertions(+), 43 deletions(-) diff --git a/pandora/interfaces/pandora_experimental/hid.proto b/pandora/interfaces/pandora_experimental/hid.proto index a153dc41d81..709d1577ff1 100644 --- a/pandora/interfaces/pandora_experimental/hid.proto +++ b/pandora/interfaces/pandora_experimental/hid.proto @@ -7,8 +7,6 @@ option java_outer_classname = "HidProto"; import "google/protobuf/empty.proto"; service HID { - // Register service - rpc RegisterService(ServiceRequest) returns (google.protobuf.Empty); // Connect HID Host rpc ConnectHost(google.protobuf.Empty) returns (google.protobuf.Empty); // Disconnect HID Host @@ -41,15 +39,6 @@ enum HidReportId { HID_INVALID_RPT_ID = 3; } -enum HidServiceType { - SERVICE_TYPE_HID = 0; - SERVICE_TYPE_HOGP = 1; - SERVICE_TYPE_BOTH = 2; -} - -message ServiceRequest { - HidServiceType service_type = 1; -} message SendHostReportRequest { bytes address = 1; HidReportType report_type = 2; diff --git a/pandora/server/bumble_experimental/hid.py b/pandora/server/bumble_experimental/hid.py index c209e933ee2..0b2f6867e26 100644 --- a/pandora/server/bumble_experimental/hid.py +++ b/pandora/server/bumble_experimental/hid.py @@ -18,8 +18,6 @@ from pandora_experimental.hid_pb2 import ( PROTOCOL_REPORT_MODE, PROTOCOL_BOOT_MODE, PROTOCOL_UNSUPPORTED_MODE, - SERVICE_TYPE_HID, - SERVICE_TYPE_HOGP, ) from bumble.core import ( @@ -704,45 +702,29 @@ def on_virtual_cable_unplug_cb(): hid_protoMode_queue = None -hid_device = None - - -def register_hid(self) -> None: - self.device.sdp_service_records.update(sdp_records()) - global hid_device - hid_device = HID_Device(self.device) - # Register for call backs - hid_device.register_get_report_cb(on_get_report_cb) - hid_device.register_set_report_cb(on_set_report_cb) - hid_device.register_get_protocol_cb(on_get_protocol_cb) - hid_device.register_set_protocol_cb(on_set_protocol_cb) - # Register for virtual cable unplug call back - hid_device.on('virtual_cable_unplug', on_virtual_cable_unplug_cb) # This class implements the Hid Pandora interface. class HIDService(HIDServicer): + hid_device = None + def __init__(self, device: Device) -> None: super().__init__() self.device = device + self.device.sdp_service_records.update(sdp_records()) self.event_queue: Optional[asyncio.Queue[ProtocolModeEvent]] = None - - @utils.rpc - async def RegisterService(self, request: empty_pb2.Empty, context: grpc.ServicerContext) -> empty_pb2.Empty: - - if request.service_type == SERVICE_TYPE_HID: - logging.info(f'Registering HID') - register_hid(self) - elif request.service_type == SERVICE_TYPE_HOGP: - logging.info(f'Registering HOGP') - hogp_device(self.device) - else: - logging.info(f'Registering both HID and HOGP') - register_hid(self) - hogp_device(self.device) - - return empty_pb2.Empty() + hogp_device(self.device) + logging.info(f'Hid device register: ') + global hid_device + hid_device = HID_Device(self.device) + # Register for call backs + hid_device.register_get_report_cb(on_get_report_cb) + hid_device.register_set_report_cb(on_set_report_cb) + hid_device.register_get_protocol_cb(on_get_protocol_cb) + hid_device.register_set_protocol_cb(on_set_protocol_cb) + # Register for virtual cable unplug call back + hid_device.on('virtual_cable_unplug', on_virtual_cable_unplug_cb) @utils.rpc async def ConnectHost(self, request: empty_pb2.Empty, context: grpc.ServicerContext) -> empty_pb2.Empty: -- GitLab From e07d0a228119096e625832eec5465d9a9920e4c7 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Tue, 1 Oct 2024 02:12:22 +0000 Subject: [PATCH 241/875] Test cases for removeBond() API Test: atest BumbleBluetoothTests:PairingTest Flag: TEST_ONLY Bug: 369242979 Change-Id: I018a62919e0b49447aad37b57235354f0bfb2d26 --- .../bluetooth/pairing/PairingTest.java | 274 ++++++++++++++++++ 1 file changed, 274 insertions(+) diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java index 7d5e3108a49..ba1a7284294 100644 --- a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java +++ b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java @@ -21,6 +21,7 @@ import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; @@ -28,9 +29,13 @@ import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothHidHost; import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.PandoraDevice; import android.bluetooth.StreamObserverSpliterator; @@ -41,6 +46,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.ParcelUuid; +import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.Log; @@ -48,6 +54,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 io.grpc.stub.StreamObserver; @@ -60,6 +67,7 @@ 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; @@ -112,8 +120,11 @@ public class PairingTest { private final StreamObserverSpliterator mPairingEventStreamObserver = new StreamObserverSpliterator<>(); @Mock private BroadcastReceiver mReceiver; + @Mock private BluetoothProfile.ServiceListener mProfileServiceListener; private InOrder mInOrder = null; private BluetoothDevice mBumbleDevice; + private BluetoothHidHost mHidService; + private BluetoothHeadset mHfpService; @Before public void setUp() throws Exception { @@ -143,6 +154,10 @@ public class PairingTest { mInOrder = inOrder(mReceiver); + // Get profile proxies + mHidService = (BluetoothHidHost) getProfileProxy(BluetoothProfile.HID_HOST); + mHfpService = (BluetoothHeadset) getProfileProxy(BluetoothProfile.HEADSET); + mBumbleDevice = mBumble.getRemoteDevice(); Set bondedDevices = sAdapter.getBondedDevices(); if (bondedDevices.contains(mBumbleDevice)) { @@ -534,6 +549,256 @@ public class PairingTest { unregisterIntentActions(BluetoothDevice.ACTION_ACL_CONNECTED); } + /** + * Test removeDevice API when connected over LE + * + *

    Prerequisites: + * + *

      + *
    1. Bumble and Android are not bonded + *
    + * + *

    Steps: + * + *

      + *
    1. Bumble is connectable over LE + *
    2. Android pairs with Bumble over LE + *
    3. Call BluetoothDevice.removeBond() API + *
    4. Android disconnects the ACL and removes the bond + *
    + * + *

    Expectation: Bumble is not bonded + */ + @Test + @RequiresFlagsEnabled({Flags.FLAG_WAIT_FOR_DISCONNECT_BEFORE_UNBOND}) + public void testRemoveBondLe_WhenConnected() { + registerIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, BluetoothDevice.ACTION_BOND_STATE_CHANGED); + + testStep_BondLe(); + assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice); + + assertThat(mBumbleDevice.removeBond()).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_DISCONNECTED), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); + + assertThat(sAdapter.getBondedDevices()).doesNotContain(mBumbleDevice); + + verifyNoMoreInteractions(mReceiver); + unregisterIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, BluetoothDevice.ACTION_BOND_STATE_CHANGED); + } + + /** + * Test removeDevice API when connected over BR/EDR + * + *

    Prerequisites: + * + *

      + *
    1. Bumble and Android are not bonded + *
    + * + *

    Steps: + * + *

      + *
    1. Bumble is connectable over BR/EDR + *
    2. Android pairs with Bumble over BR/EDR + *
    3. Call BluetoothDevice.removeBond() API + *
    4. Android disconnects the ACL and removes the bond + *
    + * + *

    Expectation: Bumble is not bonded + */ + @Test + @RequiresFlagsEnabled({Flags.FLAG_WAIT_FOR_DISCONNECT_BEFORE_UNBOND}) + public void testRemoveBondBredr_WhenConnected() { + registerIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, BluetoothDevice.ACTION_BOND_STATE_CHANGED); + + testStep_BondBredr(); + assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice); + + assertThat(mBumbleDevice.removeBond()).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_DISCONNECTED), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); + + assertThat(sAdapter.getBondedDevices()).doesNotContain(mBumbleDevice); + + verifyNoMoreInteractions(mReceiver); + unregisterIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, BluetoothDevice.ACTION_BOND_STATE_CHANGED); + } + + /** + * Test removeDevice API when not connected + * + *

    Prerequisites: + * + *

      + *
    1. Bumble and Android are not bonded + *
    2. Bumble supports HOGP + *
    + * + *

    Steps: + * + *

      + *
    1. Bumble is connectable over LE + *
    2. Android pairs with Bumble over LE + *
    3. Disconnect the Bumble + *
    4. Call BluetoothDevice.removeBond() API + *
    5. Removes the bond + *
    + * + *

    Expectation: Bumble is not bonded + */ + @Test + public void testRemoveBondLe_WhenDisconnected() { + registerIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); + + testStep_BondLe(); + assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice); + + // Wait for profiles to get connected + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothHidHost.EXTRA_STATE, BluetoothHidHost.STATE_CONNECTING)); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothHidHost.EXTRA_STATE, BluetoothHidHost.STATE_CONNECTED)); + + // Disconnect Bumble + assertThat(mBumbleDevice.disconnect()).isEqualTo(BluetoothStatusCodes.SUCCESS); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothHidHost.EXTRA_STATE, BluetoothHidHost.STATE_DISCONNECTING)); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothHidHost.EXTRA_STATE, BluetoothHidHost.STATE_DISCONNECTED)); + + // Wait for ACL to get disconnected + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_DISCONNECTED), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + + // Remove bond + assertThat(mBumbleDevice.removeBond()).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); + assertThat(sAdapter.getBondedDevices()).doesNotContain(mBumbleDevice); + + verifyNoMoreInteractions(mReceiver); + unregisterIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); + } + + /** + * Test removeDevice API when not connected + * + *

    Prerequisites: + * + *

      + *
    1. Bumble and Android are not bonded + *
    2. Bumble supports HID device role + *
    + * + *

    Steps: + * + *

      + *
    1. Bumble is connectable over BR/EDR + *
    2. Android pairs with Bumble over BR/EDR + *
    3. Disconnect the Bumble + *
    4. Call BluetoothDevice.removeBond() API + *
    5. Removes the bond + *
    + * + *

    Expectation: Bumble is not bonded + */ + @Test + public void testRemoveBondBredr_WhenDisconnected() { + registerIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + + // Disable all profiles other than A2DP as profile connections take too long + assertThat( + mHfpService.setConnectionPolicy( + mBumbleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) + .isTrue(); + assertThat( + mHidService.setConnectionPolicy( + mBumbleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) + .isTrue(); + + testStep_BondBredr(); + assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice); + + // Wait for profiles to get connected + verifyIntentReceived( + hasAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_CONNECTING), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + verifyIntentReceived( + hasAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_CONNECTED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + + // Disconnect all profiles + assertThat(mBumbleDevice.disconnect()).isEqualTo(BluetoothStatusCodes.SUCCESS); + verifyIntentReceived( + hasAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTING), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + verifyIntentReceived( + hasAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + + // Wait for the ACL to get disconnected + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_DISCONNECTED), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice)); + + // Remove bond + assertThat(mBumbleDevice.removeBond()).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); + assertThat(sAdapter.getBondedDevices()).doesNotContain(mBumbleDevice); + + verifyNoMoreInteractions(mReceiver); + unregisterIntentActions( + BluetoothDevice.ACTION_ACL_DISCONNECTED, + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + } + private void testStep_BondBredr() { registerIntentActions( BluetoothDevice.ACTION_BOND_STATE_CHANGED, @@ -791,4 +1056,13 @@ public class PairingTest { private int getTotalActionRegistrationCounts() { return mActionRegistrationCounts.values().stream().reduce(0, Integer::sum); } + + private BluetoothProfile getProfileProxy(int profile) { + sAdapter.getProfileProxy(sTargetContext, mProfileServiceListener, profile); + ArgumentCaptor proxyCaptor = + ArgumentCaptor.forClass(BluetoothProfile.class); + verify(mProfileServiceListener, timeout(BOND_INTENT_TIMEOUT.toMillis())) + .onServiceConnected(eq(profile), proxyCaptor.capture()); + return proxyCaptor.getValue(); + } } -- GitLab From 039d579a5010b5534cab049df7f040f0ec54d2fa Mon Sep 17 00:00:00 2001 From: Sarvesh Kalwit Date: Fri, 27 Sep 2024 17:59:35 +0000 Subject: [PATCH 242/875] Add MSFT extension support to JNI layer Bug: 360384904 Bug: 365787977 Test: m -j Flag: le_scan_msft_support Change-Id: I4f010d82d2187cd993d621ce14af49c09a281bcd --- .../app/jni/com_android_bluetooth_gatt.cpp | 152 ++++++++++++++++++ .../bluetooth/le_scan/MsftAdvMonitor.java | 38 +++++ .../le_scan/ScanNativeInterface.java | 19 +++ system/main/shim/le_scanning_manager.cc | 6 +- 4 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index e164923de84..5b4ade37550 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -180,6 +180,9 @@ static jmethodID method_onBatchScanThresholdCrossed; static jmethodID method_createOnTrackAdvFoundLostObject; static jmethodID method_onTrackAdvFoundLost; static jmethodID method_onScanParamSetupCompleted; +static jmethodID method_onMsftAdvMonitorAdd; +static jmethodID method_onMsftAdvMonitorRemove; +static jmethodID method_onMsftAdvMonitorEnable; /** * Periodic scanner callback methods @@ -1875,6 +1878,142 @@ static void gattClientScanFilterEnableNative(JNIEnv* /* env */, jobject /* objec sScanner->ScanFilterEnable(enable, base::Bind(&scan_enable_cb, client_if)); } +void msft_monitor_add_cb(int filter_index, uint8_t monitor_handle, uint8_t status) { + std::shared_lock lock(callbacks_mutex); + CallbackEnv sCallbackEnv(__func__); + if (!sCallbackEnv.valid() || !mScanCallbacksObj) { + return; + } + sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onMsftAdvMonitorAdd, filter_index, + monitor_handle, status); +} + +void msft_monitor_remove_cb(int filter_index, uint8_t status) { + std::shared_lock lock(callbacks_mutex); + CallbackEnv sCallbackEnv(__func__); + if (!sCallbackEnv.valid() || !mScanCallbacksObj) { + return; + } + sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onMsftAdvMonitorRemove, filter_index, + status); +} + +void msft_monitor_enable_cb(uint8_t status) { + std::shared_lock lock(callbacks_mutex); + CallbackEnv sCallbackEnv(__func__); + if (!sCallbackEnv.valid() || !mScanCallbacksObj) { + return; + } + sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onMsftAdvMonitorEnable, status); +} + +static bool gattClientIsMsftSupportedNative(JNIEnv* /* env */, jobject /* object */) { + return sScanner && sScanner->IsMsftSupported(); +} + +static void gattClientMsftAdvMonitorAddNative(JNIEnv* env, jobject /* object*/, + jobject msft_adv_monitor, + jobjectArray msft_adv_monitor_patterns, + jobject msft_adv_monitor_address, jint filter_index) { + if (!sScanner) { + return; + } + + jclass msftAdvMonitorClazz = env->GetObjectClass(msft_adv_monitor); + jfieldID rssiThresholdHighFid = env->GetFieldID(msftAdvMonitorClazz, "rssi_threshold_high", "B"); + jfieldID rssiThresholdLowFid = env->GetFieldID(msftAdvMonitorClazz, "rssi_threshold_low", "B"); + jfieldID rssiThresholdLowTimeIntervalFid = + env->GetFieldID(msftAdvMonitorClazz, "rssi_threshold_low_time_interval", "B"); + jfieldID rssiSamplingPeriodFid = + env->GetFieldID(msftAdvMonitorClazz, "rssi_sampling_period", "B"); + jfieldID conditionTypeFid = env->GetFieldID(msftAdvMonitorClazz, "condition_type", "B"); + + jclass msftAdvMonitorAddressClazz = env->GetObjectClass(msft_adv_monitor_address); + jfieldID addrTypeFid = env->GetFieldID(msftAdvMonitorAddressClazz, "addr_type", "B"); + jfieldID bdAddrFid = env->GetFieldID(msftAdvMonitorAddressClazz, "bd_addr", "Ljava/lang/String;"); + + MsftAdvMonitor native_msft_adv_monitor{}; + ScopedLocalRef msft_adv_monitor_object(env, msft_adv_monitor); + native_msft_adv_monitor.rssi_threshold_high = + env->GetByteField(msft_adv_monitor_object.get(), rssiThresholdHighFid); + native_msft_adv_monitor.rssi_threshold_low = + env->GetByteField(msft_adv_monitor_object.get(), rssiThresholdLowFid); + native_msft_adv_monitor.rssi_threshold_low_time_interval = + env->GetByteField(msft_adv_monitor_object.get(), rssiThresholdLowTimeIntervalFid); + native_msft_adv_monitor.rssi_sampling_period = + env->GetByteField(msft_adv_monitor_object.get(), rssiSamplingPeriodFid); + native_msft_adv_monitor.condition_type = + env->GetByteField(msft_adv_monitor_object.get(), conditionTypeFid); + + MsftAdvMonitorAddress native_msft_adv_monitor_address{}; + ScopedLocalRef msft_adv_monitor_address_object(env, msftAdvMonitorAddressClazz); + native_msft_adv_monitor_address.addr_type = + env->GetByteField(msft_adv_monitor_address_object.get(), addrTypeFid); + native_msft_adv_monitor_address.bd_addr = str2addr( + env, (jstring)env->GetObjectField(msft_adv_monitor_address_object.get(), bdAddrFid)); + native_msft_adv_monitor.addr_info = native_msft_adv_monitor_address; + + int numPatterns = env->GetArrayLength(msft_adv_monitor_patterns); + if (numPatterns == 0) { + sScanner->MsftAdvMonitorAdd(std::move(native_msft_adv_monitor), + base::Bind(&msft_monitor_add_cb, filter_index)); + return; + } + + jclass msftAdvMonitorPatternClazz = + env->GetObjectClass(env->GetObjectArrayElement(msft_adv_monitor_patterns, 0)); + jfieldID adTypeFid = env->GetFieldID(msftAdvMonitorPatternClazz, "ad_type", "B"); + jfieldID startByteFid = env->GetFieldID(msftAdvMonitorPatternClazz, "start_byte", "B"); + jfieldID patternFid = env->GetFieldID(msftAdvMonitorPatternClazz, "pattern", "[B"); + + std::vector patterns; + for (int i = 0; i < numPatterns; i++) { + MsftAdvMonitorPattern native_msft_adv_monitor_pattern{}; + ScopedLocalRef msft_adv_monitor_pattern_object( + env, env->GetObjectArrayElement(msft_adv_monitor_patterns, i)); + native_msft_adv_monitor_pattern.ad_type = + env->GetByteField(msft_adv_monitor_pattern_object.get(), adTypeFid); + native_msft_adv_monitor_pattern.start_byte = + env->GetByteField(msft_adv_monitor_pattern_object.get(), startByteFid); + + ScopedLocalRef patternByteArray( + env, + (jbyteArray)env->GetObjectField(msft_adv_monitor_pattern_object.get(), patternFid)); + if (patternByteArray.get() != nullptr) { + jbyte* patternBytes = env->GetByteArrayElements(patternByteArray.get(), NULL); + if (patternBytes == NULL) { + jniThrowIOException(env, EINVAL); + return; + } + for (int j = 0; j < env->GetArrayLength(patternByteArray.get()); j++) { + native_msft_adv_monitor_pattern.pattern.push_back(patternBytes[j]); + } + } + + patterns.push_back(native_msft_adv_monitor_pattern); + } + native_msft_adv_monitor.patterns = patterns; + + sScanner->MsftAdvMonitorAdd(std::move(native_msft_adv_monitor), + base::Bind(&msft_monitor_add_cb, filter_index)); +} + +static void gattClientMsftAdvMonitorRemoveNative(JNIEnv* /* env */, jobject /* object */, + int filter_index, int monitor_handle) { + if (!sScanner) { + return; + } + sScanner->MsftAdvMonitorRemove(monitor_handle, base::Bind(&msft_monitor_remove_cb, filter_index)); +} + +static void gattClientMsftAdvMonitorEnableNative(JNIEnv* /* env */, jobject /* object */, + jboolean enable) { + if (!sScanner) { + return; + } + sScanner->MsftAdvMonitorEnable(enable, base::Bind(&msft_monitor_enable_cb)); +} + static void gattClientConfigureMTUNative(JNIEnv* /* env */, jobject /* object */, jint conn_id, jint mtu) { if (!sGattIf) { @@ -2697,6 +2836,16 @@ static int register_com_android_bluetooth_gatt_scan(JNIEnv* env) { {"gattClientScanFilterClearNative", "(II)V", (void*)gattClientScanFilterClearNative}, {"gattClientScanFilterEnableNative", "(IZ)V", (void*)gattClientScanFilterEnableNative}, {"gattSetScanParametersNative", "(IIII)V", (void*)gattSetScanParametersNative}, + // MSFT HCI Extension functions. + {"gattClientIsMsftSupportedNative", "()Z", (void*)gattClientIsMsftSupportedNative}, + {"gattClientMsftAdvMonitorAddNative", + "(Lcom/android/bluetooth/le_scan/MsftAdvMonitor$Monitor;[Lcom/android/bluetooth/le_scan/" + "MsftAdvMonitor$Pattern;Lcom/android/bluetooth/le_scan/MsftAdvMonitor$Address;I)V", + (void*)gattClientMsftAdvMonitorAddNative}, + {"gattClientMsftAdvMonitorRemoveNative", "(II)V", + (void*)gattClientMsftAdvMonitorRemoveNative}, + {"gattClientMsftAdvMonitorEnableNative", "(Z)V", + (void*)gattClientMsftAdvMonitorEnableNative}, }; const int result = REGISTER_NATIVE_METHODS( env, "com/android/bluetooth/le_scan/ScanNativeInterface", methods); @@ -2723,6 +2872,9 @@ static int register_com_android_bluetooth_gatt_scan(JNIEnv* env) { {"onTrackAdvFoundLost", "(Lcom/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfo;)V", &method_onTrackAdvFoundLost}, {"onScanParamSetupCompleted", "(II)V", &method_onScanParamSetupCompleted}, + {"onMsftAdvMonitorAdd", "(III)V", &method_onMsftAdvMonitorAdd}, + {"onMsftAdvMonitorRemove", "(II)V", &method_onMsftAdvMonitorRemove}, + {"onMsftAdvMonitorEnable", "(I)V", &method_onMsftAdvMonitorEnable}, }; GET_JAVA_METHODS(env, "com/android/bluetooth/le_scan/ScanNativeInterface", javaMethods); return 0; diff --git a/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java b/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java new file mode 100644 index 00000000000..8d67f2a8348 --- /dev/null +++ b/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 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. + */ + +package com.android.bluetooth.le_scan; + +class MsftAdvMonitor { + static class Monitor { + public byte rssi_threshold_high; + public byte rssi_threshold_low; + public byte rssi_threshold_low_time_interval; + public byte rssi_sampling_period; + public byte condition_type; + } + + static class Pattern { + public byte ad_type; + public byte start_byte; + public byte[] pattern; + } + + static class Address { + byte addr_type; + String bd_addr; + } +} diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java index 35ea6775b20..c2581a5cbea 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java @@ -98,6 +98,19 @@ public class ScanNativeInterface { private native void gattClientScanFilterEnableNative(int clientIf, boolean enable); + /************************** MSFT scan related native methods *****************************/ + private native boolean gattClientIsMsftSupportedNative(); + + private native void gattClientMsftAdvMonitorAddNative( + MsftAdvMonitor.Monitor msft_adv_monitor, + MsftAdvMonitor.Pattern[] msft_adv_monitor_patterns, + MsftAdvMonitor.Address msft_adv_monitor_address, + int filter_index); + + private native void gattClientMsftAdvMonitorRemoveNative(int filter_index, int monitor_handle); + + private native void gattClientMsftAdvMonitorEnableNative(boolean enable); + /************************** Batch related native methods *********************************/ private native void gattClientConfigBatchScanStorageNative( int clientIf, @@ -371,4 +384,10 @@ public class ScanNativeInterface { } mScanHelper.onScanParamSetupCompleted(status, scannerId); } + + void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) {} + + void onMsftAdvMonitorRemove(int filter_index, int status) {} + + void onMsftAdvMonitorEnable(int status) {} } diff --git a/system/main/shim/le_scanning_manager.cc b/system/main/shim/le_scanning_manager.cc index beaa585d16f..3f5f4ad07ad 100644 --- a/system/main/shim/le_scanning_manager.cc +++ b/system/main/shim/le_scanning_manager.cc @@ -287,13 +287,13 @@ void BleScannerInterfaceImpl::MsftAdvMonitorEnable(bool enable, MsftAdvMonitorEn void BleScannerInterfaceImpl::OnMsftAdvMonitorAdd(uint8_t monitor_handle, bluetooth::hci::ErrorCode status) { log::info("in shim layer"); - msft_callbacks_.Add.Run(monitor_handle, (uint8_t)status); + do_in_jni_thread(base::BindOnce(msft_callbacks_.Add, monitor_handle, (uint8_t)status)); } /** Callback of removing MSFT filter */ void BleScannerInterfaceImpl::OnMsftAdvMonitorRemove(bluetooth::hci::ErrorCode status) { log::info("in shim layer"); - msft_callbacks_.Remove.Run((uint8_t)status); + do_in_jni_thread(base::BindOnce(msft_callbacks_.Remove, (uint8_t)status)); } /** Callback of enabling / disabling MSFT scan filter */ @@ -307,7 +307,7 @@ void BleScannerInterfaceImpl::OnMsftAdvMonitorEnable(bool enable, : bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL); } - msft_callbacks_.Enable.Run((uint8_t)status); + do_in_jni_thread(base::BindOnce(msft_callbacks_.Enable, (uint8_t)status)); } /** Sets the LE scan interval and window in units of N*0.625 msec */ -- GitLab From cf9db393268b6c4399dc3468e16caba3f30a10ba Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 9 Oct 2024 15:09:59 -0700 Subject: [PATCH 243/875] SystemServer: add logging on some binder call It would be interesting to know when the binder call is received compare to when the binder call is processed by the correct thread Bug: 361512704 Test: atest ServiceBluetoothTests Flag: Exempt logging Change-Id: I69f519a6e602cf87c35c5d40f30b02e3dddbd6a5 --- .../com/android/server/bluetooth/BluetoothServiceBinder.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java b/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java index be730c37cfb..95b4b0c1a4a 100644 --- a/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java +++ b/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java @@ -115,6 +115,7 @@ class BluetoothServiceBinder extends IBluetoothManager.Stub { return false; } + Log.d(TAG, "enable()"); return mBluetoothManagerService.enableFromBinder(source.getPackageName()); } @@ -140,6 +141,7 @@ class BluetoothServiceBinder extends IBluetoothManager.Stub { throw new SecurityException("No permission to enable Bluetooth quietly"); } + Log.d(TAG, "enableNoAutoConnect()"); return mBluetoothManagerService.enableNoAutoConnectFromBinder(source.getPackageName()); } @@ -165,6 +167,7 @@ class BluetoothServiceBinder extends IBluetoothManager.Stub { return false; } + Log.d(TAG, "disable(" + persist + ")"); return mBluetoothManagerService.disableFromBinder(source.getPackageName(), persist); } @@ -265,6 +268,7 @@ class BluetoothServiceBinder extends IBluetoothManager.Stub { return false; } + Log.d(TAG, "enableBle(" + token + ")"); return mBluetoothManagerService.enableBleFromBinder(source.getPackageName(), token); } @@ -288,6 +292,7 @@ class BluetoothServiceBinder extends IBluetoothManager.Stub { return false; } + Log.d(TAG, "disableBle(" + token + ")"); return mBluetoothManagerService.disableBleFromBinder(source.getPackageName(), token); } -- GitLab From 90e0648e633ec3483903a0399510ed1ba2409bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Y=C4=B1lmaz?= Date: Thu, 10 Oct 2024 00:48:12 +0000 Subject: [PATCH 244/875] Fix javadoc reference to BluetoothDevice#getAddressType() constants. Bug: 366988067 Change-Id: I83fdc45cec4e9b08de11492e673b57d760626622 Flag: Exempt, javadoc Test: m com.android.btservices --- framework/java/android/bluetooth/BluetoothDevice.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 23b85060dcc..4da94af0d80 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -1546,8 +1546,8 @@ public final class BluetoothDevice implements Parcelable, Attributable { } /** - * Returns the address type of this BluetoothDevice, one of {@link ADDRESS_TYPE_PUBLIC}, {@link - * ADDRESS_TYPE_RANDOM}, {@link ADDRESS_TYPE_ANONYMOUS}, or {@link ADDRESS_TYPE_UNKNOWN}. + * Returns the address type of this BluetoothDevice, one of {@link #ADDRESS_TYPE_PUBLIC}, {@link + * #ADDRESS_TYPE_RANDOM}, {@link #ADDRESS_TYPE_ANONYMOUS}, or {@link #ADDRESS_TYPE_UNKNOWN}. * * @return Bluetooth address type */ -- GitLab From d657641b85963ea96158e3b9bf9e34b344d5eb53 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 20 Sep 2024 00:07:15 +0000 Subject: [PATCH 245/875] Save user ID in restricted mode Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.guest_mode_bond Bug: 346337854 Bug: 349882273 Change-Id: Ibc502eec3f7e811018f2a427005fa9453ca79e2e --- system/btif/Android.bp | 1 + system/btif/src/btif_storage.cc | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 7eb29525247..9b22ee4784e 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -245,6 +245,7 @@ cc_library_static { ], shared_libs: [ "libcrypto", + "libcutils", ], cflags: [ /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc index 1c30c76d49a..8b969465042 100644 --- a/system/btif/src/btif_storage.cc +++ b/system/btif/src/btif_storage.cc @@ -29,14 +29,18 @@ */ #define LOG_TAG "bt_btif_storage" - #include "btif/include/btif_storage.h" #include #include +#include +#ifndef TARGET_FLOSS +#include +#endif #include #include #include +#include #include #include @@ -60,6 +64,9 @@ /* This is a local property to add a device found */ #define BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP 0xFF +// Default user ID to use when real user ID is not available +#define BTIF_STORAGE_RESTRICTED_USER_ID_DEFAULT 1 + // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" @@ -107,11 +114,24 @@ static bool btif_has_ble_keys(const std::string& bdstr); * Static functions ******************************************************************************/ +static int btif_storage_get_user_id() { + if (!com::android::bluetooth::flags::guest_mode_bond()) { + return BTIF_STORAGE_RESTRICTED_USER_ID_DEFAULT; + } +#ifdef TARGET_FLOSS + return BTIF_STORAGE_RESTRICTED_USER_ID_DEFAULT; +#else + return multiuser_get_user_id(getuid()); +#endif +} + static void btif_storage_set_mode(RawAddress* remote_bd_addr) { std::string bdstr = remote_bd_addr->ToString(); if (GetInterfaceToProfiles()->config->isRestrictedMode()) { - log::info("{} will be removed exiting restricted mode", *remote_bd_addr); - btif_config_set_int(bdstr, BTIF_STORAGE_KEY_RESTRICTED, 1); + int user_id = btif_storage_get_user_id(); + log::info("{} added by user {}, will be removed on exiting restricted mode", *remote_bd_addr, + user_id); + btif_config_set_int(bdstr, BTIF_STORAGE_KEY_RESTRICTED, user_id); } } -- GitLab From 026ff5a8f246270bdbb156503d79499fbf04a505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 23 Sep 2024 07:30:58 +0000 Subject: [PATCH 246/875] ActiveDeviceManager: stop audio when switched between ASHA and LE Audio Depending if fallback device is already available or not, audio playback was continued or not. This is unconsistent behavior for scenario when same device is switching from ASHA to LE Audio profile. Now, check if fallback device exists, and if it does, if the profile is different. If the type changes, stop audio. Bug: 368221990 Bug: 369799111: Test: atest ActiveDeviceManagerTest Flag: com.android.bluetooth.flags.adm_verify_active_fallback_device Change-Id: I290a795db89aa75fcffa5518f16acbe5712ecf1c --- .../btservice/ActiveDeviceManager.java | 40 +++++++---- .../btservice/ActiveDeviceManagerTest.java | 66 +++++++++++++++++++ 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java index 9286194a540..9b926f13069 100644 --- a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +++ b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java @@ -408,9 +408,15 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac } // New connected device: select it as active if (setHearingAidActiveDevice(device)) { + final LeAudioService leAudioService = mFactory.getLeAudioService(); setA2dpActiveDevice(null, true); setHfpActiveDevice(null); - setLeAudioActiveDevice(null, true); + if (Flags.admVerifyActiveFallbackDevice()) { + setLeAudioActiveDevice( + null, !leAudioService.getActiveDevices().contains(device)); + } else { + setLeAudioActiveDevice(null, true); + } } } } @@ -504,7 +510,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac + mA2dpActiveDevice); mA2dpConnectedDevices.remove(device); if (Objects.equals(mA2dpActiveDevice, device)) { - if (!setFallbackDeviceActiveLocked()) { + if (!setFallbackDeviceActiveLocked(device)) { setA2dpActiveDevice(null, false); } } @@ -521,7 +527,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac if (mHfpConnectedDevices.isEmpty()) { setHfpActiveDevice(null); } - setFallbackDeviceActiveLocked(); + setFallbackDeviceActiveLocked(device); } } } @@ -536,7 +542,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac + mHearingAidActiveDevices); mHearingAidConnectedDevices.remove(device); if (mHearingAidActiveDevices.remove(device) && mHearingAidActiveDevices.isEmpty()) { - if (!setFallbackDeviceActiveLocked()) { + if (!setFallbackDeviceActiveLocked(device)) { setHearingAidActiveDevice(null, false); } } @@ -562,7 +568,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac boolean hasFallbackDevice = false; if (Objects.equals(mLeAudioActiveDevice, device)) { - hasFallbackDevice = setFallbackDeviceActiveLocked(); + hasFallbackDevice = setFallbackDeviceActiveLocked(device); if (!hasFallbackDevice) { setLeAudioActiveDevice(null, false); } @@ -816,7 +822,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac return; } synchronized (mLock) { - setFallbackDeviceActiveLocked(); + setFallbackDeviceActiveLocked(null); } } } @@ -1043,7 +1049,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac * @return true when the fallback device is activated, false otherwise */ @GuardedBy("mLock") - private boolean setFallbackDeviceActiveLocked() { + private boolean setFallbackDeviceActiveLocked(BluetoothDevice recentlyRemovedDevice) { Log.d(TAG, "setFallbackDeviceActive"); mDbManager = mAdapterService.getDatabase(); List connectedHearingAidDevices = new ArrayList<>(); @@ -1057,17 +1063,29 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac BluetoothDevice device = mDbManager.getMostRecentlyConnectedDevicesInList(connectedHearingAidDevices); if (device != null) { + /* Check if fallback device shall be used. It should be used when a new + * device is connected. If the most recently connected device is the same as + * recently removed device, it means it just switched profile it is using and is + * not new one. + */ + boolean hasFallbackDevice = true; + if (Flags.admVerifyActiveFallbackDevice()) { + hasFallbackDevice = + !(recentlyRemovedDevice != null + && device.equals(recentlyRemovedDevice) + && connectedHearingAidDevices.size() == 1); + } if (mHearingAidConnectedDevices.contains(device)) { Log.d(TAG, "Found a hearing aid fallback device: " + device); setHearingAidActiveDevice(device); - setA2dpActiveDevice(null, true); + setA2dpActiveDevice(null, hasFallbackDevice); setHfpActiveDevice(null); - setLeAudioActiveDevice(null, true); + setLeAudioActiveDevice(null, hasFallbackDevice); } else { Log.d(TAG, "Found a LE hearing aid fallback device: " + device); setLeHearingAidActiveDevice(device); - setHearingAidActiveDevice(null, true); - setA2dpActiveDevice(null, true); + setHearingAidActiveDevice(null, hasFallbackDevice); + setA2dpActiveDevice(null, hasFallbackDevice); setHfpActiveDevice(null); } return true; diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index 3a508fdce8b..b50835e74aa 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -1055,6 +1055,72 @@ public class ActiveDeviceManagerTest { verify(mA2dpService).setActiveDevice(mA2dpDevice); } + /** + * An ASHA device connected and set to active. Same device connected as a LE Audio device. ASHA + * disconnects with no fallback and LE Audio is set to active. New LE Audio device is connected + * and selected as active. First LE Audio device disconnects with fallback to new one. + */ + @Test + @EnableFlags(Flags.FLAG_ADM_VERIFY_ACTIVE_FALLBACK_DEVICE) + public void sameDeviceAsAshaAndLeAudio_noFallbackOnSwitch() { + when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); + + /* Connect first device as ASHA */ + hearingAidConnected(mHearingAidDevice); + mTestLooper.dispatchAll(); + verify(mHearingAidService).setActiveDevice(mHearingAidDevice); + + /* Connect first device as LE Audio */ + leAudioConnected(mHearingAidDevice); + hearingAidDisconnected(mHearingAidDevice); + mTestLooper.dispatchAll(); + verify(mHearingAidService).removeActiveDevice(false); + verify(mLeAudioService).setActiveDevice(mHearingAidDevice); + + /* Connect second device as LE Audio. First device is disconnected with fallback to + * new one. + */ + leAudioConnected(mLeAudioDevice); + leAudioDisconnected(mHearingAidDevice); + mTestLooper.dispatchAll(); + verify(mLeAudioService).removeActiveDevice(true); + verify(mLeAudioService).setActiveDevice(mLeAudioDevice); + } + + /** + * A LE Audio device connected and set to active. Same device connected as an ASHA device. LE + * Audio disconnects with no fallback and ASHA is set to active. New ASHA device is connected + * and selected as active. First ASHA device disconnects with fallback to new one. + */ + @Test + @EnableFlags(Flags.FLAG_ADM_VERIFY_ACTIVE_FALLBACK_DEVICE) + public void sameDeviceAsLeAudioAndAsha_noFallbackOnSwitch() { + // Turn on the dual mode audio flag so the A2DP won't disconnect LE Audio + when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); + List list = new ArrayList<>(); + when(mLeAudioService.getActiveDevices()).thenReturn(list); + + /* Connect first device as LE Audio */ + leAudioConnected(mHearingAidDevice); + list.add(mHearingAidDevice); + mTestLooper.dispatchAll(); + verify(mLeAudioService).setActiveDevice(mHearingAidDevice); + + /* Connect first device as ASHA */ + hearingAidConnected(mHearingAidDevice); + leAudioDisconnected(mHearingAidDevice); + mTestLooper.dispatchAll(); + verify(mHearingAidService).setActiveDevice(mHearingAidDevice); + verify(mLeAudioService).removeActiveDevice(false); + + /* Connect second device as ASHA. It is set as fallback device for LE Audio Service + */ + hearingAidConnected(mSecondaryAudioDevice); + mTestLooper.dispatchAll(); + verify(mLeAudioService).removeActiveDevice(true); + verify(mHearingAidService).setActiveDevice(mSecondaryAudioDevice); + } + /** * Two Hearing Aid are connected and the current active is then disconnected. Should then set * active device to fallback device. -- GitLab From 91b06909b3d7a3e4452cc7d02a8ffbb92e77e273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 20 Aug 2024 08:32:14 +0000 Subject: [PATCH 247/875] has_client.cc: Connect shall connect only requested device `Connect` method should only connect single device, defined by `address` parameter. Otherwise, fail on connection of other device in group will lead to disconnection of already connected ones. Allow Java layer to handle connecting all group members, as other profiles do. Bug: 361014973 Flag: com.android.bluetooth.flags.hap_connect_only_requested_device Test: atest --host --no-bazel-mode bluetooth_has_test Change-Id: I26ebab5c6105c803865bdce49e008e9c997f3537 --- system/bta/Android.bp | 2 ++ system/bta/has/has_client.cc | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 271b008ca0f..54fe2cb79b5 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -1238,6 +1238,7 @@ cc_test { "liblog", ], static_libs: [ + "bluetooth_flags_c_lib_for_test", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", @@ -1245,6 +1246,7 @@ cc_test { "libbt-common", "libchrome", "libgmock", + "server_configurable_flags", ], sanitize: { cfi: true, diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 03f75a72e95..034bbf43e57 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -153,6 +154,22 @@ public: return; } + if (com::android::bluetooth::flags::hap_connect_only_requested_device()) { + auto device = + std::find_if(devices_.begin(), devices_.end(), HasDevice::MatchAddress(address)); + if (device == devices_.end()) { + devices_.emplace_back(address, true); + BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false); + + } else { + device->is_connecting_actively = true; + if (!device->IsConnected()) { + BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false); + } + } + return; + } + std::vector addresses = {address}; auto csis_api = CsisClient::Get(); if (csis_api != nullptr) { @@ -202,6 +219,24 @@ public: void Disconnect(const RawAddress& address) override { log::debug("{}", address); + if (com::android::bluetooth::flags::hap_connect_only_requested_device()) { + auto device = + std::find_if(devices_.begin(), devices_.end(), HasDevice::MatchAddress(address)); + auto conn_id = device->conn_id; + auto is_connecting_actively = device->is_connecting_actively; + if (conn_id != GATT_INVALID_CONN_ID) { + BTA_GATTC_Close(conn_id); + callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address); + } else { + /* Removes active connection. */ + if (is_connecting_actively) { + BTA_GATTC_CancelOpen(gatt_if_, address, true); + callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address); + } + } + return; + } + std::vector addresses = {address}; auto csis_api = CsisClient::Get(); if (csis_api != nullptr) { -- GitLab From f9b122eef37632c3e90e3710cc91012507bde134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Thu, 10 Oct 2024 07:51:05 +0000 Subject: [PATCH 248/875] flags: Add l2cap_fcs_option_fix Bug: 372605959 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: I74068d263fe5bbc50f6ffffe0ff8d7c53058f117 --- flags/l2cap.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/l2cap.aconfig b/flags/l2cap.aconfig index 9327e019da2..fb53c10bef0 100644 --- a/flags/l2cap.aconfig +++ b/flags/l2cap.aconfig @@ -34,3 +34,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "l2cap_fcs_option_fix" + namespace: "bluetooth" + description: "Use fcs_option for non BASIC mode " + bug: "372605959" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 06ef2a7a7fa905af24a90170e881915b1bdc7894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 1 Oct 2024 12:46:13 +0000 Subject: [PATCH 249/875] LeAudioService: Add groupId to the LeAudioGroupDescriptor This is just for the loging purposes. Bug: 369599302 Test: atest LeAudioServiceTest Flag: Exempt, no functional change Change-Id: I127cc89a0295b4c4054b0c9c646cf5edd28fafec --- .../bluetooth/le_audio/LeAudioService.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) 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 a6cd25b3959..ed74f24d3a2 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -237,7 +237,8 @@ public class LeAudioService extends ProfileService { } private static class LeAudioGroupDescriptor { - LeAudioGroupDescriptor(boolean isInbandRingtonEnabled) { + LeAudioGroupDescriptor(int groupId, boolean isInbandRingtonEnabled) { + mGroupId = groupId; mIsConnected = false; mActiveState = ACTIVE_STATE_INACTIVE; mAllowedSinkContexts = BluetoothLeAudio.CONTEXTS_ALL; @@ -254,6 +255,7 @@ public class LeAudioService extends ProfileService { mInactivatedDueToContextType = false; } + Integer mGroupId; Boolean mIsConnected; Boolean mHasFallbackDeviceWhenGettingInactive; Integer mDirection; @@ -287,11 +289,17 @@ public class LeAudioService extends ProfileService { if ((state != ACTIVE_STATE_ACTIVE) && (state != ACTIVE_STATE_INACTIVE) && (state != ACTIVE_STATE_GETTING_ACTIVE)) { - Log.e(TAG, "LeAudioGroupDescriptor.setActiveState: Invalid state set: " + state); + Log.e( + TAG, + ("LeAudioGroupDescriptor.setActiveState (groupId: " + mGroupId + "):") + + ("Invalid state set: " + state)); return; } - Log.d(TAG, "LeAudioGroupDescriptor.setActiveState: " + mActiveState + " -> " + state); + Log.d( + TAG, + ("LeAudioGroupDescriptor.setActiveState (groupId: " + mGroupId + "): ") + + (mActiveState + " -> " + state)); mActiveState = state; } @@ -311,7 +319,9 @@ public class LeAudioService extends ProfileService { void updateAllowedContexts(Integer allowedSinkContexts, Integer allowedSourceContexts) { Log.d( TAG, - "LeAudioGroupDescriptor.mAllowedSinkContexts: " + "LeAudioGroupDescriptor.mAllowedSinkContexts (groupId: " + + mGroupId + + "): " + mAllowedSinkContexts + " -> " + allowedSinkContexts @@ -4733,7 +4743,7 @@ public class LeAudioService extends ProfileService { LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { - mGroupDescriptors.put(groupId, new LeAudioGroupDescriptor(false)); + mGroupDescriptors.put(groupId, new LeAudioGroupDescriptor(groupId, false)); } groupDescriptor = getGroupDescriptor(groupId); if (groupDescriptor == null) { -- GitLab From 60877998a452b86be73ed5d44c19aad4760ce196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Mon, 30 Sep 2024 12:01:14 +0000 Subject: [PATCH 250/875] codec_manager: Feed offloader with Mono configuration Bug: 330847930 Bug: 331139722 Test: atest bluetooth_le_audio_codec_manager_test Flag: com::android::bluetooth:flags::leaudio_mono_location_errata Change-Id: I9dbcd92c0fbbe54bb39cfb930f65e069212598f3 --- system/bta/Android.bp | 2 +- system/bta/le_audio/codec_manager.cc | 72 ++++++++++-- system/bta/le_audio/codec_manager.h | 2 +- system/bta/le_audio/codec_manager_test.cc | 137 ++++++++++++++++++++++ system/bta/le_audio/mock_codec_manager.cc | 3 +- system/bta/le_audio/mock_codec_manager.h | 2 +- 6 files changed, 206 insertions(+), 12 deletions(-) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 271b008ca0f..f0b8f96b35d 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -807,7 +807,7 @@ cc_test { "liblog", // __android_log_print ], static_libs: [ - "bluetooth_flags_c_lib", + "bluetooth_flags_c_lib_for_test", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index d59ed996e4d..fce821417d1 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -168,9 +168,12 @@ public: bluetooth::le_audio::types::kLeAudioDirectionSource}) { auto& stream_map = offloader_stream_maps.get(direction); if (!stream_map.has_changed && !stream_map.is_initial) { + log::warn("unexpected call for direction {}, stream_map.has_changed {}", direction, + stream_map.has_changed, stream_map.is_initial); continue; } if (stream_params.get(direction).stream_locations.empty()) { + log::warn("unexpected call, stream is empty for direction {}, ", direction); continue; } @@ -675,7 +678,7 @@ public: stream_map.streams_map_current.clear(); } - static uint32_t AdjustAllocationForOffloader(uint32_t allocation) { + static int AdjustAllocationForOffloader(uint32_t allocation) { if ((allocation & codec_spec_conf::kLeAudioLocationAnyLeft) && (allocation & codec_spec_conf::kLeAudioLocationAnyRight)) { return codec_spec_conf::kLeAudioLocationStereo; @@ -686,20 +689,70 @@ public: if (allocation & codec_spec_conf::kLeAudioLocationAnyRight) { return codec_spec_conf::kLeAudioLocationFrontRight; } - return 0; + + if (allocation == codec_spec_conf::kLeAudioLocationMonoAudio) { + return codec_spec_conf::kLeAudioLocationMonoAudio; + } + + return -1; + } + + bool UpdateCisMonoConfiguration(const std::vector& cises, uint8_t direction) { + if (!LeAudioHalVerifier::SupportsStreamActiveApi() || + !com::android::bluetooth::flags::leaudio_mono_location_errata()) { + log::error( + "SupportsStreamActiveApi() not supported or leaudio_mono_location_errata flag is not " + "enabled. Mono stream cannot be enabled"); + return false; + } + + auto& stream_map = offloader_stream_maps.get(direction); + + stream_map.has_changed = true; + stream_map.streams_map_target.clear(); + stream_map.streams_map_current.clear(); + + const std::string tag = + types::BidirectionalPair({.sink = "Sink", .source = "Source"}) + .get(direction); + + constexpr types::BidirectionalPair cis_types = { + .sink = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SINK, + .source = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE}; + auto cis_type = cis_types.get(direction); + + for (auto const& cis_entry : cises) { + if ((cis_entry.type == types::CisType::CIS_TYPE_BIDIRECTIONAL || + cis_entry.type == cis_type) && + cis_entry.conn_handle != 0) { + bool is_active = cis_entry.addr != RawAddress::kEmpty; + log::info("{}: {}, Cis handle {:#x}, allocation {:#x}, active: {}", tag, cis_entry.addr, + cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active); + stream_map.streams_map_target.emplace_back(stream_map_info( + cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active)); + stream_map.streams_map_current.emplace_back(stream_map_info( + cis_entry.conn_handle, codec_spec_conf::kLeAudioLocationMonoAudio, is_active)); + } + } + + return true; } - void UpdateCisConfiguration(const std::vector& cises, + bool UpdateCisConfiguration(const std::vector& cises, const stream_parameters& stream_params, uint8_t direction) { if (GetCodecLocation() != bluetooth::le_audio::types::CodecLocation::ADSP) { - return; + return false; } auto available_allocations = AdjustAllocationForOffloader(stream_params.audio_channel_allocation); - if (available_allocations == 0) { - log::error("There is no CIS connected"); - return; + if (available_allocations == -1) { + log::error("Unsupported allocation {:#x}", stream_params.audio_channel_allocation); + return false; + } + + if (available_allocations == codec_spec_conf::kLeAudioLocationMonoAudio) { + return UpdateCisMonoConfiguration(cises, direction); } auto& stream_map = offloader_stream_maps.get(direction); @@ -770,6 +823,8 @@ public: stream_map_info(cis_entry.conn_handle, current_allocation, is_active)); } } + + return true; } private: @@ -1233,12 +1288,13 @@ void CodecManager::UpdateBroadcastConnHandle( } } -void CodecManager::UpdateCisConfiguration(const std::vector& cises, +bool CodecManager::UpdateCisConfiguration(const std::vector& cises, const stream_parameters& stream_params, uint8_t direction) { if (pimpl_->IsRunning()) { return pimpl_->codec_manager_impl_->UpdateCisConfiguration(cises, stream_params, direction); } + return false; } void CodecManager::ClearCisConfiguration(uint8_t direction) { diff --git a/system/bta/le_audio/codec_manager.h b/system/bta/le_audio/codec_manager.h index 4ba95fbde66..b41bb3b7668 100644 --- a/system/bta/le_audio/codec_manager.h +++ b/system/bta/le_audio/codec_manager.h @@ -104,7 +104,7 @@ public: void Stop(void); virtual types::CodecLocation GetCodecLocation(void) const; virtual bool IsDualBiDirSwbSupported(void) const; - virtual void UpdateCisConfiguration(const std::vector& cises, + virtual bool UpdateCisConfiguration(const std::vector& cises, const stream_parameters& stream_params, uint8_t direction); virtual void ClearCisConfiguration(uint8_t direction); virtual bool IsUsingCodecExtensibility() const; diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc index 469241ad976..d72d5878802 100644 --- a/system/bta/le_audio/codec_manager_test.cc +++ b/system/bta/le_audio/codec_manager_test.cc @@ -269,10 +269,17 @@ static constexpr char kPropLeAudioOffloadDisabled[] = "persist.bluetooth.leaudio static constexpr char kPropLeAudioBidirSwbSupported[] = "bluetooth.leaudio.dual_bidirection_swb.supported"; +RawAddress GetTestAddress(uint8_t index) { + EXPECT_LT(index, UINT8_MAX); + RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}}; + return result; +} + class CodecManagerTestBase : public Test { public: virtual void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); + com::android::bluetooth::flags::provider_->reset_flags(); set_mock_offload_capabilities(offload_capabilities_none); bluetooth::legacy::hci::testing::SetMock(legacy_hci_mock_); @@ -506,6 +513,136 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationAdspDownMix) { } } +TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) { + com::android::bluetooth::flags::provider_->leaudio_mono_location_errata(true); + const std::vector offloading_preference(0); + codec_manager->Start(offloading_preference); + + // Current CIS configuration for two earbuds + std::vector cises{ + { + .id = 0x00, + .type = types::CisType::CIS_TYPE_BIDIRECTIONAL, + .conn_handle = 96, + .addr = RawAddress::kEmpty, // Disconnected + }, + { + .id = 0x01, + .type = types::CisType::CIS_TYPE_BIDIRECTIONAL, + .conn_handle = 97, + .addr = GetTestAddress(1), + }, + }; + + // Stream parameters + types::BidirectionalPair stream_params{ + .sink = + { + .sample_frequency_hz = 16000, + .frame_duration_us = 10000, + .octets_per_codec_frame = 40, + .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, + .codec_frames_blocks_per_sdu = 1, + .num_of_channels = 1, + .num_of_devices = 1, + .stream_locations = + { + std::pair{ + 97 /*conn_handle*/, + codec_spec_conf::kLeAudioLocationMonoAudio}, + }, + }, + .source = + { + .sample_frequency_hz = 16000, + .frame_duration_us = 10000, + .octets_per_codec_frame = 40, + .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, + .codec_frames_blocks_per_sdu = 1, + .num_of_channels = 1, + .num_of_devices = 1, + { + std::pair{ + 97 /*conn_handle*/, + codec_spec_conf::kLeAudioLocationMonoAudio}, + }, + }, + }; + + ASSERT_TRUE( + codec_manager->UpdateCisConfiguration(cises, stream_params.sink, kLeAudioDirectionSink)); + ASSERT_TRUE(codec_manager->UpdateCisConfiguration(cises, stream_params.source, + kLeAudioDirectionSource)); + + // Verify the offloader config content + types::BidirectionalPair> out_offload_configs; + codec_manager->UpdateActiveAudioConfig( + stream_params, {.sink = 44, .source = 44}, + [&out_offload_configs](const offload_config& config, uint8_t direction) { + out_offload_configs.get(direction) = config; + }); + + // Expect the same configuration for sink and source + ASSERT_TRUE(out_offload_configs.sink.has_value()); + ASSERT_TRUE(out_offload_configs.source.has_value()); + for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink, + bluetooth::le_audio::types::kLeAudioDirectionSource}) { + uint32_t allocation = 0; + auto& config = out_offload_configs.get(direction).value(); + ASSERT_EQ(2lu, config.stream_map.size()); + for (const auto& info : config.stream_map) { + if (info.stream_handle == 96) { + ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation); + // The disconnected should be inactive + ASSERT_FALSE(info.is_stream_active); + + } else if (info.stream_handle == 97) { + ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation); + // The connected should be active + ASSERT_TRUE(info.is_stream_active); + + } else { + ASSERT_EQ(97, info.stream_handle); + } + allocation |= info.audio_channel_allocation; + } + + ASSERT_EQ(16, config.bits_per_sample); + ASSERT_EQ(16000u, config.sampling_rate); + ASSERT_EQ(10000u, config.frame_duration); + ASSERT_EQ(40u, config.octets_per_frame); + ASSERT_EQ(1, config.blocks_per_sdu); + ASSERT_EQ(44, config.peer_delay_ms); + ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, allocation); + } + + // Clear the CIS configuration map (no active CISes). + codec_manager->ClearCisConfiguration(kLeAudioDirectionSink); + codec_manager->ClearCisConfiguration(kLeAudioDirectionSource); + out_offload_configs.sink = std::nullopt; + out_offload_configs.source = std::nullopt; + codec_manager->UpdateActiveAudioConfig( + stream_params, {.sink = 44, .source = 44}, + [&out_offload_configs](const offload_config& config, uint8_t direction) { + out_offload_configs.get(direction) = config; + }); + + // Expect sink & source configurations with empty CIS channel allocation map. + ASSERT_TRUE(out_offload_configs.sink.has_value()); + ASSERT_TRUE(out_offload_configs.source.has_value()); + for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink, + bluetooth::le_audio::types::kLeAudioDirectionSource}) { + auto& config = out_offload_configs.get(direction).value(); + ASSERT_EQ(0lu, config.stream_map.size()); + ASSERT_EQ(16, config.bits_per_sample); + ASSERT_EQ(16000u, config.sampling_rate); + ASSERT_EQ(10000u, config.frame_duration); + ASSERT_EQ(40u, config.octets_per_frame); + ASSERT_EQ(1, config.blocks_per_sdu); + ASSERT_EQ(44, config.peer_delay_ms); + } +} + TEST_F(CodecManagerTestAdsp, test_capabilities_none) { const std::vector offloading_preference(0); codec_manager->Start(offloading_preference); diff --git a/system/bta/le_audio/mock_codec_manager.cc b/system/bta/le_audio/mock_codec_manager.cc index 53f1f787064..addf45ba852 100644 --- a/system/bta/le_audio/mock_codec_manager.cc +++ b/system/bta/le_audio/mock_codec_manager.cc @@ -160,12 +160,13 @@ void CodecManager::Stop() { mock_codec_manager_pimpl_ = nullptr; } -void CodecManager::UpdateCisConfiguration(const std::vector& cises, +bool CodecManager::UpdateCisConfiguration(const std::vector& cises, const stream_parameters& stream_params, uint8_t direction) { if (pimpl_) { return pimpl_->UpdateCisConfiguration(cises, stream_params, direction); } + return false; } void CodecManager::ClearCisConfiguration(uint8_t direction) { diff --git a/system/bta/le_audio/mock_codec_manager.h b/system/bta/le_audio/mock_codec_manager.h index 8352742a96b..3203f332571 100644 --- a/system/bta/le_audio/mock_codec_manager.h +++ b/system/bta/le_audio/mock_codec_manager.h @@ -80,7 +80,7 @@ public: (const std::vector& conn_handle, std::function update_receiver)); - MOCK_METHOD((void), UpdateCisConfiguration, + MOCK_METHOD((bool), UpdateCisConfiguration, (const std::vector& cises, const bluetooth::le_audio::stream_parameters& stream_params, uint8_t direction), (const)); -- GitLab From 9c2c6aebb91b2f6905bd7be92b829a3d8cbe4436 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Wed, 2 Oct 2024 17:02:24 +0000 Subject: [PATCH 251/875] RAS: Add timeout alarm for ranging data Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 369303724 Test: m com.android.btservice Change-Id: I5d58a38e9d71f064b1e3042d81eaaebdff4fee98 --- system/bta/include/bta_ras_api.h | 1 + system/bta/ras/ras_client.cc | 123 ++++++++++++++++++ system/gd/hci/distance_measurement_manager.cc | 22 ++++ system/gd/hci/distance_measurement_manager.h | 1 + .../main/shim/distance_measurement_manager.cc | 6 + 5 files changed, 153 insertions(+) diff --git a/system/bta/include/bta_ras_api.h b/system/bta/include/bta_ras_api.h index 23457094faa..68eae523e69 100644 --- a/system/bta/include/bta_ras_api.h +++ b/system/bta/include/bta_ras_api.h @@ -64,6 +64,7 @@ public: virtual void OnDisconnected(const RawAddress& address) = 0; virtual void OnWriteVendorSpecificReplyComplete(const RawAddress& address, bool success) = 0; virtual void OnRemoteData(const RawAddress& address, const std::vector& data) = 0; + virtual void OnRemoteDataTimeout(const RawAddress& address) = 0; }; class RasClient { diff --git a/system/bta/ras/ras_client.cc b/system/bta/ras/ras_client.cc index 093dfe02657..c938973a70d 100644 --- a/system/bta/ras/ras_client.cc +++ b/system/bta/ras/ras_client.cc @@ -39,8 +39,13 @@ class RasClientImpl; RasClientImpl* instance; enum CallbackDataType { VENDOR_SPECIFIC_REPLY }; +enum TimeoutType { TIMEOUT_NONE, FIRST_SEGMENT, FOLLOWING_SEGMENT, RANGING_DATA_READY }; +enum RangingType { RANGING_TYPE_NONE, REAL_TIME, ON_DEMAND }; static constexpr uint16_t kCachedDataSize = 10; static constexpr uint16_t kInvalidGattHandle = 0x0000; +static constexpr uint16_t kFirstSegmentRangingDataTimeoutMs = 5000; +static constexpr uint16_t kFollowingSegmentTimeoutMs = 1000; +static constexpr uint16_t kRangingDataReadyTimeoutMs = 5000; class RasClientImpl : public bluetooth::ras::RasClient { public: @@ -61,6 +66,11 @@ public: struct RasTracker { RasTracker(const RawAddress& address, const RawAddress& address_for_cs) : address_(address), address_for_cs_(address_for_cs) {} + ~RasTracker() { + if (ranging_data_timeout_timer_ != nullptr) { + alarm_free(ranging_data_timeout_timer_); + } + } tCONN_ID conn_id_; RawAddress address_; RawAddress address_for_cs_; @@ -73,6 +83,9 @@ public: std::vector vendor_specific_characteristics_; uint8_t write_reply_counter_ = 0; uint8_t write_reply_success_counter_ = 0; + alarm_t* ranging_data_timeout_timer_ = nullptr; + RangingType ranging_type_ = RANGING_TYPE_NONE; + TimeoutType timeout_type_ = TIMEOUT_NONE; const gatt::Characteristic* FindCharacteristicByUuid(Uuid uuid) { for (auto& characteristic : service_->characteristics) { @@ -140,6 +153,12 @@ public: tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic); uint16_t real_time_att_handle = characteristic == nullptr ? kInvalidGattHandle : characteristic->value_handle; + // Check if the Real-Time ranging unsubscribed due to timeout + if (characteristic != nullptr && tracker->ranging_type_ == RANGING_TYPE_NONE) { + tracker->ranging_type_ = REAL_TIME; + SubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic); + SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, TimeoutType::FIRST_SEGMENT); + } callbacks_->OnConnected(address, real_time_att_handle, tracker->vendor_specific_characteristics_); return; @@ -362,6 +381,11 @@ public: std::vector data; data.resize(evt.len); std::copy(evt.value, evt.value + evt.len, data.begin()); + bool is_last = (data[0] >> 1 & 0x01); + alarm_cancel(tracker->ranging_data_timeout_timer_); + if (!is_last) { + SetTimeOutAlarm(tracker, kFollowingSegmentTimeoutMs, FOLLOWING_SEGMENT); + } callbacks_->OnRemoteData(tracker->address_for_cs_, data); } @@ -393,6 +417,9 @@ public: // Send get ranging data command tracker->latest_ranging_counter_ = ranging_counter; + if (tracker->timeout_type_ == RANGING_DATA_READY) { + alarm_cancel(tracker->ranging_data_timeout_timer_); + } GetRangingData(ranging_counter, tracker); } @@ -416,6 +443,7 @@ public: value[2] = (uint8_t)((ranging_counter >> 8) & 0xFF); BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP, value, GATT_AUTH_REQ_NO_MITM, GattWriteCallback, nullptr); + SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, FIRST_SEGMENT); } void AckRangingData(uint16_t ranging_counter, std::shared_ptr tracker) { @@ -437,6 +465,19 @@ public: } } + void AbortOperation(std::shared_ptr tracker) { + log::debug("address {}", tracker->address_for_cs_); + auto characteristic = tracker->FindCharacteristicByUuid(kRasControlPointCharacteristic); + if (characteristic == nullptr) { + log::warn("Can't find characteristic for RAS-CP"); + return; + } + tracker->handling_on_demand_data_ = false; + std::vector value{static_cast(Opcode::ABORT_OPERATION)}; + BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP, + value, GATT_AUTH_REQ_NO_MITM, GattWriteCallback, nullptr); + } + void GattWriteCallbackForVendorSpecificData(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, const uint8_t* /*value*/, GattWriteCallbackData* data) { @@ -549,6 +590,38 @@ public: nullptr); } + void UnsubscribeCharacteristic(std::shared_ptr tracker, const Uuid uuid) { + auto characteristic = tracker->FindCharacteristicByUuid(uuid); + if (characteristic == nullptr) { + log::warn("Can't find characteristic 0x{:04x}", uuid.As16Bit()); + return; + } + uint16_t ccc_handle = FindCccHandle(characteristic); + if (ccc_handle == GAP_INVALID_HANDLE) { + log::warn("Can't find Client Characteristic Configuration descriptor"); + return; + } + + tGATT_STATUS register_status = BTA_GATTC_DeregisterForNotifications( + gatt_if_, tracker->address_, characteristic->value_handle); + if (register_status != GATT_SUCCESS) { + log::error("Fail to deregister, {}", gatt_status_text(register_status)); + return; + } + log::info("UnsubscribeCharacteristic 0x{:04x}", uuid.As16Bit()); + + std::vector ccc_none(2, 0); + BTA_GATTC_WriteCharDescr( + tracker->conn_id_, ccc_handle, ccc_none, GATT_AUTH_REQ_NONE, + [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, + const uint8_t* value, void* data) { + if (instance) { + instance->OnDescriptorWrite(conn_id, status, handle, len, value, data); + } + }, + nullptr); + } + void OnDescriptorWrite(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) { log::info("conn_id:{}, handle:{}, status:{}", conn_id, handle, gatt_status_text(status)); @@ -640,12 +713,16 @@ public: void AllCharacteristicsReadComplete(std::shared_ptr tracker) { if (tracker->remote_supported_features_ & feature::kRealTimeRangingData) { log::info("Subscribe Real-time Ranging Data"); + tracker->ranging_type_ = REAL_TIME; SubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic); + SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, TimeoutType::FIRST_SEGMENT); } else { log::info("Subscribe On-demand Ranging Data"); + tracker->ranging_type_ = ON_DEMAND; SubscribeCharacteristic(tracker, kRasOnDemandDataCharacteristic); SubscribeCharacteristic(tracker, kRasRangingDataReadyCharacteristic); SubscribeCharacteristic(tracker, kRasRangingDataOverWrittenCharacteristic); + SetTimeOutAlarm(tracker, kRangingDataReadyTimeoutMs, TimeoutType::RANGING_DATA_READY); } auto characteristic = tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic); uint16_t real_time_att_handle = @@ -734,6 +811,52 @@ public: return nullptr; } + void SetTimeOutAlarm(std::shared_ptr tracker, uint16_t interval_ms, + TimeoutType timeout_type) { + log::debug("ranging_type_: {}, {}", (uint8_t)tracker->ranging_type_, (uint8_t)timeout_type); + tracker->timeout_type_ = timeout_type; + tracker->ranging_data_timeout_timer_ = alarm_new("Ranging Data Timeout"); + alarm_set_on_mloop( + tracker->ranging_data_timeout_timer_, interval_ms, + [](void* data) { + if (instance) { + instance->OnRangingDataTimeout(reinterpret_cast(data)); + } + }, + &tracker->address_); + } + + void OnRangingDataTimeout(RawAddress* address) { + auto tracker = FindTrackerByAddress(*address); + if (tracker == nullptr) { + log::warn("Skipping unknown device, address: {}", *address); + return; + } + + switch (tracker->timeout_type_) { + case FIRST_SEGMENT: + case FOLLOWING_SEGMENT: { + auto timeout_type_text = + tracker->timeout_type_ == FIRST_SEGMENT ? "first segment" : "following segment"; + if (tracker->ranging_type_ == REAL_TIME) { + log::error("Timeout to receive {} of Real-time ranging data", timeout_type_text); + UnsubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic); + tracker->ranging_type_ = RANGING_TYPE_NONE; + } else { + log::error("Timeout to receive {} of On-Demand ranging data", timeout_type_text); + AbortOperation(tracker); + } + } break; + case RANGING_DATA_READY: { + log::error("Timeout to receive ranging data ready"); + } break; + default: + log::error("Unexpected timeout type {}", (uint16_t)tracker->timeout_type_); + return; + } + callbacks_->OnRemoteDataTimeout(tracker->address_for_cs_); + } + private: uint16_t gatt_if_; std::list> trackers_; diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 780b9f5b0c1..b8ce2f4263e 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -1033,6 +1033,23 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } + void handle_remote_data_timeout(const Address address, uint16_t connection_handle) { + log::warn("address:{}, connection_handle 0x{:04x}", address.ToString(), connection_handle); + + if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + log::error("Can't find CS tracker for connection_handle {}", connection_handle); + return; + } + auto& tracker = cs_trackers_[connection_handle]; + if (tracker.measurement_ongoing && tracker.local_start) { + cs_trackers_[connection_handle].repeating_alarm->Cancel(); + send_le_cs_procedure_enable(connection_handle, Enable::DISABLED); + distance_measurement_callbacks_->OnDistanceMeasurementStopped( + tracker.address, REASON_INTERNAL_ERROR, METHOD_CS); + } + reset_tracker_on_stopped(&tracker); + } + void parse_ras_segments(RangingHeader ranging_header, PacketViewForRecombination& segment_data, uint16_t connection_handle) { log::debug("Data size {}, Ranging_header {}", segment_data.size(), ranging_header.ToString()); @@ -1644,5 +1661,10 @@ void DistanceMeasurementManager::HandleRemoteData(const Address& address, CallOn(pimpl_.get(), &impl::handle_remote_data, address, connection_handle, raw_data); } +void DistanceMeasurementManager::HandleRemoteDataTimeout(const Address& address, + uint16_t connection_handle) { + CallOn(pimpl_.get(), &impl::handle_remote_data_timeout, address, connection_handle); +} + } // namespace hci } // namespace bluetooth diff --git a/system/gd/hci/distance_measurement_manager.h b/system/gd/hci/distance_measurement_manager.h index 45c910fbdae..bb9158c592c 100644 --- a/system/gd/hci/distance_measurement_manager.h +++ b/system/gd/hci/distance_measurement_manager.h @@ -99,6 +99,7 @@ public: bool success); void HandleRemoteData(const Address& address, uint16_t connection_handle, const std::vector& raw_data); + void HandleRemoteDataTimeout(const Address& address, uint16_t connection_handle); static const ModuleFactory Factory; diff --git a/system/main/shim/distance_measurement_manager.cc b/system/main/shim/distance_measurement_manager.cc index 0cc8ea429e9..7891e846294 100644 --- a/system/main/shim/distance_measurement_manager.cc +++ b/system/main/shim/distance_measurement_manager.cc @@ -243,6 +243,12 @@ public: bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address), data); } + // Must be called from main_thread + void OnRemoteDataTimeout(const RawAddress& address) { + bluetooth::shim::GetDistanceMeasurementManager()->HandleRemoteDataTimeout( + bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address)); + } + private: ::DistanceMeasurementCallbacks* distance_measurement_callbacks_; static constexpr uint16_t kIllegalConnectionHandle = 0xffff; -- GitLab From b394a36fdd59cc4e8fdb1f5a48cf5929c3d35415 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Tue, 10 Sep 2024 23:26:23 -0700 Subject: [PATCH 252/875] add GMAP client Bug: 350102910 Bug: 353978074 Test: atest --host bluetooth_le_audio_client_test:GmapClientTest Flag: com.android.bluetooth.flags.leaudio_gmap_client Change-Id: Ia0adc40410bb0d735b71d0dacb006dd620f5394b --- system/bta/Android.bp | 4 + system/bta/BUILD.gn | 1 + system/bta/gmap/gmap_client.cc | 111 ++++++++++++++++++++++++++++ system/bta/gmap/gmap_client_test.cc | 101 +++++++++++++++++++++++++ system/bta/le_audio/client.cc | 36 ++++++++- system/bta/le_audio/devices.cc | 6 ++ system/bta/le_audio/devices.h | 2 + system/bta/le_audio/gmap_client.h | 66 +++++++++++++++++ 8 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 system/bta/gmap/gmap_client.cc create mode 100644 system/bta/gmap/gmap_client_test.cc create mode 100644 system/bta/le_audio/gmap_client.h diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 319b5dbbf2b..42ba31bcfd6 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -74,6 +74,7 @@ cc_library_static { "av/bta_av_main.cc", "av/bta_av_ssm.cc", "csis/csis_client.cc", + "gmap/gmap_client.cc", "groups/groups.cc", "has/has_client.cc", "has/has_ctp.cc", @@ -876,6 +877,7 @@ cc_test { ":TestMockStackBtmIso", ":TestMockStackL2cap", ":TestStubOsi", + "gmap/gmap_client.cc", "le_audio/audio_hal_client/audio_hal_client_test.cc", "le_audio/audio_hal_client/audio_sink_hal_client.cc", "le_audio/audio_hal_client/audio_source_hal_client.cc", @@ -976,6 +978,8 @@ cc_test { ":TestStubOsi", "gatt/database.cc", "gatt/database_builder.cc", + "gmap/gmap_client.cc", + "gmap/gmap_client_test.cc", "le_audio/broadcaster/broadcast_configuration_provider.cc", "le_audio/broadcaster/broadcaster_types.cc", "le_audio/client.cc", diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn index ba89c1cb693..49c014792a2 100644 --- a/system/bta/BUILD.gn +++ b/system/bta/BUILD.gn @@ -64,6 +64,7 @@ static_library("bta") { "gatt/database.cc", "gatt/database_builder.cc", "groups/groups.cc", + "gmap/gmap_client.cc", "has/has_client.cc", "has/has_ctp.cc", "has/has_preset.cc", diff --git a/system/bta/gmap/gmap_client.cc b/system/bta/gmap/gmap_client.cc new file mode 100644 index 00000000000..7cd8d8c054a --- /dev/null +++ b/system/bta/gmap/gmap_client.cc @@ -0,0 +1,111 @@ +/* + * Copyright (C) 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. + */ + +#include "bta/le_audio/gmap_client.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "bta_gatt_api.h" +#include "bta_gatt_queue.h" +#include "bta_le_audio_uuids.h" +#include "gap_api.h" +#include "gatt_api.h" +#include "internal_include/bt_trace.h" +#include "os/log.h" +#include "osi/include/properties.h" +#include "stack/include/bt_types.h" + +using bluetooth::Uuid; +using namespace bluetooth; +using bluetooth::le_audio::GmapClient; +bool GmapClient::is_offloader_support_gmap_ = false; + +void GmapClient::AddFromStorage(const RawAddress &addr, const uint8_t role, + const uint16_t role_handle, const uint8_t UGT_feature, + const uint16_t UGT_feature_handle) { + addr_ = addr; + role_ = role; + role_handle_ = role_handle; + UGT_feature_ = UGT_feature; + UGT_feature_handle_ = UGT_feature_handle; +} + +void GmapClient::DebugDump(int fd) { + std::stringstream stream; + if (!IsGmapClientEnabled()) { + dprintf(fd, "%s", "GmapClient not enabled"); + return; + } + stream << "GmapClient device: " << addr_ << ", Role: " << role_ << ", "; + stream << "UGT Feature: " << UGT_feature_ << "\n"; + dprintf(fd, "%s", stream.str().c_str()); +} + +bool GmapClient::IsGmapClientEnabled() { + bool flag = com::android::bluetooth::flags::leaudio_gmap_client(); + bool system_prop = osi_property_get_bool("bluetooth.profile.gmap.enabled", false); + + bool result = flag && system_prop && is_offloader_support_gmap_; + log::info("GmapClientEnabled={}, flag={}, system_prop={}, offloader_support={}", result, + system_prop, flag, GmapClient::is_offloader_support_gmap_); + return result; +} + +void GmapClient::UpdateGmapOffloaderSupport(bool value) { + GmapClient::is_offloader_support_gmap_ = value; +} + +bool GmapClient::parseAndSaveGmapRole(uint16_t len, const uint8_t *value) { + if (len != GmapClient::kGmapRoleLen) { + log::error("device: {}, Wrong len of GMAP Role characteristic", addr_); + return false; + } + + STREAM_TO_UINT8(role_, value); + log::info("GMAP device: {}, Role: {}", addr_, role_.to_string()); + return true; +} + +bool GmapClient::parseAndSaveUGTFeature(uint16_t len, const uint8_t *value) { + if (len != kGmapUGTFeatureLen) { + log::error("device: {}, Wrong len of GMAP UGT Feature characteristic", addr_); + return false; + } + STREAM_TO_UINT8(UGT_feature_, value); + log::info("GMAP device: {}, Feature: {}", addr_, UGT_feature_.to_string()); + return true; +} + +std::bitset<8> GmapClient::getRole() { return role_; } + +uint16_t GmapClient::getRoleHandle() { return role_handle_; } + +void GmapClient::setRoleHandle(uint16_t handle) { role_handle_ = handle; } + +std::bitset<8> GmapClient::getUGTFeature() { return UGT_feature_; } + +uint16_t GmapClient::getUGTFeatureHandle() { return UGT_feature_handle_; } + +void GmapClient::setUGTFeatureHandle(uint16_t handle) { UGT_feature_handle_ = handle; } diff --git a/system/bta/gmap/gmap_client_test.cc b/system/bta/gmap/gmap_client_test.cc new file mode 100644 index 00000000000..68aec5caf51 --- /dev/null +++ b/system/bta/gmap/gmap_client_test.cc @@ -0,0 +1,101 @@ +/* + * Copyright (C) 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. + */ + +#include "bta/le_audio/gmap_client.h" + +#include +#include +#include +#include +#include + +#include "bta/le_audio/le_audio_types.h" +#include "fake_osi.h" +#include "test/mock/mock_osi_properties.h" + +using bluetooth::le_audio::GmapClient; +using ::testing::_; + +static constexpr char kGmapEnabledSysProp[] = "bluetooth.profile.gmap.enabled"; + +void osi_property_set_bool(const char* key, bool value); + +class GmapClientTest : public ::testing::Test { +public: + RawAddress addr = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); + GmapClient gmapClient = GmapClient(addr); +}; + +TEST_F(GmapClientTest, test_parse_role) { + const uint8_t role = 0b0001; + gmapClient.parseAndSaveGmapRole(1, &role); + + ASSERT_EQ(gmapClient.getRole(), role); +} + +TEST_F(GmapClientTest, test_parse_invalid_role) { + const uint8_t role = 0b0001; + ASSERT_FALSE(gmapClient.parseAndSaveGmapRole(2, &role)); +} + +TEST_F(GmapClientTest, test_parse_ugt_feature) { + const uint8_t value = 0b0001; + gmapClient.parseAndSaveUGTFeature(1, &value); + + ASSERT_EQ(gmapClient.getUGTFeature(), value); +} + +TEST_F(GmapClientTest, test_parse_invalid_ugt_feature) { + const uint8_t value = 0b0001; + ASSERT_FALSE(gmapClient.parseAndSaveUGTFeature(2, &value)); +} + +TEST_F(GmapClientTest, test_add_from_storage) { + const uint8_t role = 0b0001; + const uint16_t role_handle = 2; + const uint8_t UGT_feature = 0b0011; + const uint16_t UGT_feature_handle = 4; + gmapClient.AddFromStorage(addr, role, role_handle, UGT_feature, UGT_feature_handle); + ASSERT_EQ(gmapClient.getRole(), role); + ASSERT_EQ(gmapClient.getRoleHandle(), role_handle); + ASSERT_EQ(gmapClient.getUGTFeature(), UGT_feature); + ASSERT_EQ(gmapClient.getUGTFeatureHandle(), UGT_feature_handle); +} + +TEST_F(GmapClientTest, test_role_handle) { + const uint16_t handle = 5; + gmapClient.setRoleHandle(handle); + ASSERT_EQ(gmapClient.getRoleHandle(), handle); +} + +TEST_F(GmapClientTest, test_ugt_feature_handle) { + const uint16_t handle = 6; + gmapClient.setUGTFeatureHandle(handle); + ASSERT_EQ(gmapClient.getUGTFeatureHandle(), handle); +} + +TEST_F(GmapClientTest, test_is_gmap_client_enabled) { + GmapClient::UpdateGmapOffloaderSupport(false); + ASSERT_EQ(GmapClient::IsGmapClientEnabled(), false); + + com::android::bluetooth::flags::provider_->leaudio_gmap_client(true); + osi_property_set_bool(kGmapEnabledSysProp, true); + + GmapClient::UpdateGmapOffloaderSupport(true); + + ASSERT_EQ(GmapClient::IsGmapClientEnabled(), true); + osi_property_set_bool(kGmapEnabledSysProp, false); +} diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index a0568998e2e..3102489aaa3 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -45,7 +45,9 @@ #include "content_control_id_keeper.h" #include "devices.h" #include "gatt_api.h" +#include "gmap_client.h" #include "hci/controller_interface.h" +#include "include/hardware/bt_gmap.h" #include "internal_include/stack_config.h" #include "le_audio/device_groups.h" #include "le_audio_health_status.h" @@ -72,6 +74,7 @@ using base::Closure; using bluetooth::Uuid; using bluetooth::common::ToString; +using bluetooth::gmap::RolesBitMask; using bluetooth::groups::DeviceGroups; using bluetooth::groups::DeviceGroupsCallbacks; using bluetooth::hci::IsoManager; @@ -84,6 +87,7 @@ using bluetooth::le_audio::ContentControlIdKeeper; using bluetooth::le_audio::DeviceConnectState; using bluetooth::le_audio::DsaMode; using bluetooth::le_audio::DsaModes; +using bluetooth::le_audio::GmapClient; using bluetooth::le_audio::GroupNodeStatus; using bluetooth::le_audio::GroupStatus; using bluetooth::le_audio::GroupStreamStatus; @@ -117,7 +121,6 @@ using bluetooth::le_audio::types::LeAudioContextType; using bluetooth::le_audio::types::PublishedAudioCapabilities; using bluetooth::le_audio::utils::GetAudioContextsFromSinkMetadata; using bluetooth::le_audio::utils::GetAudioContextsFromSourceMetadata; - using namespace bluetooth; /* Enums */ @@ -2052,6 +2055,12 @@ public: } else if (hdl == leAudioDevice->tmap_role_hdl_) { bluetooth::le_audio::client_parser::tmap::ParseTmapRole(leAudioDevice->tmap_role_, len, value); + } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() && + hdl == leAudioDevice->gmap_client_->getRoleHandle()) { + leAudioDevice->gmap_client_->parseAndSaveGmapRole(len, value); + } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() && + hdl == leAudioDevice->gmap_client_->getUGTFeatureHandle()) { + leAudioDevice->gmap_client_->parseAndSaveUGTFeature(len, value); } else { log::error("Unknown attribute read: 0x{:x}", hdl); } @@ -2767,6 +2776,7 @@ public: const gatt::Service* pac_svc = nullptr; const gatt::Service* ase_svc = nullptr; const gatt::Service* tmas_svc = nullptr; + const gatt::Service* gmap_svc = nullptr; std::vector csis_primary_handles; uint16_t cas_csis_included_handle = 0; @@ -2805,6 +2815,10 @@ public: log::info("Found Telephony and Media Audio service, handle: 0x{:04x}, device: {}", tmp.handle, leAudioDevice->address_); tmas_svc = &tmp; + } else if (tmp.uuid == bluetooth::le_audio::uuid::kGamingAudioServiceUuid) { + log::info("Found Gaming Audio service, handle: 0x{:04x}, device: {}", tmp.handle, + leAudioDevice->address_); + gmap_svc = &tmp; } } @@ -3057,6 +3071,26 @@ public: } } + if (gmap_svc && GmapClient::IsGmapClientEnabled()) { + leAudioDevice->gmap_client_ = std::make_unique(leAudioDevice->address_); + for (const gatt::Characteristic& charac : gmap_svc->characteristics) { + if (charac.uuid == bluetooth::le_audio::uuid::kRoleCharacteristicUuid) { + uint16_t handle = charac.value_handle; + leAudioDevice->gmap_client_->setRoleHandle(handle); + BtaGattQueue::ReadCharacteristic(conn_id, handle, OnGattReadRspStatic, NULL); + log::info("Found Gmap Role characteristic, handle: 0x{:04x}, device: {}", + leAudioDevice->gmap_client_->getRoleHandle(), leAudioDevice->address_); + } + if (charac.uuid == bluetooth::le_audio::uuid::kUnicastGameTerminalCharacteristicUuid) { + uint16_t handle = charac.value_handle; + leAudioDevice->gmap_client_->setUGTFeatureHandle(handle); + BtaGattQueue::ReadCharacteristic(conn_id, handle, OnGattReadRspStatic, NULL); + log::info("Found Gmap UGT Feature characteristic, handle: 0x{:04x}, device: {}", + leAudioDevice->gmap_client_->getUGTFeatureHandle(), leAudioDevice->address_); + } + } + } + leAudioDevice->known_service_handles_ = true; leAudioDevice->notify_connected_after_read_ = true; if (leAudioHealthStatus_) { diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc index 28b9be0eede..1c44b611442 100644 --- a/system/bta/le_audio/devices.cc +++ b/system/bta/le_audio/devices.cc @@ -1041,6 +1041,12 @@ void LeAudioDevice::Dump(int fd) { << ",mtu: " << std::to_string(mtu_) << "\n\tnumber of ases_: " << static_cast(ases_.size()); + if (gmap_client_ != nullptr) { + gmap_client_->DebugDump(fd); + } else { + stream << "GmapClient not initialized\n"; + } + if (ases_.size() > 0) { stream << "\n\t== ASEs == \n\t"; stream << "id active dir cis_id cis_handle sdu latency rtn " diff --git a/system/bta/le_audio/devices.h b/system/bta/le_audio/devices.h index d4c7d4ba2a0..1f972aae853 100644 --- a/system/bta/le_audio/devices.h +++ b/system/bta/le_audio/devices.h @@ -24,6 +24,7 @@ #include "audio_hal_client/audio_hal_client.h" #include "bta_groups.h" #include "gatt_api.h" +#include "gmap_client.h" #include "le_audio_types.h" #include "os/log.h" #include "osi/include/alarm.h" @@ -109,6 +110,7 @@ public: bool allowlist_flag_; bool acl_asymmetric_; bool acl_phy_update_done_; + std::unique_ptr gmap_client_; alarm_t* link_quality_timer; uint16_t link_quality_timer_data; diff --git a/system/bta/le_audio/gmap_client.h b/system/bta/le_audio/gmap_client.h new file mode 100644 index 00000000000..b1167b5bcd4 --- /dev/null +++ b/system/bta/le_audio/gmap_client.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 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 +#include + +#include + +namespace bluetooth::le_audio { + +class GmapClient { +public: + void AddFromStorage(const RawAddress& addr, const uint8_t role, const uint16_t role_handle, + const uint8_t UGT_feature, const uint16_t UGT_feature_handle); + + void DebugDump(int fd); + + static bool IsGmapClientEnabled(); + + static void UpdateGmapOffloaderSupport(bool value); + + GmapClient(const RawAddress& addr) : addr_(addr) {} + + bool parseAndSaveGmapRole(uint16_t len, const uint8_t* value); + + bool parseAndSaveUGTFeature(uint16_t len, const uint8_t* value); + + std::bitset<8> getRole(); + + uint16_t getRoleHandle(); + + void setRoleHandle(uint16_t handle); + + std::bitset<8> getUGTFeature(); + + uint16_t getUGTFeatureHandle(); + + void setUGTFeatureHandle(uint16_t handle); + + constexpr static uint16_t kGmapRoleLen = 1; + constexpr static uint16_t kGmapUGTFeatureLen = 1; + +private: + static bool is_offloader_support_gmap_; + std::bitset<8> role_; + uint16_t role_handle_; + std::bitset<8> UGT_feature_; + uint16_t UGT_feature_handle_; + RawAddress addr_; +}; +} // namespace bluetooth::le_audio -- GitLab From 5f53e096e7ebebb3da2b60879c78a01313dd40d9 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Thu, 3 Oct 2024 17:08:49 -0700 Subject: [PATCH 253/875] add Gatt Server Mock Bug: 350102910 Bug: 353978074 Test: atest --host bluetooth_le_audio_client_test Flag: com.android.bluetooth.flags.leaudio_gmap_client Change-Id: Id1e9964b152a3b273f1d5df84337ccd440f3f494 --- system/bta/test/common/bta_gatt_api_mock.cc | 61 +++++++++++++++++++++ system/bta/test/common/bta_gatt_api_mock.h | 59 ++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/system/bta/test/common/bta_gatt_api_mock.cc b/system/bta/test/common/bta_gatt_api_mock.cc index e3ac011cd6f..e5dee293fbd 100644 --- a/system/bta/test/common/bta_gatt_api_mock.cc +++ b/system/bta/test/common/bta_gatt_api_mock.cc @@ -25,6 +25,7 @@ using namespace bluetooth; static gatt::MockBtaGattInterface* gatt_interface = nullptr; +static gatt::MockBtaGattServerInterface* gatt_server_interface = nullptr; void gatt::SetMockBtaGattInterface(MockBtaGattInterface* mock_bta_gatt_interface) { gatt_interface = mock_bta_gatt_interface; @@ -98,3 +99,63 @@ tGATT_STATUS BTA_GATTC_DeregisterForNotifications(tGATT_IF client_if, const RawA log::assert_that(gatt_interface != nullptr, "Mock GATT interface not set!"); return gatt_interface->DeregisterForNotifications(client_if, remote_bda, handle); } + +void BTA_GATTS_Disable(void) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->Disable(); +} +void BTA_GATTS_AppDeregister(tGATT_IF server_if) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->AppDeregister(server_if); +} +void BTA_GATTS_AppRegister(const bluetooth::Uuid& app_uuid, tBTA_GATTS_CBACK* p_cback, + bool eatt_support) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->AppRegister(app_uuid, p_cback, eatt_support); +} +void BTA_GATTS_CancelOpen(tGATT_IF server_if, const RawAddress& remote_bda, bool is_direct) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->CancelOpen(server_if, remote_bda, is_direct); +} +void BTA_GATTS_Close(uint16_t conn_id) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->Close(conn_id); +} +void BTA_GATTS_AddService(tGATT_IF server_if, std::vector service, + BTA_GATTS_AddServiceCb cb) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->AddService(server_if, service, cb); +} +void BTA_GATTS_DeleteService(uint16_t service_id) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->DeleteService(service_id); +} +void BTA_GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_id, std::vector value, + bool need_confirm) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->HandleValueIndication(conn_id, attr_id, value, need_confirm); +} +void BTA_GATTS_Open(tGATT_IF server_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE addr_type, + bool is_direct, tBT_TRANSPORT transport) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->Open(server_if, remote_bda, addr_type, is_direct, transport); +} +void BTA_GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id, tGATT_STATUS status, + tGATTS_RSP* p_msg) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->SendRsp(conn_id, trans_id, status, p_msg); +} +void BTA_GATTS_StopService(uint16_t service_id) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->StopService(service_id); +} + +void BTA_GATTS_InitBonded(void) { + log::assert_that(gatt_server_interface != nullptr, "Mock GATT server interface not set!"); + gatt_server_interface->InitBonded(); +} + +void gatt::SetMockBtaGattServerInterface( + MockBtaGattServerInterface* mock_bta_gatt_server_interface) { + gatt_server_interface = mock_bta_gatt_server_interface; +} diff --git a/system/bta/test/common/bta_gatt_api_mock.h b/system/bta/test/common/bta_gatt_api_mock.h index 2a1f2d96692..6b404526ed1 100644 --- a/system/bta/test/common/bta_gatt_api_mock.h +++ b/system/bta/test/common/bta_gatt_api_mock.h @@ -84,4 +84,63 @@ public: */ void SetMockBtaGattInterface(MockBtaGattInterface* mock_bta_gatt_interface); +class BtaGattServerInterface { +public: + virtual void Disable() = 0; + virtual void AppRegister(const bluetooth::Uuid& /* app_uuid */, tBTA_GATTS_CBACK* /* p_cback */, + bool /* eatt_support */) = 0; + virtual void AppDeregister(tGATT_IF server_if) = 0; + virtual void Open(tGATT_IF /* server_if */, const RawAddress& /* remote_bda */, + tBLE_ADDR_TYPE /* addr_type */, bool /* is_direct */, + tBT_TRANSPORT /* transport */) = 0; + virtual void CancelOpen(tGATT_IF /* server_if */, const RawAddress& /* remote_bda */, + bool /* is_direct */) = 0; + virtual void Close(uint16_t /* conn_id */) = 0; + virtual void AddService(tGATT_IF /* server_if */, std::vector /* service */, + BTA_GATTS_AddServiceCb /* cb */) = 0; + virtual void DeleteService(uint16_t /* service_id */) = 0; + virtual void HandleValueIndication(uint16_t /* conn_id */, uint16_t /* attr_id */, + std::vector /* value */, bool /* need_confirm */) = 0; + virtual void SendRsp(uint16_t /* conn_id */, uint32_t /* trans_id */, tGATT_STATUS /* status */, + tGATTS_RSP* /* p_msg */) = 0; + virtual void StopService(uint16_t /* service_id */) = 0; + virtual void InitBonded() = 0; + virtual ~BtaGattServerInterface() = default; +}; + +class MockBtaGattServerInterface : public BtaGattServerInterface { +public: + MOCK_METHOD((void), Disable, ()); + MOCK_METHOD((void), AppRegister, + (const bluetooth::Uuid& uuid, tBTA_GATTS_CBACK* cb, bool eatt_support), (override)); + MOCK_METHOD((void), AppDeregister, (tGATT_IF server_if), (override)); + MOCK_METHOD((void), Open, + (tGATT_IF server_if, const RawAddress& remote_bda, tBLE_ADDR_TYPE type, + bool is_direct, tBT_TRANSPORT transport), + (override)); + MOCK_METHOD((void), CancelOpen, + (tGATT_IF server_if, const RawAddress& remote_bda, bool is_direct)); + MOCK_METHOD((void), Close, (uint16_t conn_id)); + MOCK_METHOD((void), AddService, + (tGATT_IF server_if, std::vector service, + BTA_GATTS_AddServiceCb cb), + (override)); + MOCK_METHOD((void), DeleteService, (uint16_t service_id)); + MOCK_METHOD((void), HandleValueIndication, + (uint16_t conn_id, uint16_t attr_id, std::vector value, bool need_confirm)); + + MOCK_METHOD((void), SendRsp, + (uint16_t conn_id, uint32_t trans_id, tGATT_STATUS status, tGATTS_RSP* p_msg)); + MOCK_METHOD((void), StopService, (uint16_t service_id)); + MOCK_METHOD((void), InitBonded, ()); +}; + +/** + * Set the {@link MockBtaGattServerInterface} for testing + * + * @param mock_bta_gatt_server_interface pointer to mock bta gatt server interface, + * could be null + */ +void SetMockBtaGattServerInterface(MockBtaGattServerInterface* mock_bta_gatt_server_interface); + } // namespace gatt -- GitLab From c4b7f139688fd2ed6b75a69489f0f0e95cea2e87 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 13 Sep 2024 18:52:17 +0000 Subject: [PATCH 254/875] Remove restricted devices only in non-restricted mode GD storage module does not know if the mode is restricted or not. It always remves the restricted devices on startup. This change moves the decision to remove restricted devices from the storage to btif_storage module. This change also links the device record created in restricted mode to the user ID. This ensures that different guests cannot access each other's devices. Test: mmm packages/modules/Bluetooth Test: Manual | Pair with a device in guest mode and restart the BT, paired device must still be available in the guest mode Flag: com.android.bluetooth.flags.guest_mode_bond Bug: 346337854 Bug: 349882273 Change-Id: I909053c7ffc5f5ac2ff2b8fc3840f3b77c7b543a --- system/btif/include/btif_config.h | 2 ++ system/btif/include/btif_storage.h | 11 +++++++ system/btif/src/btif_config.cc | 6 ++++ system/btif/src/btif_dm.cc | 5 ++- system/btif/src/btif_storage.cc | 31 +++++++++++++++++++ system/gd/storage/BUILD.gn | 5 ++- system/gd/storage/storage_module.cc | 3 +- system/main/shim/config.cc | 4 +++ system/main/shim/config.h | 1 + .../mock_main_shim_BtifConfigInterface.cc | 2 ++ 10 files changed, 67 insertions(+), 3 deletions(-) diff --git a/system/btif/include/btif_config.h b/system/btif/include/btif_config.h index da98582f673..828502c1f5a 100644 --- a/system/btif/include/btif_config.h +++ b/system/btif/include/btif_config.h @@ -48,6 +48,8 @@ bool btif_config_remove(const std::string& section, const std::string& key); void btif_config_remove_device(const std::string& section); +void btif_config_remove_device_with_key(const std::string& key); + size_t btif_config_get_bin_length(const std::string& section, const std::string& key); std::vector btif_config_get_paired_devices(); diff --git a/system/btif/include/btif_storage.h b/system/btif/include/btif_storage.h index ce81f2ad00c..9e4277a3cfa 100644 --- a/system/btif/include/btif_storage.h +++ b/system/btif/include/btif_storage.h @@ -334,6 +334,17 @@ void btif_storage_set_leaudio_has_acceptlist(const RawAddress& address, bool add ******************************************************************************/ bool btif_storage_is_restricted_device(const RawAddress* remote_bd_addr); +/******************************************************************************* + * + * Function btif_storage_prune_devices + * + * Description Removes restricted mode devices in non-restricted mode + * + * Returns none + * + ******************************************************************************/ +void btif_storage_prune_devices(); + bt_status_t btif_storage_add_ble_bonding_key(RawAddress* remote_bd_addr, const uint8_t* key, uint8_t key_type, uint8_t key_length); bt_status_t btif_storage_get_ble_bonding_key(const RawAddress& remote_bd_addr, uint8_t key_type, diff --git a/system/btif/src/btif_config.cc b/system/btif/src/btif_config.cc index 32dba2da4b3..c21bd33efb4 100644 --- a/system/btif/src/btif_config.cc +++ b/system/btif/src/btif_config.cc @@ -314,6 +314,12 @@ void btif_config_remove_device(const std::string& section) { bluetooth::shim::BtifConfigInterface::RemoveSection(section); } +void btif_config_remove_device_with_key(const std::string& key) { + log::assert_that(bluetooth::shim::is_gd_stack_started_up(), + "assert failed: bluetooth::shim::is_gd_stack_started_up()"); + bluetooth::shim::BtifConfigInterface::RemoveSectionWithProperty(key); +} + bool btif_config_clear(void) { log::assert_that(bluetooth::shim::is_gd_stack_started_up(), "assert failed: bluetooth::shim::is_gd_stack_started_up()"); diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 082dded39db..a57ad767811 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -59,7 +59,6 @@ #include "btif_api.h" #include "btif_bqr.h" #include "btif_config.h" -#include "btif_dm.h" #include "btif_metrics_logging.h" #include "btif_sdp.h" #include "btif_storage.h" @@ -1923,6 +1922,10 @@ void BTIF_dm_report_inquiry_status_change(tBTM_INQUIRY_STATE status) { } void BTIF_dm_enable() { + if (com::android::bluetooth::flags::guest_mode_bond()) { + btif_storage_prune_devices(); + } + BD_NAME bdname; bt_status_t status; bt_property_t prop; diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc index 8b969465042..d7403f396a2 100644 --- a/system/btif/src/btif_storage.cc +++ b/system/btif/src/btif_storage.cc @@ -1316,6 +1316,37 @@ bool btif_storage_is_restricted_device(const RawAddress* remote_bd_addr) { return btif_config_get_int(remote_bd_addr->ToString(), BTIF_STORAGE_KEY_RESTRICTED, &val); } +/******************************************************************************* + * + * Function btif_storage_prune_devices + * + * Description Removes restricted mode devices in non-restricted mode + * + * Returns none + * + ******************************************************************************/ +void btif_storage_prune_devices() { + if (GetInterfaceToProfiles()->config->isRestrictedMode()) { + int user_id = btif_storage_get_user_id(); + + // Remove the devices with different user id + for (const auto& bd_addr : btif_config_get_paired_devices()) { + auto name = bd_addr.ToString(); + int id = 0; + if (btif_config_get_int(name, BTIF_STORAGE_KEY_RESTRICTED, &id)) { + // Restricted device, remove if user ID is different + if (id != user_id) { + log::info("Removing {} since user changed from {} to {}", bd_addr, id, user_id); + btif_config_remove_device(name); + } + } + } + } else { + // Default user, remove all restricted devices + btif_config_remove_device_with_key(BTIF_STORAGE_KEY_RESTRICTED); + } +} + // Get the name of a device from btif for interop database matching. bool btif_storage_get_stored_remote_name(const RawAddress& bd_addr, char* name) { bt_property_t property; diff --git a/system/gd/storage/BUILD.gn b/system/gd/storage/BUILD.gn index 2c9d4bd109c..2efcdb781bb 100644 --- a/system/gd/storage/BUILD.gn +++ b/system/gd/storage/BUILD.gn @@ -30,5 +30,8 @@ source_set("BluetoothStorageSources") { "//bt/system/gd:gd_defaults", "//bt/system/log:log_defaults", ] - deps = [ "//bt/system/gd:gd_default_deps" ] + deps = [ + "//bt/system/gd:gd_default_deps", + "//bt/flags:bluetooth_flags_c_lib", + ] } diff --git a/system/gd/storage/storage_module.cc b/system/gd/storage/storage_module.cc index 9e5c3ecaf01..7cdfd507daa 100644 --- a/system/gd/storage/storage_module.cc +++ b/system/gd/storage/storage_module.cc @@ -17,6 +17,7 @@ #include "storage/storage_module.h" #include +#include #include #include @@ -176,7 +177,7 @@ void StorageModule::Start() { [this] { this->CallOn(this, &StorageModule::SaveDelayed); }); // Cleanup temporary pairings if we have left guest mode - if (!is_restricted_mode_) { + if (!com::android::bluetooth::flags::guest_mode_bond() && !is_restricted_mode_) { config->RemoveSectionWithProperty("Restricted"); } diff --git a/system/main/shim/config.cc b/system/main/shim/config.cc index b392b38bae5..efa9e142219 100644 --- a/system/main/shim/config.cc +++ b/system/main/shim/config.cc @@ -137,6 +137,10 @@ void BtifConfigInterface::RemoveSection(const std::string& section) { GetStorage()->RemoveSection(section); } +void BtifConfigInterface::RemoveSectionWithProperty(const std::string& property) { + GetStorage()->RemoveSectionWithProperty(property); +} + std::vector BtifConfigInterface::GetPersistentDevices() { return GetStorage()->GetPersistentSections(); } diff --git a/system/main/shim/config.h b/system/main/shim/config.h index d8bb44e1005..ebbc94f16bd 100644 --- a/system/main/shim/config.h +++ b/system/main/shim/config.h @@ -44,6 +44,7 @@ public: size_t length); static bool RemoveProperty(const std::string& section, const std::string& key); static void RemoveSection(const std::string& section); + static void RemoveSectionWithProperty(const std::string& property); static std::vector GetPersistentDevices(); static void ConvertEncryptOrDecryptKeyIfNeeded(); static void Clear(); diff --git a/system/test/mock/mock_main_shim_BtifConfigInterface.cc b/system/test/mock/mock_main_shim_BtifConfigInterface.cc index f9000a53121..1029481de59 100644 --- a/system/test/mock/mock_main_shim_BtifConfigInterface.cc +++ b/system/test/mock/mock_main_shim_BtifConfigInterface.cc @@ -76,6 +76,8 @@ bool bluetooth::shim::BtifConfigInterface::RemoveProperty(const std::string& /* return false; } void bluetooth::shim::BtifConfigInterface::RemoveSection(const std::string& /* section */) {} +void bluetooth::shim::BtifConfigInterface::RemoveSectionWithProperty( + const std::string& /* property */) {} std::vector bluetooth::shim::BtifConfigInterface::GetPersistentDevices() { return std::vector(); } -- GitLab From 29af1076a9281a0850c5e9be23db98ce5197263e Mon Sep 17 00:00:00 2001 From: Katherine Lai Date: Mon, 16 Sep 2024 19:45:35 +0000 Subject: [PATCH 255/875] HAL: Add mgmt via soong config to enable MSFT Extension For most devices, there's no need to query MSFT opcode. This patch adds mgmt capabilities via soong config. Bug: 372707387 Test: m -j Flag: Exempt, no change to default behavior Change-Id: I9c69fa06f4dc58a61e3f9a4b53e3b8df49bc122a --- system/gd/Android.bp | 34 ++++++++++++++++++++++++++++++ system/gd/hal/Android.bp | 14 +++++++++++++ system/gd/hal/hci_hal_android.cc | 3 +++ system/gd/hal/mgmt.cc | 6 +++--- system/gd/hal/mgmt_stub.cc | 36 ++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 system/gd/hal/mgmt_stub.cc diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 9501a6e6965..5f67289b2fc 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -89,10 +89,44 @@ cc_defaults { ], } +soong_config_module_type { + name: "mgmt_cc_defaults", + module_type: "cc_defaults", + config_namespace: "mgmt", + variables: ["vertical"], + properties: ["srcs"], +} + +soong_config_string_variable { + name: "vertical", + values: [ + "android_default", + "android_desktop", + ], +} + +mgmt_cc_defaults { + name: "mgmt_defaults", + soong_config_variables: { + vertical: { + android_desktop: { + srcs: [":BluetoothHalSources_mgmt"], + }, + android_default: { + srcs: [":BluetoothHalSources_mgmt_stub"], + }, + conditions_default: { + srcs: [":BluetoothHalSources_mgmt_stub"], + }, + }, + }, +} + cc_defaults { name: "libbluetooth_gd_defaults", defaults: [ "gd_defaults", + "mgmt_defaults", ], host_supported: true, target: { diff --git a/system/gd/hal/Android.bp b/system/gd/hal/Android.bp index 91e1573c0e8..1086c318735 100644 --- a/system/gd/hal/Android.bp +++ b/system/gd/hal/Android.bp @@ -51,6 +51,20 @@ filegroup { ], } +filegroup { + name: "BluetoothHalSources_mgmt_stub", + srcs: [ + "mgmt_stub.cc", + ], +} + +filegroup { + name: "BluetoothHalSources_mgmt", + srcs: [ + "mgmt.cc", + ], +} + filegroup { name: "BluetoothHalSources_ranging_android", srcs: [ diff --git a/system/gd/hal/hci_hal_android.cc b/system/gd/hal/hci_hal_android.cc index 1c823c59bdf..3e66f981825 100644 --- a/system/gd/hal/hci_hal_android.cc +++ b/system/gd/hal/hci_hal_android.cc @@ -24,6 +24,7 @@ #include "hal/hci_backend.h" #include "hal/hci_hal.h" #include "hal/link_clocker.h" +#include "hal/mgmt.h" #include "hal/snoop_logger.h" namespace bluetooth::hal { @@ -157,6 +158,8 @@ public: backend_->sendIsoData(packet); } + uint16_t getMsftOpcode() override { return Mgmt().get_vs_opcode(MGMT_VS_OPCODE_MSFT); } + protected: void ListDependencies(ModuleList* list) const override { list->add(); diff --git a/system/gd/hal/mgmt.cc b/system/gd/hal/mgmt.cc index fd472ed01c6..dd2e0bca6e6 100644 --- a/system/gd/hal/mgmt.cc +++ b/system/gd/hal/mgmt.cc @@ -51,7 +51,7 @@ constexpr static uint8_t BTPROTO_HCI = 1; constexpr static uint16_t HCI_CHANNEL_CONTROL = 3; constexpr static uint16_t HCI_DEV_NONE = 0xffff; -static int btsocket_open_mgmt(uint16_t hci) { +static int btsocket_open_mgmt() { int fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_NONBLOCK, BTPROTO_HCI); if (fd < 0) { log::error("Failed to open BT socket."); @@ -84,7 +84,7 @@ static int btsocket_open_mgmt(uint16_t hci) { */ uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) { int hci = GetAdapterIndex(); - int fd = btsocket_open_mgmt(hci); + int fd = btsocket_open_mgmt(); uint16_t ret_opcode = HCI_OP_NOP; if (fd < 0) { @@ -99,7 +99,7 @@ uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) { struct mgmt_cp_get_vs_opcode* cp = reinterpret_cast(ev.data); cp->hci_id = hci; - cp->vendor_specification = MGMT_VS_OPCODE_MSFT; + cp->vendor_specification = vendor_specification; int ret; struct pollfd writable[1]; diff --git a/system/gd/hal/mgmt_stub.cc b/system/gd/hal/mgmt_stub.cc new file mode 100644 index 00000000000..19a3a968de2 --- /dev/null +++ b/system/gd/hal/mgmt_stub.cc @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/* + * MGMT stub + */ + +#include + +#include "hal/mgmt.h" + +namespace bluetooth { +namespace hal { + +uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) { + log::debug("Using stub for vendor opcode 0x{:04x}", vendor_specification); + return 0; +} + +} // namespace hal +} // namespace bluetooth -- GitLab From 0899608a16a3a1302fafbd69cfcc4da47248e7af Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Thu, 10 Oct 2024 18:45:03 +0000 Subject: [PATCH 256/875] Add flag com.android.bluetooth.flag.btsec_cycle_irks Bug: 372714979 Bug: 315241296 Flag: com.android.bluetooth.flags.btsec_cycle_irks Test: m libbluetooth Ignore-AOSP-First: security Tag: #security Change-Id: I4921ecd2653b2109a7f4d8ade3c43fe3eed36940 --- flags/security.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/security.aconfig b/flags/security.aconfig index 5f9e3b1a083..73cdb6cbc5f 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -54,3 +54,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "btsec_cycle_irks" + namespace: "bluetooth" + description: "Change the IRK per BT spec when all devices are unbonded" + bug: "372714979" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 248e811836f82217c5b23234ae926b4994790c8d Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 10 Oct 2024 15:22:07 -0700 Subject: [PATCH 257/875] Remove unused resources This strings resources are not used and some generate lint warning. Removing them to clean up the warning This is solving 22 StringFormatCount warning, but generate a lot of ExtraTranslation fixing the ExtraTranslation are part of follow up Bug: 372738580 Fix: 372738580 Test: m Bluetooth Flag: Exempt dead code removal Change-Id: I1203573a22b4527ebf64dc165191579e653b4e06 --- android/app/lint-baseline.xml | 5162 +++++++++++++++++++++++++--- android/app/res/values/strings.xml | 8 - 2 files changed, 4707 insertions(+), 463 deletions(-) diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml index 8b51a67d099..5b716a7eb66 100644 --- a/android/app/lint-baseline.xml +++ b/android/app/lint-baseline.xml @@ -2034,7 +2034,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -2045,7 +2045,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -2364,7 +2364,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2375,7 +2375,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2386,7 +2386,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2397,7 +2397,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2408,7 +2408,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2419,7 +2419,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -2430,7 +2430,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -2441,7 +2441,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2452,7 +2452,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2463,7 +2463,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2474,7 +2474,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2485,7 +2485,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2496,7 +2496,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -2507,7 +2507,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2518,7 +2518,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -2529,7 +2529,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2540,7 +2540,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -2551,7 +2551,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2562,7 +2562,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2573,7 +2573,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2584,7 +2584,7 @@ errorLine2=" ~~~~~~"> @@ -2595,7 +2595,7 @@ errorLine2=" ~~~~~~~"> @@ -2606,7 +2606,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2617,7 +2617,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -2628,7 +2628,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2639,7 +2639,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2650,7 +2650,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2661,7 +2661,7 @@ errorLine2=" ~~~~~~~"> @@ -2672,7 +2672,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2683,7 +2683,7 @@ errorLine2=" ~~~~~~~~~~"> @@ -2694,7 +2694,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2705,7 +2705,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -2716,7 +2716,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2727,7 +2727,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -2738,7 +2738,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -2749,7 +2749,7 @@ errorLine2=" ~~~~~~~~~"> @@ -2760,7 +2760,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2771,7 +2771,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -2782,7 +2782,7 @@ errorLine2=" ~~~~~~~~~"> @@ -2793,7 +2793,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2804,7 +2804,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -2815,7 +2815,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2826,7 +2826,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2837,7 +2837,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2848,7 +2848,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -2859,7 +2859,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2870,7 +2870,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2881,7 +2881,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2892,7 +2892,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -2903,7 +2903,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2914,7 +2914,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -2925,7 +2925,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2936,7 +2936,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2947,7 +2947,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -2958,7 +2958,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2969,7 +2969,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -2980,7 +2980,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -2991,7 +2991,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -3002,7 +3002,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -3013,7 +3013,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3024,7 +3024,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3035,7 +3035,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -3046,7 +3046,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -3057,7 +3057,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -3068,7 +3068,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -3079,7 +3079,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3090,7 +3090,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -3101,7 +3101,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3112,7 +3112,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3123,7 +3123,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3134,7 +3134,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3145,7 +3145,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3156,7 +3156,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -3167,7 +3167,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3178,7 +3178,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -3189,7 +3189,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -3200,7 +3200,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -3211,7 +3211,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -3222,7 +3222,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3233,7 +3233,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -3244,7 +3244,7 @@ errorLine2=" ~~~~"> @@ -3255,7 +3255,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3266,7 +3266,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -3277,7 +3277,7 @@ errorLine2=" ~~~~"> @@ -9639,6 +9639,4626 @@ column="5"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/app/res/values/strings.xml b/android/app/res/values/strings.xml index 38afa5c0ae1..7ee1b726151 100644 --- a/android/app/res/values/strings.xml +++ b/android/app/res/values/strings.xml @@ -70,8 +70,6 @@ Turn on - - File transfer Accept incoming file? @@ -92,16 +90,12 @@ Bluetooth share: Receiving %1$s Bluetooth share: Received %1$s - - Bluetooth share: File %1$s not received Bluetooth share: Sending %1$s Bluetooth share: Sent %1$s - - 100%% complete Bluetooth share: File %1$s not sent @@ -174,7 +168,6 @@ The file will be received. Check progress in the Notifications panel. - The file can\'t be received. Stopped receiving file from \u0022%1$s\u0022 Sending file to \u0022%1$s\u0022 Sending %1$s files to \u0022%2$s\u0022 @@ -239,7 +232,6 @@ Now Playing Application Icon - Bluetooth audio connected Bluetooth audio disconnected" Bluetooth Audio Files bigger than 4GB cannot be transferred -- GitLab From 673af20bd9eb492f01bf5eb419fa42ad4360ff7e Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 10 Oct 2024 15:50:26 -0700 Subject: [PATCH 258/875] TypographyEllipsis: replace unicode with xml escape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The translation tool doesn't handle very well escaped character. Using a unicode writing for Ellipsis \u2026 (…) become ... in translated file. By using … as recommended by Android Lint and as used by other modules. We expect the translated content to be fixed. "Replace "..." with ellipsis character (…, &#8230;) ?" Bug: 289445022 Flag: Exempt resource nit update Test: m Bluetooth & regenerate lint Change-Id: I059251ffa0d501ba398c51d60f3e3c46c783918a --- android/app/res/values/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/app/res/values/strings.xml b/android/app/res/values/strings.xml index 7ee1b726151..8154ebedd9f 100644 --- a/android/app/res/values/strings.xml +++ b/android/app/res/values/strings.xml @@ -110,7 +110,7 @@ File size: %1$s - Receiving file\u2026 + Receiving file… Stop @@ -141,7 +141,7 @@ To: \u0022%1$s\u0022 File type: %1$s (%2$s) - Sending file\u2026 + Sending file… @@ -163,8 +163,8 @@ The file doesn\'t exist. \n - Please wait\u2026 - Turning on Bluetooth\u2026 + Please wait… + Turning on Bluetooth… The file will be received. Check progress in the Notifications panel. -- GitLab From 6012433653b2770ddb67f5d6e9042e8ff6f8d66c Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Thu, 8 Aug 2024 00:27:51 +0000 Subject: [PATCH 259/875] Fix type confusion in avdt_msg.cc It is possible for a malicious user to reply to a pending AVDT message with the wrong type, leading to type confusion and an eventual OOB access. Add message type validation. Bug: 273995284 Bug: 358212054 Flag: com.android.bluetooth.flags.btsec_avdt_msg_ind_type_confusion Test: m libbluetooth Ignore-AOSP-First: security Tag: #security Change-Id: Iea207e7e5e3d469ccbc81f5abf945723cf7b60d3 --- system/stack/avdt/avdt_msg.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/system/stack/avdt/avdt_msg.cc b/system/stack/avdt/avdt_msg.cc index d8d52693405..6d59fbaaf3b 100644 --- a/system/stack/avdt/avdt_msg.cc +++ b/system/stack/avdt/avdt_msg.cc @@ -29,6 +29,7 @@ #define LOG_TAG "bluetooth-a2dp" #include +#include #include #include "avdt_api.h" @@ -1548,6 +1549,16 @@ void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf) { avdt_msg_send_grej(p_ccb, sig, &msg); } } + + /* validate reject/response against cached sig */ + if (com::android::bluetooth::flags::btsec_avdt_msg_ind_type_confusion()) { + if (((msg_type == AVDT_MSG_TYPE_RSP) || (msg_type == AVDT_MSG_TYPE_REJ)) && + (p_ccb->p_curr_cmd == nullptr || p_ccb->p_curr_cmd->event != sig)) { + log::warn("Dropping msg with mismatched sig; sig={} event type={}", sig, + p_ccb->p_curr_cmd->event); + ok = false; + } + } } log::verbose("msg_type={}, sig={}", msg_type, sig); -- GitLab From d7e55cf997f71842c072e765519e54ae1fb9e22b Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 9 Oct 2024 17:42:25 -0700 Subject: [PATCH 260/875] Remove some unnecessary uses of loghex Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, log change Change-Id: I913b5c5c25dd200f0e6aab3ef279eb2f7b1a10e3 --- .../hardware/avrcp/avrcp_logging_helper.h | 31 +++++++++---------- system/packet/avrcp/avrcp_packet.cc | 2 ++ system/packet/avrcp/change_path.cc | 2 ++ ...urrent_player_application_setting_value.cc | 2 ++ .../avrcp/get_element_attributes_packet.cc | 2 ++ system/packet/avrcp/get_item_attributes.cc | 2 ++ .../list_player_application_setting_values.cc | 2 ++ system/packet/avrcp/pass_through_packet.cc | 4 ++- system/packet/avrcp/play_item.cc | 2 ++ system/packet/avrcp/set_absolute_volume.cc | 4 ++- system/packet/avrcp/set_addressed_player.cc | 2 ++ .../set_player_application_setting_value.cc | 2 ++ .../profile/avrcp/avrcp_message_converter.h | 1 + system/profile/avrcp/connection_handler.cc | 4 +-- system/profile/avrcp/device.cc | 2 +- system/profile/sdp/sdp_logging_helper.h | 9 +++--- system/stack/a2dp/a2dp_vendor.cc | 7 +++-- system/stack/btm/btm_iso_impl.h | 10 +++--- 18 files changed, 56 insertions(+), 34 deletions(-) diff --git a/system/include/hardware/avrcp/avrcp_logging_helper.h b/system/include/hardware/avrcp/avrcp_logging_helper.h index d5a798ce9f4..5ae1f4076ed 100644 --- a/system/include/hardware/avrcp/avrcp_logging_helper.h +++ b/system/include/hardware/avrcp/avrcp_logging_helper.h @@ -25,7 +25,6 @@ #include #include "avrcp_common.h" -#include "internal_include/bt_trace.h" #include "macros.h" namespace bluetooth { @@ -42,7 +41,7 @@ inline std::string CTypeText(const CType& type) { CASE_RETURN_TEXT(CType::CHANGED); CASE_RETURN_TEXT(CType::INTERIM); default: - return "Unknown CType: " + loghex((uint8_t)type); + return fmt::format("Unknown CType: 0x{:x}", (uint8_t)type); } } @@ -57,7 +56,7 @@ inline std::string OpcodeText(const Opcode& opcode) { CASE_RETURN_TEXT(Opcode::SUBUNIT_INFO); CASE_RETURN_TEXT(Opcode::PASS_THROUGH); default: - return "Unknown Opcode: " + loghex((uint8_t)opcode); + return fmt::format("Unknown Opcode: 0x{:x}", (uint8_t)opcode); } } @@ -79,7 +78,7 @@ inline std::string CommandPduText(const CommandPdu& pdu) { CASE_RETURN_TEXT(CommandPdu::SET_ADDRESSED_PLAYER); CASE_RETURN_TEXT(CommandPdu::PLAY_ITEM); default: - return "Unknown Command PDU: " + loghex((uint8_t)pdu); + return fmt::format("Unknown Command PDU: 0x{:x}", (uint8_t)pdu); } } @@ -91,7 +90,7 @@ inline std::string PacketTypeText(const PacketType& type) { switch (type) { CASE_RETURN_TEXT(PacketType::SINGLE); default: - return "Unknown Packet Type: " + loghex((uint8_t)type); + return fmt::format("Unknown Packet Type: 0x{:x}", (uint8_t)type); } } @@ -104,7 +103,7 @@ inline std::string CapabilityText(const Capability& cap) { CASE_RETURN_TEXT(Capability::COMPANY_ID); CASE_RETURN_TEXT(Capability::EVENTS_SUPPORTED); default: - return "Unknown Capability: " + loghex((uint8_t)cap); + return fmt::format("Unknown Capability: 0x{:x}", (uint8_t)cap); } } @@ -124,7 +123,7 @@ inline std::string EventText(const Event& event) { CASE_RETURN_TEXT(Event::UIDS_CHANGED); CASE_RETURN_TEXT(Event::VOLUME_CHANGED); default: - return "Unknown Event: " + loghex((uint8_t)event); + return fmt::format("Unknown Event: 0x{:x}", (uint8_t)event); } } @@ -143,7 +142,7 @@ inline std::string AttributeText(const Attribute& attr) { CASE_RETURN_TEXT(Attribute::PLAYING_TIME); CASE_RETURN_TEXT(Attribute::DEFAULT_COVER_ART); default: - return "Unknown Attribute Value: " + loghex((uint32_t)attr); + return fmt::format("Unknown Attribute Value: 0x{:x}", (uint32_t)attr); } } @@ -177,7 +176,7 @@ inline std::string StatusText(const Status& status) { CASE_RETURN_TEXT(Status::NO_AVAILABLE_PLAYERS); CASE_RETURN_TEXT(Status::ADDRESSED_PLAYER_CHANGED); default: - return "Unknown Status: " + loghex((uint8_t)status); + return fmt::format("Unknown Status: 0x{:x}", (uint8_t)status); } } @@ -192,7 +191,7 @@ inline std::string BrowsePduText(const BrowsePdu& pdu) { CASE_RETURN_TEXT(BrowsePdu::CHANGE_PATH); CASE_RETURN_TEXT(BrowsePdu::GET_ITEM_ATTRIBUTES); default: - return "Unknown Browse PDU: " + loghex((uint8_t)pdu); + return fmt::format("Unknown Browse PDU: 0x{:x}", (uint8_t)pdu); } } @@ -207,7 +206,7 @@ inline std::string ScopeText(const Scope& scope) { CASE_RETURN_TEXT(Scope::SEARCH); CASE_RETURN_TEXT(Scope::NOW_PLAYING); default: - return "Unknown Scope: " + loghex((uint8_t)scope); + return fmt::format("Unknown Scope: 0x{:x}", (uint8_t)scope); } } @@ -218,7 +217,7 @@ inline std::string DirectionText(const Direction& dir) { CASE_RETURN_TEXT(Direction::UP); CASE_RETURN_TEXT(Direction::DOWN); default: - return "Unknown Direction: " + loghex((uint8_t)dir); + return fmt::format("Unknown Direction: 0x{:x}", (uint8_t)dir); } } @@ -231,7 +230,7 @@ inline std::string KeyStateText(const KeyState& state) { CASE_RETURN_TEXT(KeyState::PUSHED); CASE_RETURN_TEXT(KeyState::RELEASED); default: - return "Unknown KeyState: " + loghex((uint8_t)state); + return fmt::format("Unknown KeyState: 0x{:x}", (uint8_t)state); } } @@ -246,7 +245,7 @@ inline std::string PlayerAttributeText(const PlayerAttribute& attr) { CASE_RETURN_TEXT(PlayerAttribute::SHUFFLE); CASE_RETURN_TEXT(PlayerAttribute::SCAN); } - return "Unknown Player Attribute: " + loghex((uint8_t)attr); + return fmt::format("Unknown Player Attribute: 0x{:x}", (uint8_t)attr); } inline std::ostream& operator<<(std::ostream& os, const PlayerAttribute& attr) { @@ -260,7 +259,7 @@ inline std::string PlayerRepeatValueText(const PlayerRepeatValue& val) { CASE_RETURN_TEXT(PlayerRepeatValue::ALL); CASE_RETURN_TEXT(PlayerRepeatValue::GROUP); } - return "Unknown Player Repeat Value: " + loghex((uint8_t)val); + return fmt::format("Unknown Player Repeat Value: 0x{:x}", (uint8_t)val); } inline std::ostream& operator<<(std::ostream& os, const PlayerRepeatValue& val) { @@ -273,7 +272,7 @@ inline std::string PlayerShuffleValueText(const PlayerShuffleValue& val) { CASE_RETURN_TEXT(PlayerShuffleValue::ALL); CASE_RETURN_TEXT(PlayerShuffleValue::GROUP); } - return "Unknown Player Shuffle Value: " + loghex((uint8_t)val); + return fmt::format("Unknown Player Shuffle Value: 0x{:x}", (uint8_t)val); } inline std::ostream& operator<<(std::ostream& os, const PlayerShuffleValue& val) { diff --git a/system/packet/avrcp/avrcp_packet.cc b/system/packet/avrcp/avrcp_packet.cc index 5a79f84f0f8..c20de532c38 100644 --- a/system/packet/avrcp/avrcp_packet.cc +++ b/system/packet/avrcp/avrcp_packet.cc @@ -22,6 +22,8 @@ #include #include +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/change_path.cc b/system/packet/avrcp/change_path.cc index 2f5a27d14b2..08071e0cca1 100644 --- a/system/packet/avrcp/change_path.cc +++ b/system/packet/avrcp/change_path.cc @@ -18,6 +18,8 @@ #include +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/get_current_player_application_setting_value.cc b/system/packet/avrcp/get_current_player_application_setting_value.cc index 1c48b8fc5e7..54126f48123 100644 --- a/system/packet/avrcp/get_current_player_application_setting_value.cc +++ b/system/packet/avrcp/get_current_player_application_setting_value.cc @@ -16,6 +16,8 @@ #include "get_current_player_application_setting_value.h" +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/get_element_attributes_packet.cc b/system/packet/avrcp/get_element_attributes_packet.cc index 59d3c815c37..66319ad63d7 100644 --- a/system/packet/avrcp/get_element_attributes_packet.cc +++ b/system/packet/avrcp/get_element_attributes_packet.cc @@ -20,6 +20,8 @@ #include +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/get_item_attributes.cc b/system/packet/avrcp/get_item_attributes.cc index 0e3e10d3eff..42836ebe82e 100644 --- a/system/packet/avrcp/get_item_attributes.cc +++ b/system/packet/avrcp/get_item_attributes.cc @@ -18,6 +18,8 @@ #include +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/list_player_application_setting_values.cc b/system/packet/avrcp/list_player_application_setting_values.cc index 603279824b8..ec58958e778 100644 --- a/system/packet/avrcp/list_player_application_setting_values.cc +++ b/system/packet/avrcp/list_player_application_setting_values.cc @@ -16,6 +16,8 @@ #include "list_player_application_setting_values.h" +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/pass_through_packet.cc b/system/packet/avrcp/pass_through_packet.cc index dce89902ae9..e052e72276c 100644 --- a/system/packet/avrcp/pass_through_packet.cc +++ b/system/packet/avrcp/pass_through_packet.cc @@ -16,6 +16,8 @@ #include "pass_through_packet.h" +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { @@ -70,4 +72,4 @@ std::string PassThroughPacket::ToString() const { } } // namespace avrcp -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/packet/avrcp/play_item.cc b/system/packet/avrcp/play_item.cc index af850dc2c0b..8fcdda0d0b3 100644 --- a/system/packet/avrcp/play_item.cc +++ b/system/packet/avrcp/play_item.cc @@ -16,6 +16,8 @@ #include "play_item.h" +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/set_absolute_volume.cc b/system/packet/avrcp/set_absolute_volume.cc index 81cada510dc..81820c419a1 100644 --- a/system/packet/avrcp/set_absolute_volume.cc +++ b/system/packet/avrcp/set_absolute_volume.cc @@ -16,6 +16,8 @@ #include "set_absolute_volume.h" +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { @@ -74,4 +76,4 @@ std::string SetAbsoluteVolumeResponse::ToString() const { } } // namespace avrcp -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/packet/avrcp/set_addressed_player.cc b/system/packet/avrcp/set_addressed_player.cc index f760cadde12..2b4d66d63d1 100644 --- a/system/packet/avrcp/set_addressed_player.cc +++ b/system/packet/avrcp/set_addressed_player.cc @@ -16,6 +16,8 @@ #include "set_addressed_player.h" +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/packet/avrcp/set_player_application_setting_value.cc b/system/packet/avrcp/set_player_application_setting_value.cc index a01741ed7e6..03dfe434912 100644 --- a/system/packet/avrcp/set_player_application_setting_value.cc +++ b/system/packet/avrcp/set_player_application_setting_value.cc @@ -16,6 +16,8 @@ #include "set_player_application_setting_value.h" +#include "internal_include/bt_trace.h" + namespace bluetooth { namespace avrcp { diff --git a/system/profile/avrcp/avrcp_message_converter.h b/system/profile/avrcp/avrcp_message_converter.h index 724bc2739fe..384c83e7a67 100644 --- a/system/profile/avrcp/avrcp_message_converter.h +++ b/system/profile/avrcp/avrcp_message_converter.h @@ -21,6 +21,7 @@ #include #include +#include "internal_include/bt_trace.h" #include "packet/avrcp/avrcp_packet.h" #include "stack/include/bt_hdr.h" diff --git a/system/profile/avrcp/connection_handler.cc b/system/profile/avrcp/connection_handler.cc index b25e7938a50..6faf5cf0e70 100644 --- a/system/profile/avrcp/connection_handler.cc +++ b/system/profile/avrcp/connection_handler.cc @@ -638,7 +638,7 @@ void ConnectionHandler::RegisterVolChanged(const RawAddress& bdaddr) { bool ConnectionHandler::SdpLookupAudioRole(uint16_t handle) { if (device_map_.find(handle) == device_map_.end()) { - log::warn("No device found for handle: {}", loghex(handle)); + log::warn("No device found for handle: 0x{:x}", handle); return false; } auto device = device_map_[handle]; @@ -656,7 +656,7 @@ void ConnectionHandler::SdpLookupAudioRoleCb(uint16_t handle, bool found, tA2DP_Service* /*p_service*/, const RawAddress& /*peer_address*/) { if (device_map_.find(handle) == device_map_.end()) { - log::warn("No device found for handle: {}", loghex(handle)); + log::warn("No device found for handle: 0x{:x}", handle); return; } auto device = device_map_[handle]; diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index f334ab659de..d5496074524 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -1755,7 +1755,7 @@ static std::string volumeToStr(int8_t volume) { std::ostream& operator<<(std::ostream& out, const Device& d) { // TODO: whether this should be turned into LOGGABLE STRING? - out << " " << ADDRESS_TO_LOGGABLE_STR(d.address_); + out << " " << d.address_.ToRedactedStringForLogging(); if (d.IsActive()) { out << " "; } diff --git a/system/profile/sdp/sdp_logging_helper.h b/system/profile/sdp/sdp_logging_helper.h index 66aa6ae33ae..4a8d1782969 100644 --- a/system/profile/sdp/sdp_logging_helper.h +++ b/system/profile/sdp/sdp_logging_helper.h @@ -24,7 +24,6 @@ #include #include -#include "internal_include/bt_trace.h" #include "macros.h" #include "sdp_common.h" @@ -42,7 +41,7 @@ inline std::string PduIdText(const PduId& id) { CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_ATTRIBUTE_REQUEST); CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_ATTRIBUTE_RESPONSE); default: - return "Unknown PduId: " + loghex((uint8_t)id); + return fmt::format("Unknown PduId: 0x{:x}", (uint8_t)id); } } @@ -67,7 +66,7 @@ inline std::string AttributeIdText(const AttributeId& id) { CASE_RETURN_TEXT(AttributeId::VERSION_NUMBER_LIST); CASE_RETURN_TEXT(AttributeId::SERVICE_DATABASE_STATE); default: - return "Unknown AttributeId: " + loghex((uint16_t)id); + return fmt::format("Unknown AttributeId: 0x{:x}", (uint16_t)id); } } @@ -87,7 +86,7 @@ inline std::string DataElementTypeText(const DataElementType& type) { CASE_RETURN_TEXT(DataElementType::DATA_ELEMENT_ALTERNATIVE); CASE_RETURN_TEXT(DataElementType::URL); default: - return "Unknown DataElementType: " + loghex((uint8_t)type); + return fmt::format("Unknown DataElementType: 0x{:x}", (uint8_t)type); } } @@ -106,7 +105,7 @@ inline std::string DataElementSizeText(const DataElementSize& size) { CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_16BIT); CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_32BIT); default: - return "Unknown DataElementSize: " + loghex((uint8_t)size); + return fmt::format("Unknown DataElementSize: 0x{:x}", (uint8_t)size); } } diff --git a/system/stack/a2dp/a2dp_vendor.cc b/system/stack/a2dp/a2dp_vendor.cc index 84979bbff04..2057266d477 100644 --- a/system/stack/a2dp/a2dp_vendor.cc +++ b/system/stack/a2dp/a2dp_vendor.cc @@ -18,15 +18,16 @@ * Vendor Specific A2DP Codecs Support */ -#define LOG_TAG "a2dp_vendor" +#define LOG_TAG "bluetooth-a2dp" #include "a2dp_vendor.h" +#include + #include "a2dp_vendor_aptx.h" #include "a2dp_vendor_aptx_hd.h" #include "a2dp_vendor_ldac.h" #include "a2dp_vendor_opus.h" -#include "internal_include/bt_trace.h" #include "stack/include/bt_hdr.h" bool A2DP_IsVendorSourceCodecValid(const uint8_t* p_codec_info) { @@ -707,5 +708,5 @@ std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info) { // Add checks based on - return "Unsupported codec vendor_id: " + loghex(vendor_id) + " codec_id: " + loghex(codec_id); + return fmt::format("Unsupported codec vendor_id: 0x{:x} codec_id: 0x{:x}", vendor_id, codec_id); } diff --git a/system/stack/btm/btm_iso_impl.h b/system/stack/btm/btm_iso_impl.h index 6c5f0887136..ddebeb94399 100644 --- a/system/stack/btm/btm_iso_impl.h +++ b/system/stack/btm/btm_iso_impl.h @@ -17,19 +17,19 @@ #pragma once +#include +#include + #include #include #include #include -#include "base/functional/bind.h" -#include "base/functional/callback.h" #include "btm_dev.h" #include "btm_iso_api.h" #include "common/time_util.h" #include "hci/controller_interface.h" #include "hci/include/hci_layer.h" -#include "internal_include/bt_trace.h" #include "internal_include/stack_config.h" #include "main/shim/entry.h" #include "main/shim/hci_layer.h" @@ -417,7 +417,7 @@ struct iso_impl { void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) { iso_base* iso = GetIsoIfKnown(iso_handle); - log::assert_that(iso != nullptr, "No such iso connection: {}", loghex(iso_handle)); + log::assert_that(iso != nullptr, "No such iso connection: 0x{:x}", iso_handle); log::assert_that((iso->state_flags & kStateFlagHasDataPathSet) == kStateFlagHasDataPathSet, "Data path not set"); @@ -512,7 +512,7 @@ struct iso_impl { void send_iso_data(uint16_t iso_handle, const uint8_t* data, uint16_t data_len) { iso_base* iso = GetIsoIfKnown(iso_handle); - log::assert_that(iso != nullptr, "No such iso connection handle: {}", loghex(iso_handle)); + log::assert_that(iso != nullptr, "No such iso connection handle: 0x{:x}", iso_handle); if (!(iso->state_flags & kStateFlagIsBroadcast)) { if (!(iso->state_flags & kStateFlagIsConnected)) { -- GitLab From a314bc93696fef9e8b62fbd7a3600d6576ac3cfa Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Wed, 9 Oct 2024 14:20:33 -0700 Subject: [PATCH 261/875] add Gmap Server Bug: 350102910 Bug: 353978074 Test: atest --host bluetooth_le_audio_client_test Flag: com.android.bluetooth.flags.leaudio_gmap_client Change-Id: I9b2249eb1ef57f7ef56d8f654d6141b962b2a690 --- system/bta/Android.bp | 3 + system/bta/BUILD.gn | 1 + system/bta/gmap/gmap_server.cc | 278 ++++++++++++++++++++++++++++ system/bta/gmap/gmap_server_test.cc | 167 +++++++++++++++++ system/bta/le_audio/client.cc | 17 ++ system/bta/le_audio/gmap_server.h | 93 ++++++++++ 6 files changed, 559 insertions(+) create mode 100644 system/bta/gmap/gmap_server.cc create mode 100644 system/bta/gmap/gmap_server_test.cc create mode 100644 system/bta/le_audio/gmap_server.h diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 42ba31bcfd6..c84b6e3c92e 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -75,6 +75,7 @@ cc_library_static { "av/bta_av_ssm.cc", "csis/csis_client.cc", "gmap/gmap_client.cc", + "gmap/gmap_server.cc", "groups/groups.cc", "has/has_client.cc", "has/has_ctp.cc", @@ -980,6 +981,8 @@ cc_test { "gatt/database_builder.cc", "gmap/gmap_client.cc", "gmap/gmap_client_test.cc", + "gmap/gmap_server.cc", + "gmap/gmap_server_test.cc", "le_audio/broadcaster/broadcast_configuration_provider.cc", "le_audio/broadcaster/broadcaster_types.cc", "le_audio/client.cc", diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn index 49c014792a2..b328715d091 100644 --- a/system/bta/BUILD.gn +++ b/system/bta/BUILD.gn @@ -65,6 +65,7 @@ static_library("bta") { "gatt/database_builder.cc", "groups/groups.cc", "gmap/gmap_client.cc", + "gmap/gmap_server.cc", "has/has_client.cc", "has/has_ctp.cc", "has/has_preset.cc", diff --git a/system/bta/gmap/gmap_server.cc b/system/bta/gmap/gmap_server.cc new file mode 100644 index 00000000000..deb0e9cb3c6 --- /dev/null +++ b/system/bta/gmap/gmap_server.cc @@ -0,0 +1,278 @@ +/* + * Copyright (C) 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. + */ + +#include "bta/le_audio/gmap_server.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "bta/le_audio/le_audio_types.h" +#include "bta_gatt_api.h" +#include "bta_gatt_queue.h" +#include "bta_le_audio_uuids.h" +#include "btm_sec.h" +#include "gap_api.h" +#include "gatt_api.h" +#include "gd/hci/uuid.h" +#include "gd/os/rand.h" +#include "include/hardware/bt_gmap.h" +#include "internal_include/bt_trace.h" +#include "os/log.h" +#include "os/logging/log_adapter.h" +#include "osi/include/properties.h" +#include "stack/include/bt_types.h" +#include "stack/include/btm_ble_addr.h" + +using bluetooth::Uuid; +using namespace bluetooth; +using bluetooth::le_audio::GmapCharacteristic; +using bluetooth::le_audio::GmapServer; + +bool GmapServer::is_offloader_support_gmap_ = false; +uint16_t GmapServer::server_if_ = 0; +std::unordered_map GmapServer::characteristics_ = + std::unordered_map(); +// default role is UGG +std::bitset<8> GmapServer::role_ = 0b0001; +// AOSP's LE Audio source support multi-sink on default +std::bitset<8> GmapServer::UGG_feature_ = + static_cast(bluetooth::gmap::UGGFeatureBitMask::MultisinkFeatureSupport); + +bool GmapServer::IsGmapServerEnabled() { + // for UGG, both GMAP Server and Client are needed. So server and client share the same flag. + bool flag = com::android::bluetooth::flags::leaudio_gmap_client(); + bool system_prop = osi_property_get_bool("bluetooth.profile.gmap.enabled", false); + + bool result = flag && system_prop && is_offloader_support_gmap_; + log::info("GmapServerEnabled={}, flag={}, system_prop={}, offloader_support={}", result, + system_prop, flag, GmapServer::is_offloader_support_gmap_); + return result; +} + +void GmapServer::UpdateGmapOffloaderSupport(bool value) { + GmapServer::is_offloader_support_gmap_ = value; +} + +void GmapServer::DebugDump(int fd) { + std::stringstream stream; + stream << "GmapServer is enabled: " << IsGmapServerEnabled() << "\n"; + if (IsGmapServerEnabled()) { + stream << "GmapServer Role: " << role_ << ", UGG Feature: " << UGG_feature_ << "\n"; + } + + dprintf(fd, "%s", stream.str().c_str()); +} + +void GmapServer::Initialize(std::bitset<8> role, std::bitset<8> UGG_feature) { + GmapServer::role_ = role; + GmapServer::Initialize(UGG_feature); +} + +void GmapServer::Initialize(std::bitset<8> UGG_feature) { + GmapServer::UGG_feature_ = UGG_feature; + log::info("GmapServer initialized, role={}, UGG_feature={}", GmapServer::role_.to_string(), + UGG_feature.to_string()); + characteristics_.clear(); + + BTA_GATTS_AppRegister( + bluetooth::le_audio::uuid::kGamingAudioServiceUuid, + [](tBTA_GATTS_EVT event, tBTA_GATTS *p_data) { + if (p_data) { + GmapServer::GattsCallback(event, p_data); + } + }, + false); +} + +std::bitset<8> GmapServer::GetRole() { return GmapServer::role_; } + +uint16_t GmapServer::GetRoleHandle() { + for (auto &[attribute_handle, characteristic] : characteristics_) { + if (characteristic.uuid_ == bluetooth::le_audio::uuid::kRoleCharacteristicUuid) { + return attribute_handle; + } + } + log::warn("no valid UGG feature handle"); + return 0; +} + +std::bitset<8> GmapServer::GetUGGFeature() { return GmapServer::UGG_feature_; } + +uint16_t GmapServer::GetUGGFeatureHandle() { + for (auto &[attribute_handle, characteristic] : characteristics_) { + if (characteristic.uuid_ == bluetooth::le_audio::uuid::kUnicastGameGatewayCharacteristicUuid) { + return attribute_handle; + } + } + log::warn("no valid UGG feature handle"); + return 0; +} + +std::unordered_map &GmapServer::GetCharacteristics() { + return GmapServer::characteristics_; +} + +void GmapServer::GattsCallback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) { + log::info("event: {}", gatt_server_event_text(event)); + switch (event) { + case BTA_GATTS_CONNECT_EVT: { + OnGattConnect(p_data); + break; + } + case BTA_GATTS_DEREG_EVT: { + BTA_GATTS_AppDeregister(server_if_); + break; + } + case BTA_GATTS_DISCONNECT_EVT: { + OnGattDisconnect(p_data); + break; + } + case BTA_GATTS_REG_EVT: { + OnGattServerRegister(p_data); + break; + } + case BTA_GATTS_READ_CHARACTERISTIC_EVT: { + OnReadCharacteristic(p_data); + break; + } + default: + log::warn("Unhandled event {}", gatt_server_event_text(event)); + } +} + +void GmapServer::OnGattConnect(tBTA_GATTS *p_data) { + if (p_data == nullptr) { + log::warn("invalid p_data"); + } + auto address = p_data->conn.remote_bda; + log::info("Address: {}, conn_id:{}", address, p_data->conn.conn_id); + if (p_data->conn.transport == BT_TRANSPORT_BR_EDR) { + log::warn("Skip BE/EDR connection"); + return; + } +} + +void GmapServer::OnGattDisconnect(tBTA_GATTS *p_data) { + if (p_data == nullptr) { + log::warn("invalid p_data"); + } + auto address = p_data->conn.remote_bda; + log::info("Address: {}, conn_id:{}", address, p_data->conn.conn_id); +} + +void GmapServer::OnGattServerRegister(tBTA_GATTS *p_data) { + if (p_data == nullptr) { + log::warn("invalid p_data"); + } + tGATT_STATUS status = p_data->reg_oper.status; + log::info("status: {}", gatt_status_text(p_data->reg_oper.status)); + + if (status != tGATT_STATUS::GATT_SUCCESS) { + log::warn("Register Server fail"); + return; + } + server_if_ = p_data->reg_oper.server_if; + + std::vector service; + + // GMAP service + btgatt_db_element_t gmap_service; + gmap_service.uuid = bluetooth::le_audio::uuid::kGamingAudioServiceUuid; + gmap_service.type = BTGATT_DB_PRIMARY_SERVICE; + service.push_back(gmap_service); + + // GMAP role + btgatt_db_element_t role_characteristic; + role_characteristic.uuid = bluetooth::le_audio::uuid::kRoleCharacteristicUuid; + role_characteristic.type = BTGATT_DB_CHARACTERISTIC; + role_characteristic.properties = GATT_CHAR_PROP_BIT_READ; + role_characteristic.permissions = GATT_PERM_READ; + service.push_back(role_characteristic); + + // GMAP UGG feature + btgatt_db_element_t UGG_feature_characteristic; + UGG_feature_characteristic.uuid = + bluetooth::le_audio::uuid::kUnicastGameGatewayCharacteristicUuid; + UGG_feature_characteristic.type = BTGATT_DB_CHARACTERISTIC; + UGG_feature_characteristic.properties = GATT_CHAR_PROP_BIT_READ; + UGG_feature_characteristic.permissions = GATT_PERM_READ; + service.push_back(UGG_feature_characteristic); + + log::info("add service"); + BTA_GATTS_AddService(server_if_, service, + base::BindRepeating([](tGATT_STATUS status, int server_if, + std::vector service) { + OnServiceAdded(status, server_if, service); + })); +} + +void GmapServer::OnServiceAdded(tGATT_STATUS status, int server_if, + std::vector services) { + log::info("status: {}, server_if: {}", gatt_status_text(status), server_if); + for (const auto &service : services) { + uint16_t attribute_handle = service.attribute_handle; + Uuid uuid = service.uuid; + if (service.type == BTGATT_DB_CHARACTERISTIC) { + log::info("Characteristic uuid: 0x{:04x}, handle:0x{:04x}", uuid.As16Bit(), attribute_handle); + GmapCharacteristic characteristic{.uuid_ = uuid, .attribute_handle_ = attribute_handle}; + characteristics_[attribute_handle] = characteristic; + } + } +} + +void GmapServer::OnReadCharacteristic(tBTA_GATTS *p_data) { + uint16_t read_req_handle = p_data->req_data.p_data->read_req.handle; + log::info("read_req_handle: 0x{:04x},", read_req_handle); + + tGATTS_RSP p_msg; + p_msg.attr_value.handle = read_req_handle; + auto it = characteristics_.find(read_req_handle); + if (it == characteristics_.end()) { + log::error("Invalid handle 0x{:04x}", read_req_handle); + BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_INVALID_HANDLE, + &p_msg); + return; + } + + auto uuid = it->second.uuid_; + + log::info("Read uuid, 0x{:04x}", uuid.As16Bit()); + // Check Characteristic UUID + if (bluetooth::le_audio::uuid::kRoleCharacteristicUuid == uuid) { + p_msg.attr_value.len = GmapServer::kGmapRoleLen; + auto role = GmapServer::GetRole(); + p_msg.attr_value.value[0] = static_cast(role.to_ulong()); + } else if (bluetooth::le_audio::uuid::kUnicastGameGatewayCharacteristicUuid == uuid) { + p_msg.attr_value.len = GmapServer::kGmapUGGFeatureLen; + auto UGGFeature = GmapServer::GetUGGFeature(); + p_msg.attr_value.value[0] = static_cast(UGGFeature.to_ulong()); + } else { + log::warn("Unhandled uuid {}", uuid.ToString()); + BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_ILLEGAL_PARAMETER, + &p_msg); + return; + } + + BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); +} diff --git a/system/bta/gmap/gmap_server_test.cc b/system/bta/gmap/gmap_server_test.cc new file mode 100644 index 00000000000..12a197cd5d2 --- /dev/null +++ b/system/bta/gmap/gmap_server_test.cc @@ -0,0 +1,167 @@ +/* + * Copyright (C) 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. + */ + +#include "bta/le_audio/gmap_server.h" + +#include +#include +#include +#include + +#include "bta/le_audio/le_audio_types.h" +#include "bta_gatt_api_mock.h" +#include "test/common/mock_functions.h" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::DoAll; +using ::testing::DoDefault; +using ::testing::Invoke; +using ::testing::Mock; +using ::testing::NotNull; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::Sequence; +using ::testing::SetArgPointee; +using ::testing::WithArg; + +using ::testing::NiceMock; + +using bluetooth::Uuid; +using namespace bluetooth; +using bluetooth::le_audio::GmapCharacteristic; +using bluetooth::le_audio::GmapServer; + +class GmapServerTest : public ::testing::Test { +public: + RawAddress addr = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); + NiceMock gatt_server_interface; + uint8_t role = 0b1; + uint8_t UGG_feature = 0b111; + + void SetUp(void) override { + reset_mock_function_count_map(); + gatt::SetMockBtaGattServerInterface(&gatt_server_interface); + EXPECT_CALL(gatt_server_interface, AppRegister(_, _, _)).Times(1); + GmapServer::Initialize(role, UGG_feature); + } +}; + +TEST_F(GmapServerTest, test_get_role) { ASSERT_EQ(GmapServer::GetRole(), role); } + +TEST_F(GmapServerTest, test_get_UGG_feature) { + ASSERT_EQ(GmapServer::GetUGGFeature(), UGG_feature); +} + +TEST_F(GmapServerTest, test_add_service) { + tBTA_GATTS gatts_cb_data; + uint8_t server_if = 10; + gatts_cb_data.reg_oper.status = GATT_SUCCESS; + gatts_cb_data.reg_oper.server_if = server_if; + + EXPECT_CALL(gatt_server_interface, AddService(_, _, _)).Times(1); + GmapServer::GattsCallback(BTA_GATTS_REG_EVT, &gatts_cb_data); +} + +TEST_F(GmapServerTest, test_app_deregister) { + tBTA_GATTS gatts_cb_data; + EXPECT_CALL(gatt_server_interface, AppDeregister(_)).Times(1); + GmapServer::GattsCallback(BTA_GATTS_DEREG_EVT, &gatts_cb_data); +} + +TEST_F(GmapServerTest, test_read_invalid_characteristic) { + uint16_t handle = 10; + tGATTS_DATA gatts_data; + gatts_data.read_req.handle = handle; + tBTA_GATTS gatts_cb_data; + gatts_cb_data.req_data.p_data = &gatts_data; + + EXPECT_CALL(gatt_server_interface, SendRsp(_, _, GATT_INVALID_HANDLE, _)).Times(1); + GmapServer::GattsCallback(BTA_GATTS_READ_CHARACTERISTIC_EVT, &gatts_cb_data); +} + +TEST_F(GmapServerTest, test_read_invalid_role_characteristic) { + uint16_t handle = 10; + GmapCharacteristic invalidGmapCharacteristic{ + .uuid_ = bluetooth::le_audio::uuid::kTelephonyMediaAudioProfileRoleCharacteristicUuid, + .attribute_handle_ = handle}; + GmapServer::GetCharacteristics()[handle] = invalidGmapCharacteristic; + + tGATTS_DATA gatts_data; + gatts_data.read_req.handle = handle; + tBTA_GATTS gatts_cb_data; + gatts_cb_data.req_data.p_data = &gatts_data; + + EXPECT_CALL(gatt_server_interface, SendRsp(_, _, GATT_ILLEGAL_PARAMETER, _)).Times(1); + GmapServer::GattsCallback(BTA_GATTS_READ_CHARACTERISTIC_EVT, &gatts_cb_data); +} + +TEST_F(GmapServerTest, test_read_valid_role_characteristic) { + uint16_t handle = 10; + GmapCharacteristic gmapCharacteristic{.uuid_ = bluetooth::le_audio::uuid::kRoleCharacteristicUuid, + .attribute_handle_ = handle}; + GmapServer::GetCharacteristics()[handle] = gmapCharacteristic; + + tGATTS_DATA gatts_data; + gatts_data.read_req.handle = handle; + tBTA_GATTS gatts_cb_data; + gatts_cb_data.req_data.p_data = &gatts_data; + + EXPECT_CALL(gatt_server_interface, SendRsp(_, _, GATT_SUCCESS, _)).Times(1); + GmapServer::GattsCallback(BTA_GATTS_READ_CHARACTERISTIC_EVT, &gatts_cb_data); +} + +TEST_F(GmapServerTest, test_read_valid_ugg_feature_characteristic) { + uint16_t handle = 10; + GmapCharacteristic gmapCharacteristic{ + .uuid_ = bluetooth::le_audio::uuid::kUnicastGameGatewayCharacteristicUuid, + .attribute_handle_ = handle}; + GmapServer::GetCharacteristics()[handle] = gmapCharacteristic; + + tGATTS_DATA gatts_data; + gatts_data.read_req.handle = handle; + tBTA_GATTS gatts_cb_data; + gatts_cb_data.req_data.p_data = &gatts_data; + + EXPECT_CALL(gatt_server_interface, SendRsp(_, _, GATT_SUCCESS, _)).Times(1); + GmapServer::GattsCallback(BTA_GATTS_READ_CHARACTERISTIC_EVT, &gatts_cb_data); +} + +TEST_F(GmapServerTest, test_get_UGG_feature_handle) { + uint16_t handle = 10; + GmapCharacteristic gmapCharacteristic{ + .uuid_ = bluetooth::le_audio::uuid::kUnicastGameGatewayCharacteristicUuid, + .attribute_handle_ = handle}; + GmapServer::GetCharacteristics()[handle] = gmapCharacteristic; + + ASSERT_EQ(GmapServer::GetUGGFeatureHandle(), handle); +} + +TEST_F(GmapServerTest, test_read_invalid_UGG_feature_handle) { + uint16_t handle = 10; + GmapServer::GetCharacteristics().clear(); + + ASSERT_NE(GmapServer::GetUGGFeatureHandle(), handle); +} + +TEST_F(GmapServerTest, test_get_role_handle) { + uint16_t handle = 10; + GmapCharacteristic gmapCharacteristic{.uuid_ = bluetooth::le_audio::uuid::kRoleCharacteristicUuid, + .attribute_handle_ = handle}; + GmapServer::GetCharacteristics()[handle] = gmapCharacteristic; + + ASSERT_EQ(GmapServer::GetRoleHandle(), handle); +} diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 3102489aaa3..0a1c8dca6bf 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -46,6 +46,7 @@ #include "devices.h" #include "gatt_api.h" #include "gmap_client.h" +#include "gmap_server.h" #include "hci/controller_interface.h" #include "include/hardware/bt_gmap.h" #include "internal_include/stack_config.h" @@ -87,7 +88,9 @@ using bluetooth::le_audio::ContentControlIdKeeper; using bluetooth::le_audio::DeviceConnectState; using bluetooth::le_audio::DsaMode; using bluetooth::le_audio::DsaModes; +using bluetooth::le_audio::GmapCharacteristic; using bluetooth::le_audio::GmapClient; +using bluetooth::le_audio::GmapServer; using bluetooth::le_audio::GroupNodeStatus; using bluetooth::le_audio::GroupStatus; using bluetooth::le_audio::GroupStreamStatus; @@ -121,6 +124,7 @@ using bluetooth::le_audio::types::LeAudioContextType; using bluetooth::le_audio::types::PublishedAudioCapabilities; using bluetooth::le_audio::utils::GetAudioContextsFromSinkMetadata; using bluetooth::le_audio::utils::GetAudioContextsFromSourceMetadata; + using namespace bluetooth; /* Enums */ @@ -6152,6 +6156,19 @@ void LeAudioClient::Initialize( auto cm = CodecManager::GetInstance(); callbacks_->OnAudioLocalCodecCapabilities(cm->GetLocalAudioInputCodecCapa(), cm->GetLocalAudioOutputCodecCapa()); + + if (GmapServer::IsGmapServerEnabled()) { + auto capabilities = cm->GetLocalAudioOutputCodecCapa(); + std::bitset<8> UGG_feature = GmapServer::GetUGGFeature(); + for (auto& capa : capabilities) { + if (capa.sample_rate == bluetooth::le_audio::LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ) { + UGG_feature |= static_cast( + bluetooth::gmap::UGGFeatureBitMask::NinetySixKbpsSourceFeatureSupport); + break; + } + } + GmapServer::Initialize(UGG_feature); + } } void LeAudioClient::DebugDump(int fd) { diff --git a/system/bta/le_audio/gmap_server.h b/system/bta/le_audio/gmap_server.h new file mode 100644 index 00000000000..3fc3e14dd6c --- /dev/null +++ b/system/bta/le_audio/gmap_server.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 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 +#include +#include + +#include +#include + +namespace bluetooth::le_audio { +struct GmapCharacteristic { + bluetooth::Uuid uuid_; + uint16_t attribute_handle_; +}; + +/** + * As there is only 1 Gaming Audio Server, so here uses static function + */ +class GmapServer { +public: + static void DebugDump(int fd); + + /** + * UGG, UGT, and BGR devices supporting GMAP shall implement the GATT Server role + * and instantiate only one GMA Server. + * BGS-only devices are not required by GMAP to implement the GATT Server role. + * @return true if GMAP Server is enabled + */ + static bool IsGmapServerEnabled(); + + static void UpdateGmapOffloaderSupport(bool value); + + static void Initialize(std::bitset<8> role, std::bitset<8> UGG_feature); + + static void Initialize(std::bitset<8> UGG_feature); + + static std::bitset<8> GetRole(); + + static uint16_t GetRoleHandle(); + + static std::bitset<8> GetUGGFeature(); + + static uint16_t GetUGGFeatureHandle(); + + /** + * This function is used only for testing + */ + static void GattsCallback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data); + + /** + * This function is used only for testing + * @return an unordered_map whose key is attribute_handle_ and value is GmapCharacteristic + */ + static std::unordered_map &GetCharacteristics(); + + constexpr static uint16_t kGmapRoleLen = 1; + constexpr static uint16_t kGmapUGGFeatureLen = 1; + +private: + static void OnGattConnect(tBTA_GATTS *p_data); + + static void OnGattDisconnect(tBTA_GATTS *p_data); + + static void OnGattServerRegister(tBTA_GATTS *p_data); + + static void OnServiceAdded(tGATT_STATUS status, int server_if, + std::vector services); + + static void OnReadCharacteristic(tBTA_GATTS *p_data); + + static bool is_offloader_support_gmap_; + static uint16_t server_if_; + static std::unordered_map characteristics_; + static std::bitset<8> role_; + static std::bitset<8> UGG_feature_; +}; +} // namespace bluetooth::le_audio -- GitLab From b7fa19733a1ee7e5a15bbbf363ca41de6b742888 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 10 Oct 2024 16:56:53 -0700 Subject: [PATCH 262/875] AndroidLint: resolve ExtraTranslation strings lint This CL remove unused translation. This result in removing all these lint: 21 id="StringFormatInvalid" 84 id="DuplicateDefinition" 1092 id="ExtraTranslation" DuplicateDefinition and StringFormatInvalid are a side effect of the removal of ExtraTranslation Bug: 289445022 Bug: 372738580 Test: m Bluetooth & regenerate lint-baseline Flag: Exempt dead code removal in resource Change-Id: I1eacac696dc6f7c2f0935bd20ecf46932d753386 --- android/app/lint-baseline.xml | 23979 ++++------------ android/app/res/values-af/strings.xml | 5 - android/app/res/values-af/test_strings.xml | 13 - android/app/res/values-am/strings.xml | 5 - android/app/res/values-am/test_strings.xml | 13 - android/app/res/values-ar/strings.xml | 5 - android/app/res/values-ar/test_strings.xml | 13 - android/app/res/values-as/strings.xml | 5 - android/app/res/values-as/test_strings.xml | 13 - android/app/res/values-az/strings.xml | 5 - android/app/res/values-az/test_strings.xml | 13 - android/app/res/values-b+sr+Latn/strings.xml | 5 - .../app/res/values-b+sr+Latn/test_strings.xml | 13 - android/app/res/values-be/strings.xml | 5 - android/app/res/values-be/test_strings.xml | 13 - android/app/res/values-bg/strings.xml | 5 - android/app/res/values-bg/test_strings.xml | 13 - android/app/res/values-bn/strings.xml | 5 - android/app/res/values-bn/test_strings.xml | 13 - android/app/res/values-bs/strings.xml | 5 - android/app/res/values-bs/test_strings.xml | 13 - android/app/res/values-ca/strings.xml | 5 - android/app/res/values-ca/test_strings.xml | 13 - android/app/res/values-cs/strings.xml | 5 - android/app/res/values-cs/test_strings.xml | 13 - android/app/res/values-da/strings.xml | 5 - android/app/res/values-da/test_strings.xml | 13 - android/app/res/values-de/strings.xml | 5 - android/app/res/values-de/test_strings.xml | 13 - android/app/res/values-el/strings.xml | 5 - android/app/res/values-el/test_strings.xml | 13 - android/app/res/values-en-rAU/strings.xml | 5 - .../app/res/values-en-rAU/test_strings.xml | 13 - android/app/res/values-en-rCA/strings.xml | 5 - .../app/res/values-en-rCA/test_strings.xml | 13 - android/app/res/values-en-rGB/strings.xml | 5 - .../app/res/values-en-rGB/test_strings.xml | 13 - android/app/res/values-en-rIN/strings.xml | 5 - .../app/res/values-en-rIN/test_strings.xml | 13 - android/app/res/values-en-rXC/strings.xml | 5 - .../app/res/values-en-rXC/test_strings.xml | 13 - android/app/res/values-es-rUS/strings.xml | 5 - .../app/res/values-es-rUS/test_strings.xml | 13 - android/app/res/values-es/strings.xml | 5 - android/app/res/values-es/test_strings.xml | 13 - android/app/res/values-et/strings.xml | 5 - android/app/res/values-et/test_strings.xml | 13 - android/app/res/values-eu/strings.xml | 5 - android/app/res/values-eu/test_strings.xml | 13 - android/app/res/values-fa/strings.xml | 5 - android/app/res/values-fa/test_strings.xml | 13 - android/app/res/values-fi/strings.xml | 5 - android/app/res/values-fi/test_strings.xml | 13 - android/app/res/values-fr-rCA/strings.xml | 5 - .../app/res/values-fr-rCA/test_strings.xml | 13 - android/app/res/values-fr/strings.xml | 5 - android/app/res/values-fr/test_strings.xml | 13 - android/app/res/values-gl/strings.xml | 5 - android/app/res/values-gl/test_strings.xml | 13 - android/app/res/values-gu/strings.xml | 5 - android/app/res/values-gu/test_strings.xml | 13 - android/app/res/values-hi/strings.xml | 5 - android/app/res/values-hi/test_strings.xml | 13 - android/app/res/values-hr/strings.xml | 5 - android/app/res/values-hr/test_strings.xml | 13 - android/app/res/values-hu/strings.xml | 5 - android/app/res/values-hu/test_strings.xml | 13 - android/app/res/values-hy/strings.xml | 5 - android/app/res/values-hy/test_strings.xml | 13 - android/app/res/values-in/strings.xml | 5 - android/app/res/values-in/test_strings.xml | 13 - android/app/res/values-is/strings.xml | 5 - android/app/res/values-is/test_strings.xml | 13 - android/app/res/values-it/strings.xml | 5 - android/app/res/values-it/test_strings.xml | 13 - android/app/res/values-iw/strings.xml | 5 - android/app/res/values-iw/test_strings.xml | 13 - android/app/res/values-ja/strings.xml | 5 - android/app/res/values-ja/test_strings.xml | 13 - android/app/res/values-ka/strings.xml | 5 - android/app/res/values-ka/test_strings.xml | 13 - android/app/res/values-kk/strings.xml | 5 - android/app/res/values-kk/test_strings.xml | 13 - android/app/res/values-km/strings.xml | 5 - android/app/res/values-km/test_strings.xml | 13 - android/app/res/values-kn/strings.xml | 5 - android/app/res/values-kn/test_strings.xml | 13 - android/app/res/values-ko/strings.xml | 5 - android/app/res/values-ko/test_strings.xml | 13 - android/app/res/values-ky/strings.xml | 5 - android/app/res/values-ky/test_strings.xml | 13 - android/app/res/values-lo/strings.xml | 5 - android/app/res/values-lo/test_strings.xml | 13 - android/app/res/values-lt/strings.xml | 5 - android/app/res/values-lt/test_strings.xml | 13 - android/app/res/values-lv/strings.xml | 5 - android/app/res/values-lv/test_strings.xml | 13 - android/app/res/values-mk/strings.xml | 5 - android/app/res/values-mk/test_strings.xml | 13 - android/app/res/values-ml/strings.xml | 5 - android/app/res/values-ml/test_strings.xml | 13 - android/app/res/values-mn/strings.xml | 5 - android/app/res/values-mn/test_strings.xml | 13 - android/app/res/values-mr/strings.xml | 5 - android/app/res/values-mr/test_strings.xml | 13 - android/app/res/values-ms/strings.xml | 5 - android/app/res/values-ms/test_strings.xml | 13 - android/app/res/values-my/strings.xml | 5 - android/app/res/values-my/test_strings.xml | 13 - android/app/res/values-nb/strings.xml | 5 - android/app/res/values-nb/test_strings.xml | 13 - android/app/res/values-ne/strings.xml | 5 - android/app/res/values-ne/test_strings.xml | 13 - android/app/res/values-nl/strings.xml | 5 - android/app/res/values-nl/test_strings.xml | 13 - android/app/res/values-or/strings.xml | 5 - android/app/res/values-or/test_strings.xml | 13 - android/app/res/values-pa/strings.xml | 5 - android/app/res/values-pa/test_strings.xml | 13 - android/app/res/values-pl/strings.xml | 5 - android/app/res/values-pl/test_strings.xml | 13 - android/app/res/values-pt-rPT/strings.xml | 5 - .../app/res/values-pt-rPT/test_strings.xml | 13 - android/app/res/values-pt/strings.xml | 5 - android/app/res/values-pt/test_strings.xml | 13 - android/app/res/values-ro/strings.xml | 5 - android/app/res/values-ro/test_strings.xml | 13 - android/app/res/values-ru/strings.xml | 5 - android/app/res/values-ru/test_strings.xml | 13 - android/app/res/values-si/strings.xml | 5 - android/app/res/values-si/test_strings.xml | 13 - android/app/res/values-sk/strings.xml | 5 - android/app/res/values-sk/test_strings.xml | 13 - android/app/res/values-sl/strings.xml | 5 - android/app/res/values-sl/test_strings.xml | 13 - android/app/res/values-sq/strings.xml | 5 - android/app/res/values-sq/test_strings.xml | 13 - android/app/res/values-sr/strings.xml | 5 - android/app/res/values-sr/test_strings.xml | 13 - android/app/res/values-sv/strings.xml | 5 - android/app/res/values-sv/test_strings.xml | 13 - android/app/res/values-sw/strings.xml | 5 - android/app/res/values-sw/test_strings.xml | 13 - android/app/res/values-ta/strings.xml | 5 - android/app/res/values-ta/test_strings.xml | 13 - android/app/res/values-te/strings.xml | 5 - android/app/res/values-te/test_strings.xml | 13 - android/app/res/values-th/strings.xml | 5 - android/app/res/values-th/test_strings.xml | 13 - android/app/res/values-tl/strings.xml | 5 - android/app/res/values-tl/test_strings.xml | 13 - android/app/res/values-tr/strings.xml | 5 - android/app/res/values-tr/test_strings.xml | 13 - android/app/res/values-uk/strings.xml | 5 - android/app/res/values-uk/test_strings.xml | 13 - android/app/res/values-ur/strings.xml | 5 - android/app/res/values-ur/test_strings.xml | 13 - android/app/res/values-uz/strings.xml | 5 - android/app/res/values-uz/test_strings.xml | 13 - android/app/res/values-vi/strings.xml | 5 - android/app/res/values-vi/test_strings.xml | 13 - android/app/res/values-zh-rCN/strings.xml | 5 - .../app/res/values-zh-rCN/test_strings.xml | 13 - android/app/res/values-zh-rHK/strings.xml | 5 - .../app/res/values-zh-rHK/test_strings.xml | 13 - android/app/res/values-zh-rTW/strings.xml | 5 - .../app/res/values-zh-rTW/test_strings.xml | 13 - android/app/res/values-zu/strings.xml | 5 - android/app/res/values-zu/test_strings.xml | 13 - .../tests/unit/res/values/test_strings.xml | 16 +- 170 files changed, 5204 insertions(+), 20303 deletions(-) delete mode 100644 android/app/res/values-af/test_strings.xml delete mode 100644 android/app/res/values-am/test_strings.xml delete mode 100644 android/app/res/values-ar/test_strings.xml delete mode 100644 android/app/res/values-as/test_strings.xml delete mode 100644 android/app/res/values-az/test_strings.xml delete mode 100644 android/app/res/values-b+sr+Latn/test_strings.xml delete mode 100644 android/app/res/values-be/test_strings.xml delete mode 100644 android/app/res/values-bg/test_strings.xml delete mode 100644 android/app/res/values-bn/test_strings.xml delete mode 100644 android/app/res/values-bs/test_strings.xml delete mode 100644 android/app/res/values-ca/test_strings.xml delete mode 100644 android/app/res/values-cs/test_strings.xml delete mode 100644 android/app/res/values-da/test_strings.xml delete mode 100644 android/app/res/values-de/test_strings.xml delete mode 100644 android/app/res/values-el/test_strings.xml delete mode 100644 android/app/res/values-en-rAU/test_strings.xml delete mode 100644 android/app/res/values-en-rCA/test_strings.xml delete mode 100644 android/app/res/values-en-rGB/test_strings.xml delete mode 100644 android/app/res/values-en-rIN/test_strings.xml delete mode 100644 android/app/res/values-en-rXC/test_strings.xml delete mode 100644 android/app/res/values-es-rUS/test_strings.xml delete mode 100644 android/app/res/values-es/test_strings.xml delete mode 100644 android/app/res/values-et/test_strings.xml delete mode 100644 android/app/res/values-eu/test_strings.xml delete mode 100644 android/app/res/values-fa/test_strings.xml delete mode 100644 android/app/res/values-fi/test_strings.xml delete mode 100644 android/app/res/values-fr-rCA/test_strings.xml delete mode 100644 android/app/res/values-fr/test_strings.xml delete mode 100644 android/app/res/values-gl/test_strings.xml delete mode 100644 android/app/res/values-gu/test_strings.xml delete mode 100644 android/app/res/values-hi/test_strings.xml delete mode 100644 android/app/res/values-hr/test_strings.xml delete mode 100644 android/app/res/values-hu/test_strings.xml delete mode 100644 android/app/res/values-hy/test_strings.xml delete mode 100644 android/app/res/values-in/test_strings.xml delete mode 100644 android/app/res/values-is/test_strings.xml delete mode 100644 android/app/res/values-it/test_strings.xml delete mode 100644 android/app/res/values-iw/test_strings.xml delete mode 100644 android/app/res/values-ja/test_strings.xml delete mode 100644 android/app/res/values-ka/test_strings.xml delete mode 100644 android/app/res/values-kk/test_strings.xml delete mode 100644 android/app/res/values-km/test_strings.xml delete mode 100644 android/app/res/values-kn/test_strings.xml delete mode 100644 android/app/res/values-ko/test_strings.xml delete mode 100644 android/app/res/values-ky/test_strings.xml delete mode 100644 android/app/res/values-lo/test_strings.xml delete mode 100644 android/app/res/values-lt/test_strings.xml delete mode 100644 android/app/res/values-lv/test_strings.xml delete mode 100644 android/app/res/values-mk/test_strings.xml delete mode 100644 android/app/res/values-ml/test_strings.xml delete mode 100644 android/app/res/values-mn/test_strings.xml delete mode 100644 android/app/res/values-mr/test_strings.xml delete mode 100644 android/app/res/values-ms/test_strings.xml delete mode 100644 android/app/res/values-my/test_strings.xml delete mode 100644 android/app/res/values-nb/test_strings.xml delete mode 100644 android/app/res/values-ne/test_strings.xml delete mode 100644 android/app/res/values-nl/test_strings.xml delete mode 100644 android/app/res/values-or/test_strings.xml delete mode 100644 android/app/res/values-pa/test_strings.xml delete mode 100644 android/app/res/values-pl/test_strings.xml delete mode 100644 android/app/res/values-pt-rPT/test_strings.xml delete mode 100644 android/app/res/values-pt/test_strings.xml delete mode 100644 android/app/res/values-ro/test_strings.xml delete mode 100644 android/app/res/values-ru/test_strings.xml delete mode 100644 android/app/res/values-si/test_strings.xml delete mode 100644 android/app/res/values-sk/test_strings.xml delete mode 100644 android/app/res/values-sl/test_strings.xml delete mode 100644 android/app/res/values-sq/test_strings.xml delete mode 100644 android/app/res/values-sr/test_strings.xml delete mode 100644 android/app/res/values-sv/test_strings.xml delete mode 100644 android/app/res/values-sw/test_strings.xml delete mode 100644 android/app/res/values-ta/test_strings.xml delete mode 100644 android/app/res/values-te/test_strings.xml delete mode 100644 android/app/res/values-th/test_strings.xml delete mode 100644 android/app/res/values-tl/test_strings.xml delete mode 100644 android/app/res/values-tr/test_strings.xml delete mode 100644 android/app/res/values-uk/test_strings.xml delete mode 100644 android/app/res/values-ur/test_strings.xml delete mode 100644 android/app/res/values-uz/test_strings.xml delete mode 100644 android/app/res/values-vi/test_strings.xml delete mode 100644 android/app/res/values-zh-rCN/test_strings.xml delete mode 100644 android/app/res/values-zh-rHK/test_strings.xml delete mode 100644 android/app/res/values-zh-rTW/test_strings.xml delete mode 100644 android/app/res/values-zu/test_strings.xml diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml index 5b716a7eb66..1b2c4fed02e 100644 --- a/android/app/lint-baseline.xml +++ b/android/app/lint-baseline.xml @@ -101,21554 +101,7967 @@ - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" ThreadLocal.withInitial(() -> new SimpleDateFormat("MM-dd HH:mm:ss"));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java" + line="51" + column="43"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1229" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1240" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1251" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1262" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1277" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1288" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1295" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1306" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1511" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1522" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1759" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" + line="1770" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java" + line="161" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java" + line="172" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java" + line="149" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java" + line="162" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java" + line="82" + column="35"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java" + line="385" + column="39"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" ? new SimpleDateFormat("yyyyMMdd'T'HHmmssZ")" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java" + line="745" + column="27"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" : new SimpleDateFormat("yyyyMMdd'T'HHmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java" + line="746" + column="27"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" DateFormat dateFormat = new SimpleDateFormat("_hhmmss");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java" + line="167" + column="33"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat df = new SimpleDateFormat(RFC_2455_FORMAT);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java" + line="226" + column="31"/> - + id="SimpleDateFormat" + message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." + errorLine1=" SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbapclient/CallLogPullRequest.java" + line="105" + column="43"/> - + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.DEBUG)) {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java" + line="734" + column="9"/> - + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.DEBUG)) {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java" + line="734" + column="9"/> - + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.DEBUG)) {" + errorLine2=" ^"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java" + line="734" + column="9"/> + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.VERBOSE)) {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" + line="824" + column="9"/> + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.VERBOSE)) {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" + line="824" + column="9"/> - + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.VERBOSE)) {" + errorLine2=" ^"> + + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.VERBOSE)) {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" + line="824" + column="9"/> + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.DEBUG)) {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java" + line="918" + column="9"/> + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.VERBOSE)) {" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppProvider.java" + line="398" + column="9"/> + id="GuardedLogInvocation" + message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" + errorLine1=" if (Log.isLoggable(TAG, Log.DEBUG)) {" + errorLine2=" ^"> + id="InflateParams" + message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)" + errorLine1=" View view = getLayoutInflater().inflate(R.layout.confirm_dialog, null);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivity.java" + line="71" + column="74"/> + id="InflateParams" + message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)" + errorLine1=" View view = getLayoutInflater().inflate(R.layout.bt_enabling_progress, null);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java" + line="92" + column="80"/> + id="InflateParams" + message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)" + errorLine1=" View view = getLayoutInflater().inflate(R.layout.confirm_dialog, null);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppBtErrorActivity.java" + line="66" + column="74"/> + id="InflateParams" + message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)" + errorLine1=" View view = getLayoutInflater().inflate(R.layout.incoming_dialog, null);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java" + line="139" + column="75"/> + id="InflateParams" + message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)" + errorLine1=" mView = getLayoutInflater().inflate(R.layout.file_transfer, null);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java" + line="240" + column="69"/> + id="InflateParams" + message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)" + errorLine1=" mView = getLayoutInflater().inflate(R.layout.auth, null);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java" + line="152" + column="68"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" + line="673" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return mDatabaseManager.getA2dpSupportsOptionalCodecs(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" + line="847" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setA2dpSupportsOptionalCodecs(device, value);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" + line="855" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return mDatabaseManager.getA2dpOptionalCodecsEnabled(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" + line="868" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setA2dpOptionalCodecsEnabled(device, value);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" + line="888" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.sendMessage(A2dpStateMachine.STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" + line="963" + column="45"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java" + line="477" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Config.setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, false);" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="1190" + column="20"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Config.setProfileEnabled(profileId, false);" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="1195" + column="20"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mMapService = BluetoothMapService.getBluetoothMapService();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="2025" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mPbapService = BluetoothPbapService.getBluetoothPbapService();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="2030" + column="45"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSapService = SapService.getSapService();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="2034" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return mDatabaseManager.setCustomMeta(device, key, value);" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="2266" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mRemoteDevices.resetBatteryLevel(device, isBas);" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="6876" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mRemoteDevices.updateBatteryLevel(device, batteryLevel, isBas);" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" + line="6878" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="182" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseString(device, atCommandResponse);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="203" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="205" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseString(device, atCommandResponse);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="274" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="276" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="299" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseString(remoteDevice, atCommandResponse);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="314" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(remoteDevice, atCommandResult, atCommandErrorCode);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="315" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="326" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="334" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="354" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="367" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="373" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(remoteDevice, atCommandResult, atCommandErrorCode);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="387" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseString(device, atCommandResponse);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" + line="640" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.onConnectionStateChanged(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="131" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handlePlayerAppSetting(device, playerAttribRsp, rspLen);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="149" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleSetAbsVolume(device, absVol, label);" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="165" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleRegisterNotificationAbsVol(device, label);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="173" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.onTrackChanged(device, numAttributes, attributes, attribVals);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="181" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.onPlayPositionChanged(device, songLen, currSongPosition);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="189" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.onPlayStatusChanged(device, toPlaybackStateFromJni(playStatus));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="197" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleChangeFolderRsp(device, count);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="303" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleSetBrowsedPlayerRsp(device, items, depth);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="310" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleSetAddressedPlayerRsp(device, status);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="317" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleAddressedPlayerChanged(device, id);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="324" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleNowPlayingContentChanged(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="330" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.onAvailablePlayerChanged(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="336" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private final Map<BluetoothDevice, BassClientStateMachine> mStateMachines = new HashMap<>();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="148" + column="40"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .anyMatch(e -> e.first.equals(BassClientStateMachine.ADD_BCAST_SOURCE));" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="852" + column="82"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case BassClientStateMachine.ADD_BCAST_SOURCE:" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="878" + column="41"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .ADD_BCAST_SOURCE))" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="891" + column="70"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" (m.first.equals(BassClientStateMachine.ADD_BCAST_SOURCE))" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="903" + column="76"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case BassClientStateMachine.REMOVE_BCAST_SOURCE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="921" + column="41"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" m.first.equals(BassClientStateMachine.REMOVE_BCAST_SOURCE)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="926" + column="71"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="969" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && (sm.hasPendingSwitchingSourceOperation()" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="973" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || sm.hasPendingSourceOperation())) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="974" + column="39"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.getCurrentBroadcastMetadata(sourceId);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1144" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" getOrCreateStateMachine(device).getAllSources();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1150" + column="61"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = null;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1227" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" for (BluetoothLeBroadcastReceiveState recvState : stateMachine.getAllSources()) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1236" + column="72"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = null;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1247" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" List<BluetoothLeBroadcastReceiveState> sources = stateMachine.getAllSources();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1256" + column="71"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private BassClientStateMachine getOrCreateStateMachine(BluetoothDevice device) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = mStateMachines.get(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine sm = mStateMachines.get(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.doQuit();" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1367" + column="16"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.cleanup();" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1368" + column="16"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1404" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.sendMessage(BassClientStateMachine.STOP_SCAN_OFFLOAD);" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1413" + column="65"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine," + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (stateMachine.hasPendingSourceOperation()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1449" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.sendMessage(BassClientStateMachine.CONNECT);" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1565" + column="61"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.sendMessage(BassClientStateMachine.DISCONNECT);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1589" + column="61"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(sink);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return sm.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1638" + column="23"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1664" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" connectionState = sm.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1666" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (sm.isConnected()) {" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1688" + column="24"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" devices.add(sm.getDevice());" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1689" + column="36"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1711" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (sm.isConnected()) {" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1850" + column="56"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" selectSource(sm.getDevice(), result, false);" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1851" + column="69"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1903" + column="21"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.sendMessage(BassClientStateMachine.START_SCAN_OFFLOAD);" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1912" + column="69"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2639" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.REACHED_MAX_SOURCE_LIMIT);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2645" + column="75"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.SELECT_BCAST_SOURCE);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2661" + column="71"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (stateMachine.hasPendingSourceOperation()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2789" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.getCurrentBroadcastMetadata(sourceId);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2805" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" device, BassClientStateMachine.REMOVE_BCAST_SOURCE, sourceId);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2828" + column="64"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2830" + column="64"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.SWITCH_BCAST_SOURCE);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2837" + column="79"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2874" + column="56"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Message message = stateMachine.obtainMessage(BassClientStateMachine.ADD_BCAST_SOURCE);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2889" + column="81"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2900" + column="77"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" message.arg1 = BassClientStateMachine.ARGTYPE_METADATA;" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2902" + column="55"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2959" + column="71"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2973" + column="77"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" message.arg1 = BassClientStateMachine.ARGTYPE_METADATA;" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="2975" + column="55"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.getCurrentBroadcastMetadata(sourceId);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3023" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (metaData != null && stateMachine.isSyncedToTheSource(sourceId)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3029" + column="50"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3040" + column="75"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.REMOVE_BCAST_SOURCE);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3054" + column="71"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine.REMOVE_BCAST_SOURCE," + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3064" + column="44"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return stateMachine.getAllSources().stream()" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3083" + column="33"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3097" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return stateMachine.getMaximumSourceCapacity();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3102" + column="29"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3167" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (sm != null && sm.hasPendingSourceOperation(broadcastId)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3168" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine.CANCEL_PENDING_SOURCE_OPERATION);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3171" + column="60"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" getOrCreateStateMachine(groupDevice).getAllSources().stream()" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3417" + column="58"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3580" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" List<BluetoothLeBroadcastReceiveState> sources = stateMachine.getAllSources();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3581" + column="79"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3617" + column="79"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sink, reason, BassClientStateMachine.ADD_BCAST_SOURCE, param.mObj2);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3876" + column="66"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine.REMOVE_BCAST_SOURCE," + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="3884" + column="52"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine sm = entry.getValue();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="4193" + column="20"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.dump(sb);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="4194" + column="20"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine sm = entry.getValue();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (sm.getConnectionState() != BluetoothProfile.STATE_CONNECTED) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="4202" + column="20"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.dump(sb);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="4203" + column="20"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" public BassClientStateMachine makeStateMachine(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java" + line="73" + column="12"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return BassClientStateMachine.make(device, svc, adapterService, looper);" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java" + line="78" + column="39"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" public void destroyStateMachine(BassClientStateMachine stateMachine) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java" + line="86" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BassClientStateMachine.destroy(stateMachine);" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java" + line="87" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bas/BatteryService.java" + line="353" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = new Metadata(primaryKey);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="47" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = new Metadata(primaryKey);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="47" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.migrated = fetchInt(cursor, "migrated") > 0;" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="49" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.last_active_time = fetchInt(cursor, "last_active_time");" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="52" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.is_active_a2dp_device = fetchInt(cursor, "is_active_a2dp_device") > 0;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="53" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Cursor cursor, String logKey, Metadata metadata) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="155" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.a2dpSupportsOptionalCodecs = value;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="167" + column="18"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Cursor cursor, String logKey, Metadata metadata) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="171" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.a2dpOptionalCodecsEnabled = value;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="183" + column="18"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private static void migrate_connectionPolicy(Cursor cursor, String logKey, Metadata metadata) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="186" + column="80"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.setProfileConnectionPolicy(p.first, policy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="196" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private static void migrate_customizedMeta(Cursor cursor, Metadata metadata) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="208" + column="63"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.setCustomizedMeta(p.first, blob);" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java" + line="212" + column="22"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private BluetoothCall mOldHeldCall = null;" + errorLine2=" ~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private final HashMap<Integer, BluetoothCall> mBluetoothConferenceCallInference =" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="139" + column="36"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall call = mCallInfo.getRingingOrSimulatedRingingCall();" + errorLine2=" ~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.answer(VideoProfile.STATE_AUDIO_ONLY);" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="408" + column="18"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall call = mCallInfo.getForegroundCall();" + errorLine2=" ~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(call.getParentId());" + errorLine2=" ~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(call.getParentId());" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="423" + column="70"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && conferenceCall.getState() == Call.STATE_ACTIVE) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="425" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.getState() == Call.STATE_RINGING) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="429" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.reject(false, "");" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="430" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.disconnect();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="432" + column="22"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall call = mCallInfo.getForegroundCall();" + errorLine2=" ~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.playDtmfTone((char) dtmf);" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="449" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.stopDtmfTone();" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="450" + column="18"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall ringingCall = mCallInfo.getRingingOrSimulatedRingingCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="584" + column="9"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall dialingCall = mCallInfo.getOutgoingCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="585" + column="9"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall activeCall = mCallInfo.getActiveCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="586" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" isHighDef = ringingCall.isHighDefAudio();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="590" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Bundle extras = dialingCall.getDetails().getExtras();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="593" + column="41"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" isHighDef = dialingCall.isHighDefAudio();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="598" + column="45"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" isHighDef = activeCall.isHighDefAudio();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="605" + column="36"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" public void onCallAdded(BluetoothCall call) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="626" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.isExternalCall()) {" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="627" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mBluetoothCallHashMap.containsKey(call.getId())) {" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="631" + column="53"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" CallStateCallback callback = new CallStateCallback(call.getState());" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="633" + column="69"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mCallbacks.put(call.getId(), callback);" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="634" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.registerCallback(callback);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="635" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mBluetoothCallHashMap.put(call.getId(), call);" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="637" + column="44"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!call.isConference()) {" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="638" + column="23"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall call = mCallInfo.getForegroundCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="659" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.sendCallEvent(BluetoothCallQualityReport.EVENT_BLUETOOTH_CALL_QUALITY_REPORT, b);" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="676" + column="14"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" onCallAdded(new BluetoothCall(call));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="683" + column="21"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" public void onCallRemoved(BluetoothCall call, boolean forceRemoveCallback) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="696" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (callback != null && (forceRemoveCallback || !call.isExternalCall())) {" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="699" + column="63"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.unregisterCallback(callback);" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="700" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mBluetoothCallHashMap.containsKey(call.getId())) {" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="703" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mBluetoothCallHashMap.remove(call.getId());" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="704" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" DisconnectCause cause = call.getDisconnectCause();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="706" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mBluetoothCallQueue.add(call.getId());" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="709" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mBluetoothConferenceCallInference.put(call.getId(), call);" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="710" + column="60"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.mClccIndex > -1) {" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="716" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" getClccMapKey(call), call.mClccIndex);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="718" + column="67"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.isConference()) {" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="733" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.getTbsCallId(), getTbsTerminationReason(call));" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="753" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall bluetoothCall = getBluetoothCallById(System.identityHashCode(call));" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="761" + column="9"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private static boolean isConferenceWithNoChildren(BluetoothCall call) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="829" + column="55"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return call.isConference()" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="830" + column="21"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && (call.can(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="831" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || call.getChildrenIds().isEmpty());" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="832" + column="33"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Collection<BluetoothCall> calls = mCallInfo.getBluetoothCalls();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="837" + column="20"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCallChildrenNotReady = null;" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="840" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.isConference() && !mBluetoothConferenceCallInference.isEmpty()) {" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="843" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.getChildrenIds().size() >= 2) {" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="853" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (inferredCall.isCallNull() || inferredCall.getHandle() == null) {" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="863" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (inferredCall.isCallNull() || inferredCall.getHandle() == null) {" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="863" + column="63"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int index = inferredCall.mClccIndex;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="868" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (bluetoothCall.getHandle() == null) {" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="876" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Log.w(TAG, "call id: " + bluetoothCall.getId() + " handle is null");" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="877" + column="64"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" bluetoothCall.getHandle().toString()," + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="882" + column="51"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" inferredCall.getHandle().toString()," + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="883" + column="50"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + bluetoothCall.getId());" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="890" + column="57"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" bluetoothCall.mClccIndex = inferredCall.mClccIndex;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="891" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" bluetoothCall.mClccIndex = inferredCall.mClccIndex;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="891" + column="65"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int direction = inferredCall.isIncoming() ? 1 : 0;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="896" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (inferredCall.getGatewayInfo() != null) {" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="900" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" addressUri = inferredCall.getGatewayInfo().getOriginalAddress();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="901" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" addressUri = inferredCall.getHandle();" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="903" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + call.getChildrenIds().size());" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="955" + column="36"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!call.isConference() || isConferenceWithNoChildren) {" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="956" + column="23"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private void sendClccForCall(BluetoothCall call, boolean shouldLog) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="973" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" boolean isForeground = call.equals(mCallInfo.getForegroundCall());" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="974" + column="37"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(call.getParentId());" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="983" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(call.getParentId());" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="983" + column="66"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (conferenceCall.hasProperty(Call.Details.PROPERTY_GENERIC_CONFERENCE)) {" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="987" + column="32"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall activeChild =" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="997" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" conferenceCall.getGenericConferenceActiveChildCallId());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="999" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" conferenceCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1004" + column="44"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || (conferenceCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1005" + column="56"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && !conferenceCall.wasConferencePreviouslyMerged());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1006" + column="64"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.equals(activeChild)) {" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1010" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (conferenceCall.getState() == Call.STATE_HOLDING" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1020" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && conferenceCall.can(Connection.CAPABILITY_MANAGE_CONFERENCE)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1021" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int direction = call.isIncoming() ? 1 : 0;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1036" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.getGatewayInfo() != null) {" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1038" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" addressUri = call.getGatewayInfo().getOriginalAddress();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1039" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" addressUri = call.getHandle();" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1041" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int callCLCCIndex = bluetoothCall.mClccIndex;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1092" + column="47"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private int getIndexForCall(BluetoothCall call) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1122" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.mClccIndex = mConferenceCallClccIndexMap.get(getClccMapKey(call));" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1131" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.mClccIndex >= 1) {" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1134" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return call.mClccIndex;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1135" + column="25"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.isConference()) {" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1139" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" call.mClccIndex = getNextAvailableClccIndex(index);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1145" + column="14"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .removeIf(entry -> entry.getValue() == call.mClccIndex);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1151" + column="65"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Log.d(TAG, "call " + call.getId() + " CLCC index is " + call.mClccIndex);" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1153" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Log.d(TAG, "call " + call.getId() + " CLCC index is " + call.mClccIndex);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1153" + column="70"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return call.mClccIndex;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1154" + column="21"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall activeCall = mCallInfo.getActiveCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1159" + column="9"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall ringingCall = mCallInfo.getRingingOrSimulatedRingingCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1160" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Log.i(TAG, "ringingCall hashcode: " + ringingCall.hashCode());" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1164" + column="63"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall heldCall = mCallInfo.getHeldCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1167" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Log.i(TAG, "reject ringing call " + ringingCall.hashCode());" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1183" + column="65"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ringingCall.reject(false, null);" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1184" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" heldCall.disconnect();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1187" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(activeCall.getParentId());" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1197" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(activeCall.getParentId());" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1197" + column="80"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && conferenceCall.getState() == Call.STATE_ACTIVE) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1199" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" conferenceCall.disconnect();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1201" + column="36"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" activeCall.disconnect();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1203" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ringingCall.answer(ringingCall.getVideoState());" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1207" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ringingCall.answer(ringingCall.getVideoState());" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1207" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" heldCall.unhold();" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1209" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && activeCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1214" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" activeCall.swapConference();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1215" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ringingCall.answer(VideoProfile.STATE_AUDIO_ONLY);" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1220" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" heldCall.unhold();" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1225" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && activeCall.can(Connection.CAPABILITY_HOLD)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1228" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" activeCall.hold();" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1229" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (activeCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1234" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" activeCall.mergeConference();" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1235" + column="32"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" List<BluetoothCall> conferenceable =" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1238" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" getBluetoothCallsByIds(activeCall.getConferenceableCalls());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1239" + column="63"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" activeCall.conference(conferenceable.get(0));" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1241" + column="36"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall activeCall = mCallInfo.getActiveCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1259" + column="9"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall ringingCall = mCallInfo.getRingingOrSimulatedRingingCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1260" + column="9"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall heldCall = mCallInfo.getHeldCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1261" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && ringingCall.getHandle() != null" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1269" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && !ringingCall.isSilentRingingRequested()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1270" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ringingAddress = ringingCall.getHandle().getSchemeSpecificPart();" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1271" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ringingName = ringingCall.getCallerDisplayName();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1275" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ringingName = ringingCall.getContactDisplayName();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1277" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mCallInfo.isNullCall(activeCall) ? 0 : activeCall.getChildrenIds().size();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1287" + column="67"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && activeCall.isConference()" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1299" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && !activeCall.can(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1300" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (activeCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1301" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" numHeldCalls = activeCall.wasConferencePreviouslyMerged() ? 0 : 1;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1304" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" } else if (activeCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1305" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" for (Integer id : activeCall.getChildrenIds()) {" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1309" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mOldHeldCall != null && Objects.equals(mOldHeldCall.getId(), id)) {" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1313" + column="73"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall ringingCall = mCallInfo.getRingingOrSimulatedRingingCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1402" + column="9"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall dialingCall = mCallInfo.getOutgoingCall();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1403" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mCallInfo.isNullCall(ringingCall) && !ringingCall.isSilentRingingRequested()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1416" + column="64"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private int getBtCallState(BluetoothCall call, boolean isForeground) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1427" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" switch (call.getState()) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1428" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.isSilentRingingRequested()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1455" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private Integer getTbsCallState(BluetoothCall call) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1643" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" switch (call.getState()) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1644" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.isSilentRingingRequested()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1661" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private BluetoothLeCall createTbsCall(BluetoothCall call) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1699" + column="43"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(call.getParentId());" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1707" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall conferenceCall = getBluetoothCallById(call.getParentId());" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1707" + column="66"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" BluetoothCall activeChild =" + errorLine2=" ~~~~~~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" getBluetoothCallById(conferenceCall.getGenericConferenceActiveChildCallId());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1720" + column="57"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" conferenceCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1725" + column="40"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || (conferenceCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1726" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && !conferenceCall.wasConferencePreviouslyMerged());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1727" + column="60"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.equals(activeChild)) {" + errorLine2=" ~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1730" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (conferenceCall.getState() == Call.STATE_HOLDING" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1739" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && conferenceCall.can(Connection.CAPABILITY_MANAGE_CONFERENCE)) {" + errorLine2=" ~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1740" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (call.getGatewayInfo() != null) {" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1755" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" addressUri = call.getGatewayInfo().getOriginalAddress();" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1756" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" addressUri = call.getHandle();" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1758" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int callFlags = call.isIncoming() ? 0 : BluetoothLeCall.FLAG_OUTGOING_CALL;" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1762" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" String friendlyName = call.getCallerDisplayName();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1764" + column="36"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" friendlyName = call.getContactDisplayName();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1766" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return new BluetoothLeCall(call.getTbsCallId(), uri, friendlyName, state, callFlags);" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java" + line="1769" + column="41"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothMapService.getBluetoothMapService()" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java" + line="1262" + column="49"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothMapService.getBluetoothMapService()" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListing.java" + line="103" + column="49"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothMapService.getBluetoothMapService().getRemoteDevice().getAddress()," + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListing.java" + line="152" + column="45"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothMapService.getBluetoothMapService().getRemoteDevice().getAddress()," + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java" + line="277" + column="41"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" + line="640" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" BluetoothMapService.getBluetoothMapService().getRemoteDevice().getAddress();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageSms.java" + line="93" + column="41"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java" + line="641" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mRemoteDevices.addDeviceProperties(address);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java" + line="645" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mRemoteDevices.addDeviceProperties(address);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java" + line="682" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mRemoteDevices.addDeviceProperties(address);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java" + line="712" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java" + line="449" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java" + line="879" + column="63"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" List<Metadata> list;" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="124" + column="34"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata data = (Metadata) msg.obj;" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="141" + column="25"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata data = (Metadata) msg.obj;" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="141" + column="42"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="210" + column="17"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata data = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return data.getCustomizedMeta(key);" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="280" + column="25"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata data = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int connectionPolicy = data.getProfileConnectionPolicy(profile);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="439" + column="41"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="606" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.last_active_time = MetadataDatabase.sCurrentConnectionNumber++;" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="608" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.is_active_a2dp_device = true;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="613" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.isActiveHfpDevice = true;" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="617" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + metadata.last_active_time);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="625" + column="36"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (profileId == BluetoothProfile.A2DP && metadata.is_active_a2dp_device) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="697" + column="64"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.is_active_a2dp_device = false;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="698" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (profileId == BluetoothProfile.HEADSET && metadata.isActiveHfpDevice) {" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="705" + column="67"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.isActiveHfpDevice = false;" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="706" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = entry.getValue();" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (metadata.is_active_a2dp_device) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="722" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.is_active_a2dp_device = false;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="724" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = entry.getValue();" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (metadata.isActiveHfpDevice) {" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="736" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.isActiveHfpDevice = false;" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="738" + column="26"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" List<Metadata> sortedMetadata = new ArrayList<>(mMetadataCache.values());" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="754" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sortedMetadata.sort((o1, o2) -> Long.compare(o2.last_active_time, o1.last_active_time));" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="755" + column="61"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sortedMetadata.sort((o1, o2) -> Long.compare(o2.last_active_time, o1.last_active_time));" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="755" + column="82"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getRemoteDevice(metadata.getAddress()));" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="760" + column="63"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + metadata.getAnonymizedAddress());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="765" + column="48"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="790" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || mostRecentLastActiveTime < metadata.last_active_time)) {" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="793" + column="72"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mostRecentLastActiveTime = metadata.last_active_time;" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="794" + column="57"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = entry.getValue();" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="810" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (metadata.is_active_a2dp_device) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="811" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getRemoteDevice(metadata.getAddress());" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="814" + column="59"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + metadata.getAnonymizedAddress());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="819" + column="52"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Map.Entry<String, Metadata> entry;" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="833" + column="27"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .filter(x -> x.getValue().isActiveHfpDevice)" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="837" + column="55"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getRemoteDevice(entry.getValue().getAddress());" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="844" + column="59"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + entry.getValue().getAnonymizedAddress());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="849" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .filter(x -> x.getValue().isActiveHfpDevice)" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="863" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .map(x -> adapter.getRemoteDevice(x.getValue().getAddress()))" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="864" + column="68"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private void compactLastConnectionTime(List<Metadata> metadataList) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="873" + column="49"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = metadataList.get(index);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="879" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (metadata.last_active_time != MetadataDatabase.sCurrentConnectionNumber) {" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="880" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + metadata.getAnonymizedAddress()" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="884" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + metadata.last_active_time" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="886" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.last_active_time = MetadataDatabase.sCurrentConnectionNumber;" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="889" + column="30"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="935" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && (metadata.preferred_output_only_profile != 0" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="937" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || metadata.preferred_duplex_profile != 0)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="938" + column="45"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.preferred_output_only_profile = outputProfile;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="946" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && (metadata.preferred_output_only_profile != 0" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="950" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || metadata.preferred_duplex_profile != 0)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="951" + column="45"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.preferred_duplex_profile = duplexProfile;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="958" + column="30"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(firstGroupDevice.getAddress());" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="970" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.preferred_output_only_profile = outputProfile;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="979" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.preferred_duplex_profile = duplexProfile;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="988" + column="30"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" outputOnlyProfile = metadata.preferred_output_only_profile;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1021" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" duplexProfile = metadata.preferred_duplex_profile;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1022" + column="38"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" metadata.active_audio_device_policy = activeAudioDevicePolicy;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1066" + column="22"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata metadata = mMetadataCache.get(address);" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return metadata.active_audio_device_policy;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1091" + column="29"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata.Builder dataBuilder = new Metadata.Builder(address);" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1170" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Metadata.Builder dataBuilder = new Metadata.Builder(address);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1170" + column="40"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" dataBuilder.setActiveA2dp();" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1173" + column="25"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" dataBuilder.setActiveHfp();" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1176" + column="25"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata data = dataBuilder.build();" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1179" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Metadata data = dataBuilder.build();" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1179" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + (" address=" + data.getAnonymizedAddress())" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1183" + column="47"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" void cacheMetadata(List<Metadata> list) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1214" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" String address = data.getAddress();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1227" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Log.v(TAG, "cacheMetadata: found device " + data.getAnonymizedAddress());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1228" + column="66"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" boolean isMigrated(List<Metadata> list) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1235" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" String address = data.getAddress();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1237" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (address.equals(LOCAL_STORAGE) && data.migrated) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1238" + column="55"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata data = new Metadata(address);" + errorLine2=" ~~~~~~~~"> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Metadata data = new Metadata(address);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1324" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.A2DP, a2dpConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1325" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.A2DP_SINK, a2dpSinkConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1326" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.HEADSET, headsetConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1327" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1328" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.HID_HOST, hidHostConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1330" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.PAN, panConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1331" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.PBAP, pbapConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1332" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1333" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.MAP, mapConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1335" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.MAP_CLIENT, mapClientConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1336" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(BluetoothProfile.SAP, sapConnectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1337" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1338" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1340" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.a2dpSupportsOptionalCodecs = a2dpSupportsOptionalCodec;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1342" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" data.a2dpOptionalCodecsEnabled = a2dpOptionalCodecEnabled;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1343" + column="18"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" Metadata localData = new Metadata(LOCAL_STORAGE);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1349" + column="9"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Metadata localData = new Metadata(LOCAL_STORAGE);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1349" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" localData.migrated = true;" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1350" + column="19"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private void updateDatabase(Metadata data) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1433" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (data.getAddress() == null) {" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1434" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" Log.d(TAG, "updateDatabase " + data.getAnonymizedAddress());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1438" + column="45"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" private void logMetadataChange(Metadata data, String log) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1498" + column="36"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" time + " (" + uidPid + ") " + data.getAnonymizedAddress() + " " + log);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java" + line="1502" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return new HapClientBinder(this);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hap/HapClientService.java" + line="147" + column="16"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hap/HapClientService.java" + line="319" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.sendMessage(HapClientStateMachine.STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hap/HapClientService.java" + line="927" + column="50"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.initialize();" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java" + line="127" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.cleanup();" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java" + line="196" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java" + line="784" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.queryCurrentCalls(mCurrentDevice);" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="402" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.handleCallAction(mCurrentDevice, action, 0)) {" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="657" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.handleCallAction(mCurrentDevice, action, 0)) {" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="698" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.handleCallAction(mCurrentDevice, action, 0)) {" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="723" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.handleCallAction(mCurrentDevice, action, 0)) {" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="746" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.disconnect(mCurrentDevice);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="990" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.connect(device)) {" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1068" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.disconnect(device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1122" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.disconnect(device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1286" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.sendATCmd(" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1294" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.connect(device);" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1405" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.disconnect(dev)) {" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1412" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.connectAudio(mCurrentDevice)) {" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1418" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.startVoiceRecognition(mCurrentDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1438" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.stopVoiceRecognition(mCurrentDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1448" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.sendATCmd(" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1470" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int hfVol = mService.amToHfVol(amVol);" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1486" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.setVolume(" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1491" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.dial(mCurrentDevice, c.getNumber())) {" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1502" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.sendDtmf(mCurrentDevice, (byte) message.arg1)) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1533" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.retrieveSubscriberInfo(mCurrentDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1540" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.queryCurrentOperatorName(mCurrentDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1606" + column="54"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" final int hfVol = mService.amToHfVol(amVol);" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="1874" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.sendAndroidAt(" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="2398" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.sendAndroidAt(mCurrentDevice, "+ANDROID=?")) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" + line="2408" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mHandler = new Handler(headsetService.getStateMachinesThreadLooper());" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetPhoneState.java" + line="86" + column="51"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="253" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getVoiceRecognitionWakeLock().release();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="255" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.cleanup();" + errorLine2=" ~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="268" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getHeadsetPhoneState()" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="421" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (stateMachine.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="489" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int connectionState = stateMachine.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="889" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int connectionState = stateMachine.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="937" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (stateMachine.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="957" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" devices.add(stateMachine.getDevice());" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="958" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return stateMachine.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1005" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1033" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1119" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getVoiceRecognitionWakeLock().release();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1121" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int connectionState = stateMachine.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1137" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" AudioManager am = mSystemInterface.getAudioManager();" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1163" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int connectionState = stateMachine.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1211" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getAudioManager().clearCommunicationDevice();" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1232" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.setScoAllowed(allowed);" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1266" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getAudioManager()" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1402" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.setActiveDevice(null);" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1410" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.setActiveDevice(device)) {" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1443" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mSystemInterface.isInCall() || mSystemInterface.isRinging()) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1454" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mSystemInterface.isInCall() || mSystemInterface.isRinging()) {" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1454" + column="65"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.setActiveDevice(previousActiveDevice);" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1472" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getAudioManager()" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1478" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getAudioManager()" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1492" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.setActiveDevice(previousActiveDevice);" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1515" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getAudioManager()" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1523" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (stateMachine.getConnectionState() != BluetoothProfile.STATE_CONNECTED) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1573" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" devices.add(stateMachine.getDevice());" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1598" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1808" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getVoiceRecognitionWakeLock().release();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1810" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mSystemInterface.activateVoiceRecognition()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1892" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1905" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getVoiceRecognitionWakeLock().acquire(sStartVrTimeoutMs);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1906" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1933" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getVoiceRecognitionWakeLock().release();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1935" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mSystemInterface.deactivateVoiceRecognition()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="1956" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" int connectionState = stateMachine.getConnectionState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2103" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mVoiceRecognitionStarted || mVirtualCallStarted || !mSystemInterface.isCallIdle()) {" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2251" + column="86"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + mSystemInterface.isCallIdle());" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2259" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return mSystemInterface.isInCall()" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2287" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || (mSystemInterface.isRinging() && isInbandRingingEnabled());" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2288" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within package private scope" + errorLine1=" if (a2dpService != null && a2dpService.okToConnect(device, true)) {" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2429" + column="56"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + mSystemInterface.isInCall()" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2494" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" + mSystemInterface.isRinging()" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2498" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" boolean isScoOn = mSystemInterface.getAudioManager().isBluetoothScoOn();" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2559" + column="44"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ProfileService.println(sb, "Telecom.isInCall(): " + mSystemInterface.isInCall());" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2585" + column="82"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" ProfileService.println(sb, "Telecom.isRinging(): " + mSystemInterface.isRinging());" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2586" + column="83"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sb, "==== StateMachine for " + stateMachine.getDevice() + " ====");" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2589" + column="69"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" boolean result = mNativeInterface.enableSwb(swbCodec, enable, device);" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" + line="2598" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.getAudioPolicyMetadata(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="210" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setAudioPolicyMetadata(device, mHsClientAudioPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="214" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mHeadsetService.onConnectionStateChangedFromStateMachine(device, fromState, toState);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="349" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mHeadsetService.onAudioStateChangedFromStateMachine(device, fromState, toState);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="374" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mSystemInterface.isHighDefCallInProgress()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="529" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.connectHfp(device)) {" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="590" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.disconnectHfp(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="665" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.answerCall(event.device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="847" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.hangupCall(event.device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="851" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.startVoiceRecognition(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1023" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.stopVoiceRecognition(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1039" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.phoneStateChange(mDevice, callState)) {" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1049" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.notifyDeviceStatus(mDevice, (HeadsetDeviceState) message.obj);" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1062" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.clccResponse(device, 0, 0, 0, 0, false, "", 0);" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1075" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.sendBsir(mDevice, message.arg1 == 1);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1083" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1095" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1115" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.answerCall(event.device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1155" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.hangupCall(event.device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1158" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.sendDtmf(event.valueInt, event.device);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1167" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.setVolume(" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1261" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.queryPhoneState();" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1282" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.disconnectHfp(device)) {" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1315" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getAudioManager().setA2dpSuspended(true);" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1334" + column="38"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getAudioManager().setLeAudioSuspended(true);" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1336" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && mSystemInterface.isHighDefCallInProgress()) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1342" + column="53"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.connectAudio(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1353" + column="43"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getAudioManager().setA2dpSuspended(false);" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1354" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getAudioManager().setLeAudioSuspended(false);" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1356" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.disconnectAudio(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1385" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.disconnectAudio(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1401" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .getAudioManager()" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1556" + column="22"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getAudioManager().clearAudioServerStateCallback();" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1567" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.disconnectAudio(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1589" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mNativeInterface.disconnectAudio(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1619" + column="46"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" AudioManager am = mSystemInterface.getAudioManager();" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1870" + column="44"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1934" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1941" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1949" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1956" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1968" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1977" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1981" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1983" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="1986" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" final HeadsetPhoneState phoneState = mSystemInterface.getHeadsetPhoneState();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2117" + column="63"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.cindResponse(" + errorLine2=" ~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2155" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mNativeInterface.atResponseString(" + errorLine2=" ~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2413" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setAudioPolicyMetadata(mDevice, policies);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2474" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mSystemInterface.isRinging()) {" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2592" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.answerCall(device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2593" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" } else if (mSystemInterface.isInCall()) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2594" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.hangupCall(device);" + errorLine2=" ~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2601" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.disconnectAudio(mDevice)) {" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2604" + column="35"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getHeadsetPhoneState().listenForPhoneState(mDevice, events);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2731" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mSystemInterface.getHeadsetPhoneState().listenForPhoneState(mDevice, events);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" + line="2731" + column="49"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java" + line="483" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.sendMessage(HearingAidStateMachine.STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java" + line="655" + column="51"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hid/HidDeviceService.java" + line="662" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hid/HidHostService.java" + line="1073" + column="31"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" public LeAudioTmapGattServer getTmapGattServer(Context context) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioObjectsFactory.java" + line="66" + column="12"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return new LeAudioTmapGattServer(" + errorLine2=" ^"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioObjectsFactory.java" + line="67" + column="16"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" new LeAudioTmapGattServer.BluetoothGattServerProxy(context));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioObjectsFactory.java" + line="68" + column="17"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" LeAudioTmapGattServer mTmapGattServer;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="187" + column="5"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mTmapGattServer.start(mTmapRoleMask);" + errorLine2=" ~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="520" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG | LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS;" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="566" + column="39"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG | LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="566" + column="81"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mTmapRoleMask |= LeAudioTmapGattServer.TMAP_ROLE_FLAG_BMS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="579" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mTmapGattServer.stop();" + errorLine2=" ~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="656" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="2644" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.sendMessage(LeAudioStateMachine.STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="3393" + column="52"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="4382" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && !TbsGatt.UUID_GTBS.equals(userUuid.getUuid())) {" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" + line="4521" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/mapclient/MapClientService.java" + line="248" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mService.cleanupDevice(mDevice, this);" + errorLine2=" ~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java" + line="277" + column="22"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" List<Metadata> load();" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/MetadataDao.java" + line="30" + column="10"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" void insert(Metadata... metadata);" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/MetadataDao.java" + line="34" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" entities = {Metadata.class}," + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java" + line="35" + column="21"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" public void insert(Metadata... metadata) {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java" + line="96" + column="24"/> + id="VisibleForTests" + message="This class should only be accessed from tests or within private scope" + errorLine1=" public List<Metadata> load() {" + errorLine2=" ~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java" + line="105" + column="17"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mPanService.onControlStateChanged(localRole, convertHalState(halState), error, ifname);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java" + line="83" + column="21"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pan/PanService.java" + line="521" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java" + line="626" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mAdapterService.isProfileSupported(dev, BluetoothProfile.LE_AUDIO)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="229" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (mAdapterService.isProfileSupported(dev, BluetoothProfile.HEARING_AID)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="234" + column="33"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="363" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="386" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="397" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="414" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="425" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="445" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="465" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="474" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="494" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="513" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="522" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="537" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="549" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="569" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="577" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="596" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="607" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="625" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" || !mAdapterService.isProfileSupported(device, BluetoothProfile.LE_AUDIO)) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" + line="640" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .setProfileConnectionPolicy(device, BluetoothProfile.SAP, connectionPolicy);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/sap/SapService.java" + line="641" + column="18"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" a2dpService.setSilenceMode(device, state);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java" + line="249" + column="25"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" headsetService.setSilenceMode(device, state);" + errorLine2=" ~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java" + line="253" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" new ParcelUuid(TbsGatt.UUID_GTBS)," + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="171" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (request.requestedOpcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_TERMINATE) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="434" + column="48"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="436" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="438" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" } else if (request.requestedOpcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_ACCEPT) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="440" + column="55"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="442" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="444" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" } else if (request.requestedOpcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_HOLD) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="446" + column="55"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="449" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="451" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" } else if (request.requestedOpcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_RETRIEVE) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="453" + column="55"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="456" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="458" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" } else if (request.requestedOpcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_ORIGINATE) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="460" + column="55"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="462" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="464" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" } else if (request.requestedOpcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_JOIN) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="466" + column="55"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="471" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="483" + column="34"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="486" + column="30"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return TbsGatt.CALL_CONTROL_POINT_RESULT_INVALID_CALL_INDEX;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="497" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" && requestedOpcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_ORIGINATE) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="501" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return TbsGatt.CALL_CONTROL_POINT_RESULT_INVALID_OUTGOING_URI;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="502" + column="28"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="505" + column="24"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" TbsGatt.CALL_CONTROL_POINT_OPCODE_ORIGINATE," + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="773" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="775" + column="29"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" TbsGatt.CALL_CONTROL_POINT_OPCODE_ORIGINATE," + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="783" + column="37"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return TbsGatt.CALL_CONTROL_POINT_RESULT_INVALID_OUTGOING_URI;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="788" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="795" + column="32"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" return TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="803" + column="24"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_ACCEPT:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="850" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_TERMINATE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="851" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_HOLD:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="852" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_RETRIEVE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="853" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="858" + column="58"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_INVALID_CALL_INDEX;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="867" + column="58"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_STATE_MISMATCH;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="873" + column="58"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (opcode == TbsGatt.CALL_CONTROL_POINT_OPCODE_ACCEPT) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="883" + column="63"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" == TbsGatt.CALL_CONTROL_POINT_OPCODE_TERMINATE) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="888" + column="60"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" == TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_HOLD) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="892" + column="60"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_OPCODE_NOT_SUPPORTED;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="899" + column="66"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_OPCODE_NOT_SUPPORTED;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="911" + column="66"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="925" + column="58"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="932" + column="54"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_ORIGINATE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="936" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_JOIN:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="942" + column="42"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="948" + column="58"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="954" + column="54"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_INVALID_CALL_INDEX;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="960" + column="62"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="975" + column="62"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (result != TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="982" + column="59"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" .CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1000" + column="58"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1007" + column="54"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" result = TbsGatt.CALL_CONTROL_POINT_RESULT_OPCODE_NOT_SUPPORTED;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1012" + column="50"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (result == TbsGatt.CALL_CONTROL_POINT_RESULT_SUCCESS) {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1016" + column="47"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_ACCEPT:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1028" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_TERMINATE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1030" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_HOLD:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1032" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_RETRIEVE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1034" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_ACCEPT:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1216" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_TERMINATE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1222" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_HOLD:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1226" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" case TbsGatt.CALL_CONTROL_POINT_OPCODE_LOCAL_RETRIEVE:" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" + line="1234" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" if (!mNativeInterface.sendATCmd(" + errorLine2=" ~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessor.java" + line="104" + column="31"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/vc/VolumeControlService.java" + line="416" + column="26"/> + id="VisibleForTests" + message="This method should only be accessed from tests or within private scope" + errorLine1=" sm.sendMessage(VolumeControlStateMachine.STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/vc/VolumeControlService.java" + line="1316" + column="54"/> + id="MissingVersion" + message="Should set `android:versionCode` to specify the application version" + errorLine1="<manifest xmlns:android="http://schemas.android.com/apk/res/android"" + errorLine2=" ~~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="2" + column="2"/> + id="MissingVersion" + message="Should set `android:versionName` to specify the application version" + errorLine1="<manifest xmlns:android="http://schemas.android.com/apk/res/android"" + errorLine2=" ~~~~~~~~"> + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex33/manifest_merger/AndroidManifest.xml" + line="2" + column="2"/> @@ -22010,7 +8423,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22021,7 +8434,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22032,7 +8445,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22043,7 +8456,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22054,7 +8467,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22065,7 +8478,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22076,7 +8489,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22087,7 +8500,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -22098,7 +8511,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22109,7 +8522,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22120,7 +8533,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22131,7 +8544,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22142,7 +8555,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22153,7 +8566,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22164,7 +8577,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22175,7 +8588,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -22186,7 +8599,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> @@ -22197,7 +8610,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22208,7 +8621,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22219,7 +8632,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22230,7 +8643,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22241,7 +8654,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22252,7 +8665,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22263,7 +8676,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -22274,7 +8687,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22285,7 +8698,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22296,7 +8709,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22307,7 +8720,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22318,7 +8731,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22329,7 +8742,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22340,7 +8753,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22351,7 +8764,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22362,7 +8775,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -22373,7 +8786,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -22384,7 +8797,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -22395,7 +8808,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22406,7 +8819,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -22417,7 +8830,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22428,7 +8841,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -22439,7 +8852,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22450,7 +8863,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22461,7 +8874,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22472,7 +8885,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -22483,7 +8896,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22494,7 +8907,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22505,7 +8918,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22516,7 +8929,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22527,7 +8940,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22538,7 +8951,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22549,7 +8962,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22560,7 +8973,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22571,7 +8984,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22582,7 +8995,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22593,7 +9006,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22604,7 +9017,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -22615,7 +9028,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22626,7 +9039,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -22637,7 +9050,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -22648,7 +9061,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22659,7 +9072,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22670,7 +9083,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22681,7 +9094,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22692,7 +9105,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22703,7 +9116,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22714,7 +9127,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -22725,7 +9138,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22736,7 +9149,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22747,7 +9160,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -22758,7 +9171,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22769,7 +9182,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22780,7 +9193,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -22791,7 +9204,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -22802,7 +9215,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22813,7 +9226,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -22824,7 +9237,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22835,7 +9248,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22846,7 +9259,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -22857,7 +9270,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -22868,7 +9281,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22879,7 +9292,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -22890,7 +9303,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -22901,7 +9314,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -22912,7 +9325,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -22923,7 +9336,7 @@ errorLine2=" ~~~~~~~~~"> @@ -22934,7 +9347,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -22945,7 +9358,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> @@ -22956,7 +9369,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22967,7 +9380,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -22978,7 +9391,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -22989,7 +9402,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23000,7 +9413,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -23011,7 +9424,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23022,7 +9435,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23033,7 +9446,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -23044,7 +9457,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23055,7 +9468,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -23066,7 +9479,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -23077,7 +9490,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -23088,7 +9501,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> @@ -23099,7 +9512,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -23110,7 +9523,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -23121,7 +9534,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -23132,7 +9545,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -23143,7 +9556,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23154,7 +9567,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -23165,7 +9578,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> @@ -23176,7 +9589,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23187,7 +9600,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23198,7 +9611,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -23209,7 +9622,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -23220,7 +9633,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -23231,7 +9644,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -23242,7 +9655,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -23253,7 +9666,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23264,7 +9677,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -23275,7 +9688,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> @@ -23286,7 +9699,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -23297,7 +9710,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23308,7 +9721,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -23319,7 +9732,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -23330,7 +9743,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -23341,7 +9754,7 @@ errorLine2=" ~~~~~~~~"> @@ -23352,7 +9765,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -23363,7 +9776,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -23374,7 +9787,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23385,7 +9798,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23396,7 +9809,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23407,7 +9820,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23418,7 +9831,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23429,7 +9842,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23440,7 +9853,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23451,7 +9864,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23462,7 +9875,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23473,7 +9886,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23484,7 +9897,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23495,7 +9908,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23506,7 +9919,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23517,7 +9930,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23528,7 +9941,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23539,7 +9952,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23550,7 +9963,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -23561,7 +9974,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23572,7 +9985,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23583,7 +9996,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23594,7 +10007,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23605,7 +10018,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23616,7 +10029,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23627,7 +10040,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23638,7 +10051,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23649,7 +10062,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23660,7 +10073,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23671,7 +10084,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23682,7 +10095,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -23693,7 +10106,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -23704,7 +10117,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -23715,7 +10128,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -23726,7 +10139,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> diff --git a/android/app/res/values-af/strings.xml b/android/app/res/values-af/strings.xml index 272d1a1e1b6..6640182e240 100644 --- a/android/app/res/values-af/strings.xml +++ b/android/app/res/values-af/strings.xml @@ -32,7 +32,6 @@ "Skakel nou Bluetooth aan?" "Kanselleer" "Skakel aan" - "Lêeroordrag" "Aanvaar inkomende lêer?" "Wys af" "Aanvaar" @@ -42,10 +41,8 @@ "%1$s is gereed om \'n lêer te stuur: %2$s" "Bluetooth-deling: Ontvang %1$s" "Bluetooth-deling: Het \"%1$s\" ontvang" - "Bluetooth-deling: Lêer %1$s nie ontvang nie" "Bluetooth-deling: Stuur %1$s" "Bluetooth-deling: %1$s gestuur" - "100% voltooi" "Bluetooth-deling: Lêer %1$s nie gestuur nie" "Lêeroordrag" "Van: \"%1$s\"" @@ -80,7 +77,6 @@ "Wag asseblief…" "Skakel tans Bluetooth aan…" "Die lêer sal ontvang word. Kontroleer vordering in die Kennisgewings-paneel." - "Die lêer kan nie ontvang word nie." "Opgehou om lêer van \"%1$s\" te ontvang" "Stuur lêer na \"%1$s\"" "Stuur %1$s lêers na \"%2$s\"" @@ -118,7 +114,6 @@ "Vee uit" "Wat Speel" "Programikoon" - "Bluetooth-oudio is gekoppel" "Bluetooth-oudio is ontkoppel" "Bluetooth-oudio" "Lêers groter as 4 GB kan nie oorgedra word nie" diff --git a/android/app/res/values-af/test_strings.xml b/android/app/res/values-af/test_strings.xml deleted file mode 100644 index fbaf1bedeab..00000000000 --- a/android/app/res/values-af/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Voeg rekord in" - "Bevestig rekord" - "Ack-rekord" - "Vee alle rekords uit" - "OK" - "Vee rekord uit" - "Begin TCP-bediener" - "Stel TCP-bediener in kennis" - diff --git a/android/app/res/values-am/strings.xml b/android/app/res/values-am/strings.xml index bc7530b2c2d..6c2eebec910 100644 --- a/android/app/res/values-am/strings.xml +++ b/android/app/res/values-am/strings.xml @@ -32,7 +32,6 @@ "ብሉቱዝ አሁን ይብራ?" "ይቅር" "አብራ" - "ፋይልሰደዳ" "ገቢ ፋይልን ይቀበሉ?" "አትቀበል" "ተቀበል" @@ -42,10 +41,8 @@ "%1$s ፋይል ለመላክ ዝግጁ ነው፦ %2$s" "ብሉቱዝ ማጋሪያ፡ %1$s እየተቀበለ" "ብሉቱዝ ማጋሪያ፡ %1$s ደርሷል" - "ብሉቱዝ ማጋሪያ፡ ፋይል%1$s አልደረሰም" "ብሉቱዝ ማጋሪያ፡ %1$s እየላከ" "ብሉቱዝ ማጋሪያ፡ %1$s ልኳል" - "100% ተጠናቋል።" "ብሉቱዝ ማጋሪያ፡ ፋይል %1$s አልተላከም" "ፋይል ሰደዳ" "ከ: \"%1$s\"" @@ -80,7 +77,6 @@ "እባክዎ ይጠብቁ…" "ብሉቱዝ በማብራት ላይ..." "ፋይሉ ይደርሳል።በማሳወቂያ ውስን ቦታ ውስጥ ሂደቱን ይመልከቱ።" - "ፋይሉን መቀበል አይቻልም::" "ከ\"%1$s\" ፋይል መቀበል አቁሟል" "ፋይል ወደ \"%1$s\" በመላክ ላይ" "%1$s ፋይሎችን ወደ \"%2$s\" በመላክ ላይ" @@ -118,7 +114,6 @@ "አጽዳ" "አሁን እየተጫወተ ያለ" "የመተግበሪያ አዶ" - "የብሉቱዝ ኦዲዮ ተገናኝቷል" "የብሉቱዝ ኦዲዮ ግንኙነት ተቋርጧል" "የብሉቱዝ ኦዲዮ" "ከ4 ጊባ በላይ የሆኑ ፋይሎች ሊዛወሩ አይችሉም" diff --git a/android/app/res/values-am/test_strings.xml b/android/app/res/values-am/test_strings.xml deleted file mode 100644 index 371e4b3c119..00000000000 --- a/android/app/res/values-am/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ብሉቱዝ" - "መዝገብ አስገባ" - "መዝገብ አረጋግጥ" - "Ack መዝገብ" - "ሁሉንም መዝገብ ሰርዝ" - "እሺ" - "መዝገብ ሰርዝ" - "TCP አገልጋይን ጀምር" - "TCP አገልጋይን አሳውቅ" - diff --git a/android/app/res/values-ar/strings.xml b/android/app/res/values-ar/strings.xml index a4b90ce671c..8d877fe44c7 100644 --- a/android/app/res/values-ar/strings.xml +++ b/android/app/res/values-ar/strings.xml @@ -32,7 +32,6 @@ "هل تريد تفعيل البلوتوث الآن؟" "إلغاء" "تفعيل" - "نقل الملف" "هل تقبل الملف الوارد؟" "رفض" "قبول" @@ -42,10 +41,8 @@ "‏‫%1$s على استعداد لإرسال ملف: %2$s" "مشاركة البلوتوث: يتم استلام %1$s" "مشاركة البلوتوث: تم استلام %1$s" - "مشاركة البلوتوث: لم يتم استلام الملف %1$s" "مشاركة البلوتوث: يتم إرسال %1$s" "مشاركة البلوتوث: تم إرسال %1$s" - "اكتمل بنسبة 100%" "مشاركة البلوتوث: لم يتم إرسال الملف %1$s" "نقل الملف" "من: \"%1$s\"" @@ -80,7 +77,6 @@ "يرجى الانتظار…" "جارٍ تفعيل البلوتوث..." "سيتم استلام الملف. تحقق من التقدم في لوحة الإشعارات." - "لا يمكن تلقي الملف." "تم إيقاف استلام الملف من \"%1$s\"" "إرسال الملف إلى \"%1$s\"" "إرسال %1$s من الملفات إلى \"%2$s\"" @@ -118,7 +114,6 @@ "محو" "قيد التشغيل الآن" "رمز التطبيق" - "تم الاتصال بالبث الصوتي عبر البلوتوث." "انقطع الاتصال بالبث الصوتي عبر البلوتوث." "بث صوتي عبر البلوتوث" "يتعذّر نقل الملفات التي يزيد حجمها عن 4 غيغابايت" diff --git a/android/app/res/values-ar/test_strings.xml b/android/app/res/values-ar/test_strings.xml deleted file mode 100644 index 1b6a012a2ef..00000000000 --- a/android/app/res/values-ar/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "بلوتوث" - "إدراج سجل" - "تأكيد السجل" - "‏سجل Ack" - "حذف السجل كله" - "حسنًا" - "حذف السجل" - "‏بدء الخادم TCP" - "‏إعلام الخادم TCP" - diff --git a/android/app/res/values-as/strings.xml b/android/app/res/values-as/strings.xml index 734cc986ad5..27769419465 100644 --- a/android/app/res/values-as/strings.xml +++ b/android/app/res/values-as/strings.xml @@ -32,7 +32,6 @@ "এতিয়াই ব্লুটুথ অন কৰিবনে?" "বাতিল কৰক" "অন কৰক" - "ফাইল স্থানান্তৰণ" "অন্তৰ্গামী ফাইল গ্ৰহণ কৰিবনে?" "প্ৰত্যাখ্যান কৰক" "গ্ৰহণ কৰক" @@ -42,10 +41,8 @@ "%1$s এটা ফাইল পঠিয়াবলৈ সাজু: %2$s" "ব্লুটুথ শ্বেয়াৰ: %1$s লাভ কৰি থকা হৈছে" "ব্লুটুথ শ্বেয়াৰ: %1$s লাভ কৰা হ’ল" - "ব্লুটুথ শ্বেয়াৰ: ফাইল %1$s লাভ কৰা নহ\'ল" "ব্লুটুথ শ্বেয়াৰ: %1$s প্ৰেৰণ কৰি থকা হৈছে" "ব্লুটুথ শ্বেয়াৰ: %1$s প্ৰেৰণ কৰা হ’ল" - "১০০% সম্পূৰ্ণ হ’ল" "ব্লুটুথ শ্বেয়াৰ: ফাইল %1$s প্ৰেৰণ কৰা নহ\'ল" "ফাইল স্থানান্তৰণ" "প্ৰেৰক: \"%1$s\"" @@ -80,7 +77,6 @@ "অনুগ্ৰহ কৰি অপেক্ষা কৰক…" "ব্লুটুথ অন কৰি থকা হৈছে…" "ফাইলটো লাভ কৰা হ\'ব। জাননী পেনেলত অগ্ৰগতি নিৰীক্ষণ কৰক।" - "ফাইলটো লাভ কৰিব নোৱাৰি।" "\"%1$s\"ৰ ফাইল লাভ কৰা বন্ধ কৰা হ’ল" "\"%1$s\"লৈ ফাইল প্ৰেৰণ কৰি থকা হৈছে" "\"%2$s\"লৈ %1$sটা ফাইল পঠিয়াই থকা হৈছে" @@ -118,7 +114,6 @@ "মচক" "এতিয়া প্লে’ হৈ আছে" "এপ্লিকেশ্বন আইকন" - "ব্লুটুথ অডিঅ’ সংযুক্ত কৰা হ’ল" "ব্লুটুথ অডিঅ\'ৰ সৈতে সংযোগ বিচ্ছিন্ন কৰা হ’ল" "ব্লুটুথ অডিঅ\'" "৪ জি. বি. তকৈ ডাঙৰ ফাইল স্থানান্তৰ কৰিব নোৱাৰি" diff --git a/android/app/res/values-as/test_strings.xml b/android/app/res/values-as/test_strings.xml deleted file mode 100644 index 5d237a46ca7..00000000000 --- a/android/app/res/values-as/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ব্লুটুথ" - "ৰেকৰ্ড ভৰাওক" - "ৰেকৰ্ড নিশ্চিত কৰক" - "স্বীকৃত কৰা ৰেকৰ্ড" - "আটাইবোৰ ৰেকৰ্ড মচক" - "ঠিক" - "ৰেকৰ্ড মচক" - "TCP ছাৰ্ভাৰ আৰম্ভ কৰক" - "TCP ছাৰ্ভাৰক জাননী দিয়ক" - diff --git a/android/app/res/values-az/strings.xml b/android/app/res/values-az/strings.xml index 76a47acc551..afb5b586343 100644 --- a/android/app/res/values-az/strings.xml +++ b/android/app/res/values-az/strings.xml @@ -32,7 +32,6 @@ "İndi Bluetooth\'u yandıraq?" "Ləğv et" "Yandır" - "Fayl transferi" "Gələn fayl qəbul edilsin?" "İmtina edin" "Qəbul edirəm" @@ -42,10 +41,8 @@ "%1$s bu faylı göndərməyə hazırdır: %2$s" "Bluetooth paylaşım: %1$s qəbul edilir" "Bluetooth paylaşım: %1$s qəbul edildi" - "Bluetooth paylaşım: %1$s faylı qəbul edilmədi" "Bluetooth paylaşım: %1$s göndərilir" "Bluetooth paylaşım: %1$s göndərildi" - "100% tamamlandı" "Bluetooth paylaşım: %1$s göndərilmədi" "Fayl transferi" "Kimdən: \" %1$s \"" @@ -80,7 +77,6 @@ "Lütfən, gözləyin..." "Bluetooth yandırılır..." "Fayl qəbul ediləcək. Gedişatı Bildiriş panelində yoxlayın." - "Fayl qəbul edilə bilməz." "\"%1$s\" tərəfindən faylın göndərilməsi dayandırıldı" "\"%1$s\" adlı istifadəçiyə fayl göndərilir" "\"%2$s\" adlı istifadəçiyə %1$s fayl göndərilir" @@ -118,7 +114,6 @@ "Silin" "Hazırda oxudulan" "Tətbiq ikonası" - "Bluetooth audio bağlantısı yaradıldı" "Bluetooth audio ilə bağlantı kəsildi" "Bluetooth audio" "4GB-dən böyük olan faylları köçürmək mümkün deyil" diff --git a/android/app/res/values-az/test_strings.xml b/android/app/res/values-az/test_strings.xml deleted file mode 100644 index 18930b6aa5a..00000000000 --- a/android/app/res/values-az/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Qeyd daxil edin" - "Qeydi təsdiq edin" - "Ack qeydəalma" - "Bütün qeydləri silin" - "OK" - "Qeydi silin" - "TCP serverinə başlayın" - "TCP serverinə bildirin" - diff --git a/android/app/res/values-b+sr+Latn/strings.xml b/android/app/res/values-b+sr+Latn/strings.xml index 0e6bbad6fca..bda6d762401 100644 --- a/android/app/res/values-b+sr+Latn/strings.xml +++ b/android/app/res/values-b+sr+Latn/strings.xml @@ -32,7 +32,6 @@ "Želite li odmah da uključite Bluetooth?" "Otkaži" "Uključi" - "Prenos datoteke" "Želite li da prihvatite dolaznu datoteku?" "Odbij" "Prihvati" @@ -42,10 +41,8 @@ "%1$s je spreman/na za slanje fajla: %2$s" "Bluetooth deljenje: prijem %1$s" "Bluetooth deljenje: primljeno %1$s" - "Bluetooth deljenje: datoteka %1$s nije primljena" "Bluetooth deljenje: slanje %1$s" "Bluetooth deljenje: poslato %1$s" - "Dovršeno je 100%" "Bluetooth deljenje: datoteka %1$s nije poslata" "Prenos datoteke" "Od: „%1$s“" @@ -80,7 +77,6 @@ "Sačekajte…" "Uključivanje Bluetooth-a…" "Datoteka će biti primljena. Proveravajte tok na tabli sa obaveštenjima." - "Nije moguće primiti datoteku." "Zaustavljen prijem datoteke od pošiljaoca „%1$s“" "Slanje datoteke primaocu „%1$s“" "Slanje%1$s datoteka primaocu „%2$s“" @@ -118,7 +114,6 @@ "Brisanje" "Trenutno svira" "Ikona aplikacije" - "Bluetooth audio je povezan" "Veza sa Bluetooth audijom je prekinuta" "Bluetooth audio" "Ne mogu da se prenose datoteke veće od 4 GB" diff --git a/android/app/res/values-b+sr+Latn/test_strings.xml b/android/app/res/values-b+sr+Latn/test_strings.xml deleted file mode 100644 index b5938428ecf..00000000000 --- a/android/app/res/values-b+sr+Latn/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Umetni zapis" - "Potvrdi zapis" - "Ack zapis" - "Izbriši sve zapise" - "Potvrdi" - "Izbriši zapis" - "Pokreni TCP server" - "Obavesti TCP server" - diff --git a/android/app/res/values-be/strings.xml b/android/app/res/values-be/strings.xml index 37d06ae204b..93598cc71a7 100644 --- a/android/app/res/values-be/strings.xml +++ b/android/app/res/values-be/strings.xml @@ -32,7 +32,6 @@ "Уключыць Bluetooth зараз?" "Скасаваць" "Уключыць" - "Перадача файлаў" "Прыняць уваходны файл?" "Адхіліць" "Прыняць" @@ -42,10 +41,8 @@ "%1$s збіраецца адправіць файл %2$s" "Перадача праз Bluetooth: атрыманне файла %1$s" "Перадача праз Bluetooth: атрыманы файл %1$s" - "Перадача прз Bluetooth: файл %1$s не атрыманы" "Перадача праз Bluetooth: адпраўка файла %1$s" "Перадача праз Bluetooth: адпраўлены файл %1$s" - "Завершана 100%" "Перадача праз Bluetooth: файл %1$s не адпраўлены" "Перадача файлаў" "Ад: \"%1$s\"" @@ -80,7 +77,6 @@ "Чакайце..." "Уключэнне Bluetooth..." "Файл будзе атрыманы. Сачыце за прагрэсам на панэлі апавяшчэнняў." - "Немагчыма атрымаць файл." "Атрыманне файла ад адпраўніка \"%1$s\" спыненае" "Адпраўка файла атрымальніку \"%1$s\"" "Адпраўка файлаў (%1$s) атрымальніку \"%2$s\"" @@ -118,7 +114,6 @@ "Ачысціць" "Цяпер іграе" "Значок праграмы" - "Bluetooth-аўдыя падключана" "Bluetooth-аўдыя адключана" "Bluetooth-аўдыя" "Немагчыма перадаць файлы, большыя за 4 ГБ" diff --git a/android/app/res/values-be/test_strings.xml b/android/app/res/values-be/test_strings.xml deleted file mode 100644 index 54819d7fd21..00000000000 --- a/android/app/res/values-be/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Уставіць запіс" - "Пацвердзіць запіс" - "Запіс" - "Выдаліць усе запісы" - "ОК" - "Выдаліць запіс" - "Запусціць сервер TCP" - "Апавясцiць сервер TCP" - diff --git a/android/app/res/values-bg/strings.xml b/android/app/res/values-bg/strings.xml index 331dd5d2652..d5f636f07ae 100644 --- a/android/app/res/values-bg/strings.xml +++ b/android/app/res/values-bg/strings.xml @@ -32,7 +32,6 @@ "Включване на Bluetooth сега?" "Отказ" "Включване" - "Прехвърляне на файл" "Да се приеме ли входящият файл?" "Отхвърляне" "Приемане" @@ -42,10 +41,8 @@ "%1$s е в готовност за изпращане на файл: %2$s" "Споделяне чрез Bluetooth: %1$s се получава" "Споделяне чрез Bluetooth: %1$s се получи" - "Споделяне чрез Bluetooth: Файлът %1$s не е получен" "Споделяне чрез Bluetooth: %1$s се изпраща" "Споделяне чрез Bluetooth: %1$s се изпрати" - "100% завършено" "Споделяне чрез Bluetooth: Файлът %1$s не е изпратен" "Прехвърляне на файл" "От: „%1$s“" @@ -80,7 +77,6 @@ "Моля, изчакайте…" "Bluetooth се включва..." "Файлът ще бъде получен. Проверете хода в панела за известия." - "Файлът не може да бъде получен." "Получаването на файл от „%1$s“ спря" "Изпраща се файл до „%1$s“" "%1$s файла се изпращат до „%2$s“" @@ -118,7 +114,6 @@ "Изчистване" "Възпроизвеждано сега съдържание" "Икона на приложението" - "Установена е аудиовръзка през Bluetooth" "Аудиовръзката през Bluetooth е прекратена" "Аудио през Bluetooth" "Файловете с размер над 4 ГБ не могат да бъдат прехвърлени" diff --git a/android/app/res/values-bg/test_strings.xml b/android/app/res/values-bg/test_strings.xml deleted file mode 100644 index 0f16aaf9b01..00000000000 --- a/android/app/res/values-bg/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Вмъкване на запис" - "Потвърждение на записа" - "Запис на Ack" - "Изтриване на всички записи" - "OK" - "Изтриване на записа" - "Стартиране на TCP сървър" - "Известяване на TCP сървър" - diff --git a/android/app/res/values-bn/strings.xml b/android/app/res/values-bn/strings.xml index bbe0e28a19a..1092286aeca 100644 --- a/android/app/res/values-bn/strings.xml +++ b/android/app/res/values-bn/strings.xml @@ -32,7 +32,6 @@ "এখন ব্লুটুথ চালু করবেন?" "বাতিল করুন" "চালু করুন" - "ফাইল ট্রান্সফার" "আগত ফাইল স্বীকার করবেন?" "অস্বীকার করুন" "স্বীকার করুন" @@ -42,10 +41,8 @@ "%1$s এবার ফাইল পাঠাতে পারবে: %2$s" "ব্লুটুথ share: %1$s প্রাপ্ত করা হচ্ছে" "ব্লুটুথ share: %1$s প্রাপ্ত করা হয়েছে" - "ব্লুটুথ share: %1$s ফাইল প্রাপ্ত করা হয়নি" "ব্লুটুথ শেয়ার: %1$s পাঠানো হচ্ছে" "ব্লুটুথ শেয়ার: %1$s পাঠানো হয়েছে" - "১০০% সম্পূর্ণ" "ব্লুটুথ share: %1$s ফাইল পাঠানো হয়নি" "ফাইল ট্রান্সফার" "প্রেরক: \"%1$s\"" @@ -80,7 +77,6 @@ "দয়া করে অপেক্ষা করুন..." "ব্লুটুথ চালু করা হচ্ছে..." "ফাইল প্রাপ্ত করা হবে। বিজ্ঞপ্তি প্যানেলে প্রগতি চেক করুন।" - "ফাইল প্রাপ্ত করা যাবে না।" "\"%1$s\" এর থেকে ফাইল পাওয়া বন্ধ করা হয়েছে" "\"%1$s\" কে ফাইল পাঠানো হচ্ছে" "\"%2$s\" কে %1$sটি ফাইল পাঠানো হচ্ছে" @@ -118,7 +114,6 @@ "সাফ করুন" "এখন চলছে" "অ্যাপ্লিকেশান আইকন" - "ব্লুটুথ অডিও সংযুক্ত হয়েছে" "ব্লুটুথ অডিওর সংযোগ বিচ্ছিন্ন হয়েছে" "ব্লুটুথ অডিও" "৪GB থেকে বড় ফটো ট্রান্সফার করা যাবে না" diff --git a/android/app/res/values-bn/test_strings.xml b/android/app/res/values-bn/test_strings.xml deleted file mode 100644 index 60f7742bd33..00000000000 --- a/android/app/res/values-bn/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ব্লুটুথ" - "রেকর্ড ঢোকান" - "রেকর্ড নিশ্চিত করুন" - "Ack রেকর্ড" - "সব রেকর্ড মুছে দিন" - "ঠিক আছে" - "রেকর্ড মুছে দিন" - "TCP সার্ভার শুরু করুন" - "TCP সার্ভার সূচিত করুন" - diff --git a/android/app/res/values-bs/strings.xml b/android/app/res/values-bs/strings.xml index 059fbd2d2f8..9a3ba14c7fa 100644 --- a/android/app/res/values-bs/strings.xml +++ b/android/app/res/values-bs/strings.xml @@ -32,7 +32,6 @@ "Želite uključiti Bluetooth sada?" "Otkaži" "Uključi" - "Prenošenje fajla" "Prihvatiti dolazni fajl?" "Odbij" "Prihvati" @@ -42,10 +41,8 @@ "%1$s je spreman/na za slanje fajla: %2$s" "Bluetooth dijeljenje: primanje fajla %1$s" "Bluetooth dijeljenje: Primljen fajl %1$s" - "Bluetooth dijeljenje: Fajl %1$s nije primljen" "Bluetooth dijeljenje: slanje fajla %1$s" "Bluetooth dijeljenje: poslan fajl %1$s" - "Dovršeno 100%" "Bluetooth dijeljenje: Fajl %1$s nije poslan" "Prenošenje fajla" "Šalje: \"%1$s\"" @@ -80,7 +77,6 @@ "Pričekajte…" "Uključuje se Bluetooth…" "Fajl će biti primljen. Pratite napredak u Ploči s obavještenjima." - "Nije moguće primiti fajl." "Zaustavljeno primanje fajla kojeg šalje \"%1$s\"" "Slanje fajla kojeg prima \"%1$s\"" "Slanje %1$s fajl(ov)a, prima \"%2$s\"" @@ -118,7 +114,6 @@ "Obriši" "Trenutno se reproducira" "Ikona aplikacije" - "Bluetooth audio je povezan" "Bluetooth audio je isključen" "Bluetooth Audio" "Nije moguće prenijeti fajlove veće od 4 GB" diff --git a/android/app/res/values-bs/test_strings.xml b/android/app/res/values-bs/test_strings.xml deleted file mode 100644 index ba0f8b74f12..00000000000 --- a/android/app/res/values-bs/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Umetni zapis" - "Potvrdi zapis" - "Evidencija Ack" - "Izbriši svu evidenciju" - "Uredu" - "Izbriši evidenciju" - "Pokreni TCP server" - "Obavijesti TCP server" - diff --git a/android/app/res/values-ca/strings.xml b/android/app/res/values-ca/strings.xml index 10f47cd46b8..695301fe791 100644 --- a/android/app/res/values-ca/strings.xml +++ b/android/app/res/values-ca/strings.xml @@ -32,7 +32,6 @@ "Vols activar el Bluetooth ara?" "Cancel·la" "Activa" - "Transferència de fitxers" "Acceptes el fitxer entrant?" "Rebutja" "Accepta" @@ -42,10 +41,8 @@ "%1$s està a punt per enviar un fitxer: %2$s" "Bluetooth: s\'està rebent %1$s" "Bluetooth: %1$s rebut" - "Bluetooth: %1$s no rebut" "Bluetooth: s\'està enviant %1$s" "Bluetooth: %1$s enviat" - "100% complet" "Bluetooth: %1$s no enviat" "Transferència de fitxers" "De: \"%1$s\"" @@ -80,7 +77,6 @@ "Espereu…" "S\'està activant el Bluetooth..." "El fitxer es rebrà. Comproveu-ne el progrés al tauler de notificacions." - "No es pot rebre el fitxer." "S\'ha aturat la recepció del fitxer de \"%1$s\"" "S\'està enviant el fitxer a \"%1$s\"" "S\'estan enviant %1$s fitxers a \"%2$s\"" @@ -118,7 +114,6 @@ "Esborra" "Reproducció actual" "Icona d\'aplicació" - "Àudio per Bluetooth connectat" "Àudio per Bluetooth desconnectat" "Àudio per Bluetooth" "No es poden transferir fitxers més grans de 4 GB" diff --git a/android/app/res/values-ca/test_strings.xml b/android/app/res/values-ca/test_strings.xml deleted file mode 100644 index 258b3b89ad9..00000000000 --- a/android/app/res/values-ca/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insereix un registre" - "Confirma el registre" - "Registre de notificacions" - "Suprimeix tots els registres" - "D\'acord" - "Suprimeix el registre" - "Inicia el servidor TCP" - "Notifica-ho al servidor TCP" - diff --git a/android/app/res/values-cs/strings.xml b/android/app/res/values-cs/strings.xml index 391d36bb621..766f4f5cafe 100644 --- a/android/app/res/values-cs/strings.xml +++ b/android/app/res/values-cs/strings.xml @@ -32,7 +32,6 @@ "Zapnout Bluetooth?" "Zrušit" "Zapnout" - "Přenos souborů" "Přijmout příchozí soubor?" "Odmítnout" "Přijmout" @@ -42,10 +41,8 @@ "%1$s může odeslat soubor: %2$s" "Sdílení Bluetooth: Příjem souboru %1$s" "Sdílení Bluetooth: Soubor %1$s byl přijat" - "Sdílení Bluetooth: Soubor %1$s nebyl přijat" "Sdílení Bluetooth: Odesílání souboru %1$s" "Sdílení Bluetooth: Soubor %1$s byl odeslán" - "Dokončeno 100 %" "Sdílení Bluetooth: Soubor %1$s nebyl odeslán" "Přenos souborů" "Od: %1$s" @@ -80,7 +77,6 @@ "Čekejte prosím..." "Zapínání Bluetooth…" "Proběhne přijímání souboru. Průběh můžete sledovat na panelu Oznámení." - "Soubor nelze přijmout." "Příjem souboru od uživatele %1$s byl zastaven" "Odesílání souboru uživateli %1$s" "Odesílání %1$s souborů uživateli %2$s" @@ -118,7 +114,6 @@ "Vymazat" "Co to hraje" "Ikona aplikace" - "Bluetooth Audio – připojeno" "Bluetooth Audio – odpojeno" "Bluetooth Audio" "Soubory větší než 4 GB nelze přenést" diff --git a/android/app/res/values-cs/test_strings.xml b/android/app/res/values-cs/test_strings.xml deleted file mode 100644 index e73f5ae988a..00000000000 --- a/android/app/res/values-cs/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Vložit záznam" - "Potvrdit záznam" - "Záznam ACK" - "Smazat všechny záznamy" - "OK" - "Smazat záznam" - "Spustit server TCP" - "Upozornit server TCP" - diff --git a/android/app/res/values-da/strings.xml b/android/app/res/values-da/strings.xml index 96424f5b9e8..3ab8898b79b 100644 --- a/android/app/res/values-da/strings.xml +++ b/android/app/res/values-da/strings.xml @@ -32,7 +32,6 @@ "Vil du slå Bluetooth til nu?" "Annuller" "Slå til" - "Filoverførsel" "Vil du acceptere den indgående fil?" "Afvis" "Accepter" @@ -42,10 +41,8 @@ "%1$s er klar til at sende en fil: %2$s" "Bluetooth-deling: Modtager %1$s" "Bluetooth-deling: Modtog %1$s" - "Bluetooth-deling: Filen %1$s blev ikke modtaget" "Bluetooth-deling: Sender %1$s" "Bluetooth-deling: Sendt %1$s" - "100 % fuldført" "Bluetooth-deling: Filen %1$s blev ikke sendt" "Filoverførsel" "Fra: \"%1$s\"" @@ -80,7 +77,6 @@ "Vent..." "Aktiverer Bluetooth..." "Filen modtages. Se status i underretningspanelet." - "Filen kan ikke modtages." "Modtagelse af fil fra \"%1$s\" stoppet" "Sender filen til \"%1$s\"" "Sender %1$s filer til \"%2$s\"" @@ -118,7 +114,6 @@ "Ryd" "Afspiller nu" "Appens ikon" - "Bluetooth-lyden blev tilsluttet" "Bluetooth-lyden blev afbrudt" "Bluetooth-lyd" "File, der er større end 4 GB, kan ikke overføres" diff --git a/android/app/res/values-da/test_strings.xml b/android/app/res/values-da/test_strings.xml deleted file mode 100644 index 7aaecefcfd0..00000000000 --- a/android/app/res/values-da/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Indsæt post" - "Bekræft post" - "Ack-post" - "Slet alle poster" - "OK" - "Slet post" - "Start TCP-server" - "Meddel TCP-server" - diff --git a/android/app/res/values-de/strings.xml b/android/app/res/values-de/strings.xml index ce8106facd6..bf93f571ce8 100644 --- a/android/app/res/values-de/strings.xml +++ b/android/app/res/values-de/strings.xml @@ -32,7 +32,6 @@ "Bluetooth jetzt aktivieren?" "Abbrechen" "Aktivieren" - "Dateiübertragung" "Eingehende Datei annehmen?" "Ablehnen" "Akzeptieren" @@ -42,10 +41,8 @@ "%1$s ist bereit, eine Datei zu senden: %2$s" "Bluetooth-Freigabe: %1$s wird empfangen" "Bluetooth-Freigabe: %1$s wurde empfangen" - "Bluetooth-Freigabe: %1$s wurde nicht empfangen" "Bluetooth-Freigabe: %1$s wird gesendet" "Bluetooth-Freigabe: %1$s gesendet" - "Zu 100 % abgeschlossen" "Bluetooth-Freigabe: %1$s wurde nicht gesendet" "Dateiübertragung" "Von: \"%1$s\"" @@ -80,7 +77,6 @@ "Bitte warten..." "Bluetooth wird aktiviert..." "Die Datei wird empfangen. Überprüfe den Fortschritt in der Benachrichtigungskonsole." - "Die Datei kann nicht empfangen werden." "Der Empfang der Datei von \"%1$s\" wurde angehalten." "Datei wird an „%1$s“ gesendet..." "%1$s Dateien werden an \"%2$s\" gesendet." @@ -118,7 +114,6 @@ "Löschen" "Now Playing" "App-Symbol" - "Bluetooth-Audio verbunden" "Bluetooth-Audio-Verbindung aufgehoben" "Bluetooth-Audio" "Dateien mit mehr als 4 GB können nicht übertragen werden" diff --git a/android/app/res/values-de/test_strings.xml b/android/app/res/values-de/test_strings.xml deleted file mode 100644 index 113aae53f0b..00000000000 --- a/android/app/res/values-de/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Aufnahme einfügen" - "Aufnahme bestätigen" - "Aufnahme bestätigen" - "Gesamte Aufnahme löschen" - "Ok" - "Aufnahme löschen" - "TCP-Server starten" - "TCP-Server benachrichtigen" - diff --git a/android/app/res/values-el/strings.xml b/android/app/res/values-el/strings.xml index 982282e4e21..edf35287382 100644 --- a/android/app/res/values-el/strings.xml +++ b/android/app/res/values-el/strings.xml @@ -32,7 +32,6 @@ "Να γίνει τώρα ενεργοποίηση του Bluetooth;" "Ακύρωση" "Ενεργοποίηση" - "Μεταφορά αρχείου" "Αποδοχή εισερχόμενου αρχείου;" "Απόρριψη" "Αποδοχή" @@ -42,10 +41,8 @@ "Ο χρήστης %1$s είναι έτοιμος να στείλει ένα αρχείο: %2$s" "Μοιραστείτε μέσω Bluetooth: Λήψη του %1$s" "Μοιραστείτε μέσω Bluetooth: Ελήφθη το %1$s" - "Μοιραστείτε μέσω Bluetooth: Το αρχείο %1$s δεν ελήφθη" "Μοιραστείτε με Bluetooth: Αποστολή του %1$s" "Μοιραστείτε με Bluetooth: %1$s" - "Ολοκληρώθηκε το 100%" "Μοιραστείτε μέσω Bluetooth: Το αρχείο %1$s δεν εστάλη" "Μεταφορά αρχείου" "Από: \"%1$s\"" @@ -80,7 +77,6 @@ "Περιμένετε..." "Ενεργοποίηση Bluetooth…" "Θα γίνει λήψη του αρχείου. Ελέγξτε την πρόοδο στο πλαίσιο \"Ειδοποιήσεις\"." - "Δεν είναι δυνατή η παραλαβή του αρχείου." "Διακόπηκε η λήψη του αρχείου από τον αποστολέα \"%1$s\"" "Γίνεται αποστολή του αρχείου στον παραλήπτη \"%1$s\"" "Αποστολή %1$s αρχείων στον παραλήπτη \"%2$s\"" @@ -118,7 +114,6 @@ "Διαγραφή" "Ακούγεται τώρα" "Εικονίδιο εφαρμογής" - "Ο ήχος Bluetooth συνδέθηκε" "Ο ήχος Bluetooth αποσυνδέθηκε" "Ήχος Bluetooth" "Δεν είναι δυνατή η μεταφορά αρχείων που ξεπερνούν τα 4 GB" diff --git a/android/app/res/values-el/test_strings.xml b/android/app/res/values-el/test_strings.xml deleted file mode 100644 index fbc639cb169..00000000000 --- a/android/app/res/values-el/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Εισαγωγή αρχείου" - "Επιβεβαίωση αρχείου" - "Αρχείο ack" - "Διαγραφή όλων των αρχείων" - "ΟΚ" - "Διαγραφή αρχείου" - "Εκκίνηση διακομιστή TCP" - "Να ειδοποιείται ο διακομιστής TCP" - diff --git a/android/app/res/values-en-rAU/strings.xml b/android/app/res/values-en-rAU/strings.xml index 2d94f0abc9d..38dcc8a3284 100644 --- a/android/app/res/values-en-rAU/strings.xml +++ b/android/app/res/values-en-rAU/strings.xml @@ -32,7 +32,6 @@ "Turn on Bluetooth now?" "Cancel" "Turn on" - "File transfer" "Accept incoming file?" "Decline" "Accept" @@ -42,10 +41,8 @@ "%1$s is ready to send a file: %2$s" "Bluetooth share: Receiving %1$s" "Bluetooth share: Received %1$s" - "Bluetooth share: File %1$s not received" "Bluetooth share: Sending %1$s" "Bluetooth share: Sent %1$s" - "100% complete" "Bluetooth share: File %1$s not sent" "File transfer" "From: \"%1$s\"" @@ -80,7 +77,6 @@ "Please wait…" "Turning on Bluetooth…" "The file will be received. Check progress in the Notifications panel." - "The file can\'t be received." "Stopped receiving file from \"%1$s\"" "Sending file to \"%1$s\"" "Sending %1$s files to \"%2$s\"" @@ -118,7 +114,6 @@ "Clear" "Now playing" "Application icon" - "Bluetooth audio connected" "Bluetooth audio disconnected" "Bluetooth audio" "Files bigger than 4 GB cannot be transferred" diff --git a/android/app/res/values-en-rAU/test_strings.xml b/android/app/res/values-en-rAU/test_strings.xml deleted file mode 100644 index d83ac6db891..00000000000 --- a/android/app/res/values-en-rAU/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insert record" - "Confirm record" - "Ack record" - "Delete all record" - "OK" - "Delete record" - "Start TCP server" - "Notify TCP server" - diff --git a/android/app/res/values-en-rCA/strings.xml b/android/app/res/values-en-rCA/strings.xml index a230e2b6058..61bc2f858b5 100644 --- a/android/app/res/values-en-rCA/strings.xml +++ b/android/app/res/values-en-rCA/strings.xml @@ -32,7 +32,6 @@ "Turn on Bluetooth now?" "Cancel" "Turn on" - "File transfer" "Accept incoming file?" "Decline" "Accept" @@ -42,10 +41,8 @@ "%1$s is ready to send a file: %2$s" "Bluetooth share: Receiving %1$s" "Bluetooth share: Received %1$s" - "Bluetooth share: File %1$s not received" "Bluetooth share: Sending %1$s" "Bluetooth share: Sent %1$s" - "100% complete" "Bluetooth share: File %1$s not sent" "File transfer" "From: \"%1$s\"" @@ -80,7 +77,6 @@ "Please wait…" "Turning on Bluetooth…" "The file will be received. Check progress in the Notifications panel." - "The file can\'t be received." "Stopped receiving file from \"%1$s\"" "Sending file to \"%1$s\"" "Sending %1$s files to \"%2$s\"" @@ -118,7 +114,6 @@ "Clear" "Now Playing" "Application Icon" - "Bluetooth audio connected" "Bluetooth audio disconnected" "Bluetooth Audio" "Files bigger than 4GB cannot be transferred" diff --git a/android/app/res/values-en-rCA/test_strings.xml b/android/app/res/values-en-rCA/test_strings.xml deleted file mode 100644 index d83ac6db891..00000000000 --- a/android/app/res/values-en-rCA/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insert record" - "Confirm record" - "Ack record" - "Delete all record" - "OK" - "Delete record" - "Start TCP server" - "Notify TCP server" - diff --git a/android/app/res/values-en-rGB/strings.xml b/android/app/res/values-en-rGB/strings.xml index 2d94f0abc9d..38dcc8a3284 100644 --- a/android/app/res/values-en-rGB/strings.xml +++ b/android/app/res/values-en-rGB/strings.xml @@ -32,7 +32,6 @@ "Turn on Bluetooth now?" "Cancel" "Turn on" - "File transfer" "Accept incoming file?" "Decline" "Accept" @@ -42,10 +41,8 @@ "%1$s is ready to send a file: %2$s" "Bluetooth share: Receiving %1$s" "Bluetooth share: Received %1$s" - "Bluetooth share: File %1$s not received" "Bluetooth share: Sending %1$s" "Bluetooth share: Sent %1$s" - "100% complete" "Bluetooth share: File %1$s not sent" "File transfer" "From: \"%1$s\"" @@ -80,7 +77,6 @@ "Please wait…" "Turning on Bluetooth…" "The file will be received. Check progress in the Notifications panel." - "The file can\'t be received." "Stopped receiving file from \"%1$s\"" "Sending file to \"%1$s\"" "Sending %1$s files to \"%2$s\"" @@ -118,7 +114,6 @@ "Clear" "Now playing" "Application icon" - "Bluetooth audio connected" "Bluetooth audio disconnected" "Bluetooth audio" "Files bigger than 4 GB cannot be transferred" diff --git a/android/app/res/values-en-rGB/test_strings.xml b/android/app/res/values-en-rGB/test_strings.xml deleted file mode 100644 index d83ac6db891..00000000000 --- a/android/app/res/values-en-rGB/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insert record" - "Confirm record" - "Ack record" - "Delete all record" - "OK" - "Delete record" - "Start TCP server" - "Notify TCP server" - diff --git a/android/app/res/values-en-rIN/strings.xml b/android/app/res/values-en-rIN/strings.xml index 2d94f0abc9d..38dcc8a3284 100644 --- a/android/app/res/values-en-rIN/strings.xml +++ b/android/app/res/values-en-rIN/strings.xml @@ -32,7 +32,6 @@ "Turn on Bluetooth now?" "Cancel" "Turn on" - "File transfer" "Accept incoming file?" "Decline" "Accept" @@ -42,10 +41,8 @@ "%1$s is ready to send a file: %2$s" "Bluetooth share: Receiving %1$s" "Bluetooth share: Received %1$s" - "Bluetooth share: File %1$s not received" "Bluetooth share: Sending %1$s" "Bluetooth share: Sent %1$s" - "100% complete" "Bluetooth share: File %1$s not sent" "File transfer" "From: \"%1$s\"" @@ -80,7 +77,6 @@ "Please wait…" "Turning on Bluetooth…" "The file will be received. Check progress in the Notifications panel." - "The file can\'t be received." "Stopped receiving file from \"%1$s\"" "Sending file to \"%1$s\"" "Sending %1$s files to \"%2$s\"" @@ -118,7 +114,6 @@ "Clear" "Now playing" "Application icon" - "Bluetooth audio connected" "Bluetooth audio disconnected" "Bluetooth audio" "Files bigger than 4 GB cannot be transferred" diff --git a/android/app/res/values-en-rIN/test_strings.xml b/android/app/res/values-en-rIN/test_strings.xml deleted file mode 100644 index d83ac6db891..00000000000 --- a/android/app/res/values-en-rIN/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insert record" - "Confirm record" - "Ack record" - "Delete all record" - "OK" - "Delete record" - "Start TCP server" - "Notify TCP server" - diff --git a/android/app/res/values-en-rXC/strings.xml b/android/app/res/values-en-rXC/strings.xml index b5e59d80061..cd09708e6f0 100644 --- a/android/app/res/values-en-rXC/strings.xml +++ b/android/app/res/values-en-rXC/strings.xml @@ -32,7 +32,6 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎Turn on Bluetooth now?‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‎Cancel‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎Turn on‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‎‎File transfer‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎Accept incoming file?‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‎Decline‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‎Accept‎‏‎‎‏‎" @@ -42,10 +41,8 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ is ready to send a file: ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎Bluetooth share: Receiving ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎Bluetooth share: Received ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‏‎‎Bluetooth share: File ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ not received‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎Bluetooth share: Sending ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎Bluetooth share: Sent ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎100% complete‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‏‎Bluetooth share: File ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ not sent‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎File transfer‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‎From: \"‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎\"‎‏‎‎‏‎" @@ -80,7 +77,6 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎Please wait…‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎Turning on Bluetooth…‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎The file will be received. Check progress in the Notifications panel.‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎‏‏‎‏‎‎The file can\'t be received.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎Stopped receiving file from \"‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎\"‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎Sending file to \"‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎\"‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‎Sending ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ files to \"‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎\"‎‏‎‎‏‎" @@ -118,7 +114,6 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎Clear‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎Now Playing‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎Application Icon‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‏‏‎Bluetooth audio connected‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎Bluetooth audio disconnected‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎Bluetooth Audio‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎Files bigger than 4GB cannot be transferred‎‏‎‎‏‎" diff --git a/android/app/res/values-en-rXC/test_strings.xml b/android/app/res/values-en-rXC/test_strings.xml deleted file mode 100644 index 245dbdad73b..00000000000 --- a/android/app/res/values-en-rXC/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎Bluetooth‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎Insert record‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎Confirm record‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎Ack record‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‎Delete all record‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎OK‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎Delete record‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎Start TCP server‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎Notify TCP server‎‏‎‎‏‎" - diff --git a/android/app/res/values-es-rUS/strings.xml b/android/app/res/values-es-rUS/strings.xml index fcd4d0e4017..ef3f2e72a4b 100644 --- a/android/app/res/values-es-rUS/strings.xml +++ b/android/app/res/values-es-rUS/strings.xml @@ -32,7 +32,6 @@ "¿Deseas activar el Bluetooth ahora?" "Cancelar" "Activar" - "Transferencia de archivo" "¿Aceptar archivo entrante?" "Rechazar" "Aceptar" @@ -42,10 +41,8 @@ "%1$s está listo para enviar un archivo: %2$s" "Bluetooth: recibiendo %1$s" "Bluetooth: %1$s recibido" - "Bluetooth: no se recibió el archivo %1$s" "Bluetooth: enviando %1$s" "Bluetooth: %1$s enviado" - "Completado el 100%" "Bluetooth: no se envió el archivo %1$s" "Transferencia de archivo" "De: \"%1$s\"" @@ -80,7 +77,6 @@ "Por favor, espera..." "Activando Bluetooth..." "El archivo será recibido. Verifica el progreso en el panel de notificaciones." - "No se puede recibir el archivo." "Se detuvo la recepción del archivo de \"%1$s\"" "Enviando archivo a \"%1$s\"" "Enviando %1$s archivos a \"%2$s\"" @@ -118,7 +114,6 @@ "Eliminar" "Está sonando" "Ícono de la aplicación" - "Audio Bluetooth conectado" "Audio Bluetooth desconectado" "Audio Bluetooth" "No se pueden transferir los archivos de más de 4 GB" diff --git a/android/app/res/values-es-rUS/test_strings.xml b/android/app/res/values-es-rUS/test_strings.xml deleted file mode 100644 index 0e1ea89ed19..00000000000 --- a/android/app/res/values-es-rUS/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insertar grabación" - "Confirmar grabación" - "Confirmación de la grabación" - "Eliminar todas las grabaciones" - "Aceptar" - "Eliminar grabación" - "Iniciar el servidor TCP" - "Notificar al servidor TCP" - diff --git a/android/app/res/values-es/strings.xml b/android/app/res/values-es/strings.xml index ae37a245468..7ac1db5eb99 100644 --- a/android/app/res/values-es/strings.xml +++ b/android/app/res/values-es/strings.xml @@ -32,7 +32,6 @@ "¿Quieres activar la función Bluetooth ahora?" "Cancelar" "Activar" - "Transferencia de archivos" "¿Aceptar archivo entrante?" "Rechazar" "Aceptar" @@ -42,10 +41,8 @@ "%1$s está listo para enviar un archivo: %2$s" "Bluetooth: recibiendo %1$s" "Compartir con Bluetooth: %1$s recibido" - "Bluetooth: %1$s no recibido" "Bluetooth: enviando %1$s" "Bluetooth: %1$s enviado" - "100% completado" "Bluetooth: archivo %1$s no enviado" "Transferencia de archivos" "De: \"%1$s\"" @@ -80,7 +77,6 @@ "Por favor, espera..." "Activando Bluetooth..." "Se recibirá el archivo. Comprueba el progreso en la barra de notificaciones." - "No se puede recibir el archivo." "Se ha detenido la recepción del archivo de \"%1$s\"" "Enviando archivo a \"%1$s\"" "Enviando %1$s archivos a \"%2$s\"" @@ -118,7 +114,6 @@ "Borrar" "Reproduciendo" "Icono de aplicación" - "Audio por Bluetooth conectado" "Audio por Bluetooth desconectado" "Audio por Bluetooth" "No se pueden transferir archivos de más de 4 GB" diff --git a/android/app/res/values-es/test_strings.xml b/android/app/res/values-es/test_strings.xml deleted file mode 100644 index 1f3caa9522e..00000000000 --- a/android/app/res/values-es/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insertar grabación" - "Confirmar grabación" - "Confirmar grabación" - "Eliminar todas las grabaciones" - "Aceptar" - "Eliminar grabación" - "Iniciar servidor TCP" - "Informar al servidor TCP" - diff --git a/android/app/res/values-et/strings.xml b/android/app/res/values-et/strings.xml index f246f9dbc9a..9781e789830 100644 --- a/android/app/res/values-et/strings.xml +++ b/android/app/res/values-et/strings.xml @@ -32,7 +32,6 @@ "Lülitan Bluetoothi kohe sisse?" "Tühista" "Lülita sisse" - "Failiedastus" "Kas aktsepteerida sissetulev fail?" "Keeldu" "Nõustun" @@ -42,10 +41,8 @@ "%1$s on valmis faili %2$s saatma" "Bluetoothi jagamine: faili %1$s vastuvõtmine" "Bluetoothi jagamine: %1$s vastu võetud" - "Bluetoothi jagamine: faili %1$s pole saadud" "Bluetoothi jagamine: faili %1$s saatmine" "Bluetoothi jagamine: fail %1$s saadetud" - "100% lõpetatud" "Bluetoothi jagamine: faili %1$s ei saadetud" "Failiedastus" "Saatja: „%1$s”" @@ -80,7 +77,6 @@ "Palun oodake ..." "Bluetoothi sisselülitamine ..." "Fail võetakse vastu. Vaadake edenemist teatiste paneelil." - "Faili ei saa vastu võtta." "Faili vastuvõtmine saatjalt „%1$s” peatatud" "Faili saatmine saajale „%1$s”" "%1$s faili saatmine saajale „%2$s”" @@ -118,7 +114,6 @@ "Kustuta" "Hetkel mängimas" "Rakenduse ikoon" - "Bluetoothi heli on ühendatud" "Bluetoothi heli ühendus on katkestatud" "Bluetoothi heli" "Faile, mis on üle 4 GB, ei saa üle kanda" diff --git a/android/app/res/values-et/test_strings.xml b/android/app/res/values-et/test_strings.xml deleted file mode 100644 index b0d85f9d56a..00000000000 --- a/android/app/res/values-et/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Sisestage kirje" - "Kinnita kirje" - "Acki kirje" - "Kustuta kõik kirjed" - "OK" - "Kustuta kirje" - "Käivita TCP-server" - "Teavita TCP-serverit" - diff --git a/android/app/res/values-eu/strings.xml b/android/app/res/values-eu/strings.xml index 0c4f7f8d5e8..d4b76277dff 100644 --- a/android/app/res/values-eu/strings.xml +++ b/android/app/res/values-eu/strings.xml @@ -32,7 +32,6 @@ "Bluetootha aktibatu nahi duzu?" "Utzi" "Aktibatu" - "Fitxategi-transferentzia" "Sarrerako fitxategia onartu nahi duzu?" "Baztertu" "Onartu" @@ -42,10 +41,8 @@ "%1$s igorlea prest dago fitxategi hau bidaltzeko: %2$s" "Bluetooth bidez partekatzea: %1$s jasotzen" "Bluetooth bidez partekatzea: %1$s fitxategia jaso da" - "Bluetooth bidez partekatzea: ez da jaso %1$s fitxategia" "Bluetooth bidez partekatzea: %1$s bidaltzen" "Bluetooth bidez partekatzea: %1$s bidali da" - "% 100ean osatuta" "Bluetooth bidez partekatzea: ez da bidali %1$s fitxategia" "Fitxategi-transferentzia" "Igorlea: \"%1$s\"" @@ -80,7 +77,6 @@ "Itxaron…" "Bluetootha aktibatzen…" "Fitxategia jasoko da. Egoera kontrolatzeko, joan Jakinarazpenen panelera." - "Ezin da fitxategia jaso." "\"%1$s\" igorlearen fitxategia jasotzeari utzi zaio" "\"%1$s\" hartzaileari fitxategia bidaltzen" "\"%2$s\" hartzaileari %1$s fitxategi bidaltzen" @@ -118,7 +114,6 @@ "Garbitu" "Orain erreproduzitzen" "Aplikazioaren ikonoa" - "Konektatu da Bluetooth bidezko audioa" "Deskonektatu da Bluetooth bidezko audioa" "Bluetooth bidezko audioa" "Ezin dira transferitu 4 GB baino gehiagoko fitxategiak" diff --git a/android/app/res/values-eu/test_strings.xml b/android/app/res/values-eu/test_strings.xml deleted file mode 100644 index 4c501ab19e1..00000000000 --- a/android/app/res/values-eu/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetootha" - "Sartu erregistroa" - "Berretsi erregistroa" - "ACK erregistroa" - "Ezabatu erregistro guztiak" - "Ados" - "Ezabatu erregistroa" - "Hasi TCP zerbitzaria" - "Jakinarazi TCP zerbitzariari" - diff --git a/android/app/res/values-fa/strings.xml b/android/app/res/values-fa/strings.xml index 17519b7d375..ce0c2198234 100644 --- a/android/app/res/values-fa/strings.xml +++ b/android/app/res/values-fa/strings.xml @@ -32,7 +32,6 @@ "اکنون بلوتوث روشن شود؟" "لغو" "روشن کردن" - "انتقال فایل" "فایل ورودی پذیرفته شود؟" "نپذیرفتن" "پذیرفتن" @@ -42,10 +41,8 @@ "‏%1$s آماده ارسال فایل است: %2$s" "اشتراک بلوتوث: در حال دریافت %1$s" "اشتراک بلوتوث: %1$s دریافت شد" - "اشتراک بلوتوث: فایل %1$sدریافت نشد" "اشتراک بلوتوث: در حال ارسال %1$s" "اشتراک بلوتوث:%1$s ارسال شد" - "100% کامل شد" "اشتراک بلوتوث: فایل %1$s ارسال نشد" "انتقال فایل" "از: \"%1$s\"" @@ -80,7 +77,6 @@ "لطفاً منتظر بمانید…" "روشن کردن بلوتوث…" "فایل دریافت می‌شود: پیشرفت دریافت را در پانل اعلان‌ها بررسی کنید." - "فایل را نمی‌توان دریافت کرد." "دریافت فایل از \"%1$s\" متوقف شد" "ارسال فایل به \"%1$s\"" "ارسال %1$s فایل به \"%2$s\"" @@ -118,7 +114,6 @@ "پاک کردن" "درحال پخش" "نماد برنامه" - "بلوتوث صوتی متصل شد" "ارتباط بلوتوث صوتی قطع شد" "بلوتوث‌ صوتی" "فایل‌های بزرگ‌تر از ۴ گیگابایت نمی‌توانند منتقل شوند" diff --git a/android/app/res/values-fa/test_strings.xml b/android/app/res/values-fa/test_strings.xml deleted file mode 100644 index 83b828a4653..00000000000 --- a/android/app/res/values-fa/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "بلوتوث" - "درج سابقه" - "تأیید سابقه" - "‏سابقه Ack" - "حذف همه سابقه" - "تأیید" - "حذف سابقه" - "‏راه‌اندازی سرور TCP" - "‏اعلان سرور TCP" - diff --git a/android/app/res/values-fi/strings.xml b/android/app/res/values-fi/strings.xml index c74ef126688..e2d29d7f8ef 100644 --- a/android/app/res/values-fi/strings.xml +++ b/android/app/res/values-fi/strings.xml @@ -32,7 +32,6 @@ "Otetaanko Bluetooth käyttöön nyt?" "Peru" "Laita päälle" - "Tiedostonsiirto" "Hyväksytäänkö saapuva tiedosto?" "Hylkää" "Hyväksy" @@ -42,10 +41,8 @@ "%1$s on valmis lähettämään tiedoston: %2$s" "Bluetooth-jako: vastaanotetaan tiedostoa %1$s" "Bluetooth-jako: %1$s vastaanotettu" - "Bluetooth-jako: tiedostoa %1$s ei vastaanotettu" "Bluetooth-jako: lähetetään tiedostoa %1$s" "Bluetooth-jako: %1$s lähetetty" - "100 % valmis" "Bluetooth-jako: tiedostoa %1$s ei lähetetty" "Tiedostonsiirto" "Lähettäjä: %1$s" @@ -80,7 +77,6 @@ "Odota…" "Otetaan Bluetooth käyttöön..." "Tiedosto otetaan vastaan. Näet siirron tilan Ilmoitukset-paneelissa." - "Tiedostoa ei voi vastaanottaa." "Pysäytettiin tiedoston vastaanotto lähettäjältä %1$s" "Lähetetään tiedosto vastaanottajalle %1$s" "Lähetetään %1$s tiedostoa vastaanottajalle %2$s" @@ -118,7 +114,6 @@ "Poista" "Musiikintunnistus" "Sovelluskuvake" - "Bluetooth-ääni liitetty" "Bluetooth-ääni katkaistu" "Bluetooth-ääni" "Yli 4 Gt:n kokoisia tiedostoja ei voi siirtää." diff --git a/android/app/res/values-fi/test_strings.xml b/android/app/res/values-fi/test_strings.xml deleted file mode 100644 index 3e7ca4b78ac..00000000000 --- a/android/app/res/values-fi/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Lisää tiedot" - "Vahvista tiedot" - "Hyv. tiedot" - "Poista kaikki tiedot" - "OK" - "Poista tiedot" - "Käynnistä TCP-palvelin" - "Ilmoita TCP-palvelin" - diff --git a/android/app/res/values-fr-rCA/strings.xml b/android/app/res/values-fr-rCA/strings.xml index 4ad6b7b5c1f..39936b20db9 100644 --- a/android/app/res/values-fr-rCA/strings.xml +++ b/android/app/res/values-fr-rCA/strings.xml @@ -32,7 +32,6 @@ "Activer Bluetooth maintenant?" "Annuler" "Activer" - "Transfert de fichier" "Accepter le fichier entrant?" "Refuser" "Accepter" @@ -42,10 +41,8 @@ "%1$s est prêt à vous envoyer un fichier : %2$s" "Partage Bluetooth : réception de %1$s en cours…" "Partage Bluetooth : %1$s reçu(s)" - "Partage Bluetooth : fichier %1$s non reçu" "Partage Bluetooth : envoi de %1$s en cours…" "Partage Bluetooth : %1$s envoyé" - "100 % effectués" "Partage Bluetooth : fichier %1$s non envoyé" "Transfert de fichier" "De : \"%1$s\"" @@ -80,7 +77,6 @@ "Veuillez patienter…" "Activation de Bluetooth…" "La réception du fichier va commencer. La progression va s\'afficher dans le panneau de notification." - "Impossible de recevoir le fichier." "Réception du fichier de \"%1$s\" interrompue" "Envoi du fichier à « %1$s »" "Envoi de %1$s fichiers à \"%2$s\"" @@ -118,7 +114,6 @@ "Effacer" "En cours de lecture" "Icône de l\'appli" - "Audio Bluetooth connecté" "Audio Bluetooth déconnecté" "Audio Bluetooth" "Les fichiers dépassant 4 Go ne peuvent pas être transférés" diff --git a/android/app/res/values-fr-rCA/test_strings.xml b/android/app/res/values-fr-rCA/test_strings.xml deleted file mode 100644 index eff4a9d8979..00000000000 --- a/android/app/res/values-fr-rCA/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insérer l\'enregistrement" - "Confirmer l\'enregistrement" - "Enregistrement accusé de réception" - "Supprimer tout l\'enregistrement" - "OK" - "Supprimer l\'enregistrement" - "Démarrer le serveur TCP" - "Avertir le serveur TCP" - diff --git a/android/app/res/values-fr/strings.xml b/android/app/res/values-fr/strings.xml index 5a1174f9e0a..629c6d26d44 100644 --- a/android/app/res/values-fr/strings.xml +++ b/android/app/res/values-fr/strings.xml @@ -32,7 +32,6 @@ "Activer le Bluetooth maintenant ?" "Annuler" "Activer" - "Transfert de fichier" "Accepter le fichier entrant ?" "Refuser" "Accepter" @@ -42,10 +41,8 @@ "%1$s est prêt à envoyer un fichier : %2$s" "Partage Bluetooth : réception de %1$s" "Partage Bluetooth : %1$s reçu" - "Partage Bluetooth : fichier %1$s non reçu" "Partage Bluetooth : envoi de %1$s" "Partage Bluetooth : %1$s envoyé" - "100 % effectués" "Partage Bluetooth : fichier %1$s non envoyé" "Transfert de fichier" "De : \"%1$s\"" @@ -80,7 +77,6 @@ "Veuillez patienter..." "Activation Bluetooth…" "La réception du fichier va commencer. La progression va s\'afficher dans le panneau de notification." - "Impossible de recevoir le fichier." "Réception du fichier de \"%1$s\" interrompue" "Envoi du fichier à \"%1$s\"" "Envoi de %1$s fichiers à \"%2$s\"" @@ -118,7 +114,6 @@ "Effacer" "En écoute" "Icône de l\'application" - "Audio Bluetooth connecté" "Audio Bluetooth déconnecté" "Audio Bluetooth" "Impossible de transférer les fichiers supérieurs à 4 Go" diff --git a/android/app/res/values-fr/test_strings.xml b/android/app/res/values-fr/test_strings.xml deleted file mode 100644 index eff4a9d8979..00000000000 --- a/android/app/res/values-fr/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Insérer l\'enregistrement" - "Confirmer l\'enregistrement" - "Enregistrement accusé de réception" - "Supprimer tout l\'enregistrement" - "OK" - "Supprimer l\'enregistrement" - "Démarrer le serveur TCP" - "Avertir le serveur TCP" - diff --git a/android/app/res/values-gl/strings.xml b/android/app/res/values-gl/strings.xml index 54b484c7d7b..302255a817d 100644 --- a/android/app/res/values-gl/strings.xml +++ b/android/app/res/values-gl/strings.xml @@ -32,7 +32,6 @@ "Queres activar o Bluetooth agora?" "Cancelar" "Activar" - "Transferencia de ficheiros" "Queres aceptar o ficheiro entrante?" "Rexeitar" "Aceptar" @@ -42,10 +41,8 @@ "%1$s ten todo listo para enviar un ficheiro: %2$s" "Uso compartido por Bluetooth: recibindo %1$s" "Uso compartido por Bluetooth: %1$s recibido" - "Uso compartido por Bluetooth: ficheiro %1$s non recibido" "Uso compartido por Bluetooth: enviando %1$s" "Uso compartido por Bluetooth: %1$s enviado" - "100% completado" "Uso compartido por Bluetooth: ficheiro %1$s non enviado" "Transferencia de ficheiros" "De: \"%1$s\"" @@ -80,7 +77,6 @@ "Agarda..." "Activando Bluetooth…" "Recibirase o ficheiro. Comproba o progreso no panel de notificacións." - "O ficheiro non se pode recibir." "Detívose a recepción do ficheiro de \"%1$s\"" "Enviando ficheiro a \"%1$s\"" "Enviando %1$s ficheiros a \"%2$s\"" @@ -118,7 +114,6 @@ "Borrar" "Está soando" "Icona da aplicación" - "Conectouse o audio por Bluetooth" "Desconectouse o audio por Bluetooth" "Audio por Bluetooth" "Non se poden transferir ficheiros de máis de 4 GB" diff --git a/android/app/res/values-gl/test_strings.xml b/android/app/res/values-gl/test_strings.xml deleted file mode 100644 index 4ca4d5351f3..00000000000 --- a/android/app/res/values-gl/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Inserir rexistro" - "Confirmar rexistro" - "Rexistro Ack" - "Eliminar todos os rexistros" - "Aceptar" - "Eliminar rexistro" - "Iniciar servidor TCP" - "Notificar ao servidor TCP" - diff --git a/android/app/res/values-gu/strings.xml b/android/app/res/values-gu/strings.xml index 0914052f323..bae6c11943a 100644 --- a/android/app/res/values-gu/strings.xml +++ b/android/app/res/values-gu/strings.xml @@ -32,7 +32,6 @@ "હવે બ્લૂટૂથ ચાલુ કરીએ?" "રદ કરો" "ચાલુ કરો" - "ફાઇલ સ્થાનાંતરણ" "આવનારી ફાઇલ સ્વીકારીએ?" "નકારો" "સ્વીકારો" @@ -42,10 +41,8 @@ "%1$s આ ફાઇલ મોકલવા માટે તૈયાર છે: %2$s" "બ્લૂટૂથ શેર: %1$s પ્રાપ્ત કરી રહ્યું છે" "બ્લૂટૂથ શેર: %1$s પ્રાપ્ત" - "બ્લૂટૂથ શેર: ફાઇલ %1$s પ્રાપ્ત થઈ નથી" "બ્લૂટૂથ શેર: %1$s મોકલી રહ્યું છે" "બ્લૂટૂથ શેર: %1$s મોકલી" - "100% પૂર્ણ" "બ્લૂટૂથ શેર: ફાઇલ %1$s મોકલાઈ નથી" "ફાઇલ સ્થાનાંતરણ" "દ્વારા: \"%1$s\"" @@ -80,7 +77,6 @@ "કૃપા કરીને રાહ જુઓ..." "બ્લૂટૂથ ચાલુ કરી રહ્યું છે…" "ફાઇલ પ્રાપ્ત થશે. સૂચનાઓ પેનલમાં પ્રગતિ તપાસો." - "ફાઇલ પ્રાપ્ત કરી શકાતી નથી." "\"%1$s\" થી ફાઇલ પ્રાપ્ત કરવાનું બંધ કર્યું" "\"%1$s\" પર ફાઇલ મોકલી રહ્યાં છે" "%1$s ફાઇલો \"%2$s\" પર મોકલી રહ્યાં છે" @@ -118,7 +114,6 @@ "સાફ કરો" "હમણાં વાગી રહ્યું છે" "ઍપ્લિકેશન આયકન" - "બ્લૂટૂથ ઑડિઓ કનેક્ટ થયું" "બ્લૂટૂથ ઑડિઓ ડિસ્કનેક્ટ થયું" "બ્લૂટૂથ ઑડિઓ" "4GB કરતા મોટી ફાઇલ ટ્રાન્સફર કરી શકાતી નથી" diff --git a/android/app/res/values-gu/test_strings.xml b/android/app/res/values-gu/test_strings.xml deleted file mode 100644 index 1013f116773..00000000000 --- a/android/app/res/values-gu/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "બ્લૂટૂથ" - "રેકોર્ડ શામેલ કરો" - "રેકોર્ડની પુષ્ટિ કરો" - "Ack રેકોર્ડ" - "તમામ રેકોર્ડ કાઢી નાખો" - "ઓકે" - "રેકોર્ડ કાઢી નાખો" - "TCP સર્વર પ્રારંભ કરો" - "TCP સર્વરને સૂચિત કરો" - diff --git a/android/app/res/values-hi/strings.xml b/android/app/res/values-hi/strings.xml index 84132ccec73..0e0cc894287 100644 --- a/android/app/res/values-hi/strings.xml +++ b/android/app/res/values-hi/strings.xml @@ -32,7 +32,6 @@ "अभी ब्लूटूथ चालू करें?" "रद्द करें" "चालू करें" - "फ़ाइल ट्रांसफ़र करें" "इनकमिंग फ़ाइल स्वीकार करें?" "अस्वीकारें" "स्वीकारें" @@ -42,10 +41,8 @@ "%1$s, इस फ़ाइल को भेजने के लिए तैयार है: %2$s" "ब्लूटूथ शेयर: %1$s मिल रही है" "ब्लूटूथ शेयर: %1$s पाई गई" - "ब्लूटूथ शेयर: फ़ाइल %1$s नहीं मिली" "ब्लूटूथ शेयर: %1$s भेज रहा है" "ब्लूटूथ शेयर: %1$s भेजा गया" - "100% पूरा" "ब्लूटूथ शेयर: फ़ाइल %1$s भेजी नहीं गई" "फ़ाइल ट्रांसफ़र करें" "प्रेषक: \"%1$s\"" @@ -80,7 +77,6 @@ "कृपया इंतज़ार करें..." "ब्लूटूथ चालू कर रहा है…" "फ़ाइल मिलेगी. सूचना पैनल में प्रगति देखें." - "फ़ाइल पाई नहीं जा सकती." "\"%1$s\" से फ़ाइल पाना रोका गया" "\"%1$s\" को फ़ाइल भेज रहा है" "\"%2$s\" को %1$s फ़ाइलें भेज रहा है" @@ -118,7 +114,6 @@ "साफ़ करें" "अभी चल रहा है" "ऐप्लिकेशन आइकॉन" - "ब्लूटूथ ऑडियो कनेक्ट किया गया" "ब्लूटूथ ऑडियो डिसकनेक्ट किया गया" "ब्लूटूथ ऑडियो" "4 जीबी से बड़ी फ़ाइलें ट्रांसफ़र नहीं की जा सकतीं" diff --git a/android/app/res/values-hi/test_strings.xml b/android/app/res/values-hi/test_strings.xml deleted file mode 100644 index f59b2338dd4..00000000000 --- a/android/app/res/values-hi/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ब्लूटूथ" - "रिकॉर्ड सम्मिलित करें" - "रिकॉर्ड की पुष्टि करें" - "रिकॉर्ड अभिस्वीकृत करें" - "सभी रिकॉर्ड मिटाएं" - "ठीक है" - "रिकॉर्ड मिटाएं" - "TCP सर्वर शरू करें" - "TCP सर्वर को सूचित करें" - diff --git a/android/app/res/values-hr/strings.xml b/android/app/res/values-hr/strings.xml index 4808febd16c..0931f34d13a 100644 --- a/android/app/res/values-hr/strings.xml +++ b/android/app/res/values-hr/strings.xml @@ -32,7 +32,6 @@ "Uključiti Bluetooth sada?" "Odustani" "Uključi" - "Prijenos datoteke" "Prihvatiti dolaznu datoteku?" "Odbaci" "Prihvaćam" @@ -42,10 +41,8 @@ "%1$s sada može poslati datoteku: %2$s" "Dijeljenje Bluetoothom: primanje datoteke %1$s" "Dijeljenje Bluetoothom: primljena datoteka %1$s" - "Dijeljenje Bluetoothom: datoteka %1$s nije primljena" "Dijeljenje Bluetoothom: slanje datoteke %1$s" "Dijeljenje Bluetoothom: datoteka %1$s poslana" - "100% dovršeno" "Dijeljenje Bluetoothom: datoteka %1$s nije poslana" "Prijenos datoteke" "Šalje: \"%1$s\"" @@ -80,7 +77,6 @@ "Pričekajte…" "Uključivanje Bluetootha…" "Datoteka će biti primljena. Napredak provjerite na ploči Obavijesti." - "Datoteka ne može biti primljena." "Zaustavljeno primanje datoteke od pošiljatelja \"%1$s\"" "Slanje datoteke primatelju \"%1$s\"" "Sljedeći broj datoteka: %1$s šalje se primatelju \"%2$s\"" @@ -118,7 +114,6 @@ "Brisanje" "Upravo svira" "Ikona aplikacije" - "Bluetooth Audio povezan" "Veza Bluetooth Audija prekinuta" "Bluetooth Audio" "Datoteke veće od 4 GB ne mogu se prenijeti" diff --git a/android/app/res/values-hr/test_strings.xml b/android/app/res/values-hr/test_strings.xml deleted file mode 100644 index ba6ac604d15..00000000000 --- a/android/app/res/values-hr/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Umetni zapis" - "Potvrdi zapis" - "Ack zapis" - "Izbriši sve zapise" - "U redu" - "Izbriši zapis" - "Pokreni TCP poslužitelj" - "Obavijesti TCP poslužitelj" - diff --git a/android/app/res/values-hu/strings.xml b/android/app/res/values-hu/strings.xml index 6b5d46576f2..e94dc8f11de 100644 --- a/android/app/res/values-hu/strings.xml +++ b/android/app/res/values-hu/strings.xml @@ -32,7 +32,6 @@ "Bekapcsolja most a Bluetooth-funkciót?" "Mégse" "Bekapcsolás" - "Fájlátvitel" "Fogadja a bejövő fájlt?" "Elutasítás" "Fogadás" @@ -42,10 +41,8 @@ "%1$s fájlt szeretne küldeni: %2$s" "Bluetooth megosztás: %1$s fogadása" "Bluetooth megosztás: %1$s fogadva" - "Bluetooth megosztás: %1$s fájl fogadása nem sikerült" "Bluetooth megosztás: %1$s küldése" "Bluetooth megosztás: %1$s elküldve" - "100% kész" "Bluetooth megosztás: %1$s fájl küldése nem sikerült" "Fájlátvitel" "Feladó: \"%1$s\"" @@ -80,7 +77,6 @@ "Kérjük, várjon..." "Bluetooth bekapcsolása..." "A fájl fogadható. Az átvitel haladását az Értesítések párbeszédpanelen kísérheti figyelemmel." - "A fájlt nem lehet fogadni." "A fájl fogadása \"%1$s\" feladótól leállítva" "Fájl küldése a következőnek: \"%1$s\"" "%1$s fájl küldése a következőnek: \"%2$s\"" @@ -118,7 +114,6 @@ "Törlés" "Now Playing" "Alkalmazás ikonja" - "Bluetooth audió csatlakoztatva" "Bluetooth audió leválasztva" "Bluetooth audió" "A 4 GB-nál nagyobb fájlokat nem lehet átvinni" diff --git a/android/app/res/values-hu/test_strings.xml b/android/app/res/values-hu/test_strings.xml deleted file mode 100644 index f277c44dd56..00000000000 --- a/android/app/res/values-hu/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Rekord beszúrása" - "Rekord megerősítése" - "ACK rekord" - "Minden rekord törlése" - "OK" - "Rekord törlése" - "TCP-szerver indítása" - "TCP-szerver értesítése" - diff --git a/android/app/res/values-hy/strings.xml b/android/app/res/values-hy/strings.xml index 836912d5403..877ac762ec3 100644 --- a/android/app/res/values-hy/strings.xml +++ b/android/app/res/values-hy/strings.xml @@ -32,7 +32,6 @@ "Միացնե՞լ Bluetooth-ը հիմա:" "Չեղարկել" "Միացնել" - "Ֆայլերի փոխանցում" "Ընդունե՞լ մուտքային ֆայլը" "Մերժել" "Ընդունել" @@ -42,10 +41,8 @@ %1$s» սարքը պատրաստ է ուղարկել այս ֆայլը՝ %2$s" "Bluetooth-ով փոխանցում․ %1$s ֆայլն ընդունվում է" "Bluetooth-ով փոխանցում․ %1$s ֆայլն ընդունվեց" - "Bluetooth-ով փոխանցում․ %1$s ֆայլը չի ընդունվել" "Bluetooth-ով փոխանցում․ ուղարկվում է %1$s ֆայլը" "Bluetooth-ով փոխանցում․ %1$s ֆայլն ուղարկվեց" - "100% ավարտուն" "Bluetooth-ով փոխանցում․ %1$s ֆայլը չի ուղարկվել" "Ֆայլերի փոխանցում" "Ումից՝ «%1$s»" @@ -80,7 +77,6 @@ "Խնդրում ենք սպասել..." "Bluetooth-ը միանում է..." "Դուք կստանաք ֆայլը: Առաջընթացի մասին տեղեկացեք Ծանուցումների վահանակից:" - "Հնարավոր չէ ստանալ ֆայլը:" "Դադարեցվեց «%1$s»-ից ֆայլի ստացումը" "Ֆայլն ուղարկվում է «%1$s»-ին" "%1$s ֆայլեր ուղարկվում են «%2$s»-ին" @@ -118,7 +114,6 @@ "Ջնջել" "Այժմ հնչում է" "Հավելվածի պատկերակը" - "Bluetooth աուդիոն կապակցված է" "Bluetooth աուդիոն անջատված է" "Bluetooth աուդիո" "4 ԳԲ-ից մեծ ֆայլերը հնարավոր չէ փոխանցել" diff --git a/android/app/res/values-hy/test_strings.xml b/android/app/res/values-hy/test_strings.xml deleted file mode 100644 index 89fd515404b..00000000000 --- a/android/app/res/values-hy/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Կատարեք գրառում" - "Հաստատել գրառումը" - "ACK գրառում" - "Ջնջել բոլոր գրառումները" - "Եղավ" - "Ջնջել գրառումը" - "Մեկնարկել TCP սերվերը" - "Ծանուցել TCP սերվերին" - diff --git a/android/app/res/values-in/strings.xml b/android/app/res/values-in/strings.xml index 18c529ef8e0..cca7198aabb 100644 --- a/android/app/res/values-in/strings.xml +++ b/android/app/res/values-in/strings.xml @@ -32,7 +32,6 @@ "Hidupkan Bluetooth sekarang?" "Batal" "Hidupkan" - "Transfer file" "Terima file masuk?" "Tolak" "Terima" @@ -42,10 +41,8 @@ "%1$s siap mengirim file: %2$s" "Berbagi via Bluetooth: Sedang menerima %1$s" "Berbagi via Bluetooth: Telah menerima %1$s" - "Berbagi via Bluetooth: File %1$s gagal diterima" "Berbagi via Bluetooth: Sedang mengirim %1$s" "Berbagi via Bluetooth: Telah mengirim %1$s" - "100% selesai" "Berbagi via Bluetooth: File %1$s gagal dikirim" "Transfer file" "Dari: \"%1$s\"" @@ -80,7 +77,6 @@ "Harap tunggu…" "Menghidupkan Bluetooth..." "File akan diterima. Periksa kemajuan dalam panel Notifikasi." - "File tidak dapat diterima." "Berhenti menerima file dari \"%1$s\"" "Mengirim file ke \"%1$s\"" "Mengirim %1$s file ke \"%2$s\"" @@ -118,7 +114,6 @@ "Hapus" "Now Playing" "Ikon Aplikasi" - "Bluetooth audio terhubung" "Bluetooth audio terputus" "Bluetooth Audio" "File yang berukuran lebih dari 4GB tidak dapat ditransfer" diff --git a/android/app/res/values-in/test_strings.xml b/android/app/res/values-in/test_strings.xml deleted file mode 100644 index dab91b5c433..00000000000 --- a/android/app/res/values-in/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Masukkan catatan" - "Konfirmasi catatan" - "Akui catatan" - "Hapus semua catatan" - "Oke" - "Hapus catatan" - "Mulai server TCP" - "Beri tahu server TCP" - diff --git a/android/app/res/values-is/strings.xml b/android/app/res/values-is/strings.xml index 71502f6c209..9744a5f01c3 100644 --- a/android/app/res/values-is/strings.xml +++ b/android/app/res/values-is/strings.xml @@ -32,7 +32,6 @@ "Viltu kveikja á Bluetooth núna?" "Hætta við" "Kveikja" - "Skráaflutningur" "Samþykkja skrá sem berst?" "Hafna" "Samþykkja" @@ -42,10 +41,8 @@ "%1$s ætlar að senda skrá: %2$s" "Bluetooth-deiling: Tekur á móti %1$s" "Bluetooth-deiling: Skráin %1$s var móttekin" - "Bluetooth-deiling: Skráin %1$s var ekki móttekin" "Bluetooth-deiling: Sendir %1$s" "Bluetooth-deiling: Skráin %1$s var send" - "100% lokið" "Bluetooth-deiling: Skráin %1$s var ekki send" "Skráaflutningur" "Frá: „%1$s“" @@ -80,7 +77,6 @@ "Augnablik…" "Kveikir á Bluetooth…" "Tekið verður á móti skránni. Fylgstu með framvindunni í tilkynningaglugganum." - "Ekki er hægt að taka á móti skránni." "Móttaka skráar sem „%1$s“ sendi stöðvuð" "Sendir skrá til „%1$s“" "Sendir %1$s skrár til „%2$s“" @@ -118,7 +114,6 @@ "Hreinsa" "Í spilun" "Forritstákn" - "Bluetooth-hljóð tengt" "Bluetooth-hljóð aftengt" "Bluetooth-hljóð" "Ekki er hægt að flytja skrár sem eru stærri en 4 GB" diff --git a/android/app/res/values-is/test_strings.xml b/android/app/res/values-is/test_strings.xml deleted file mode 100644 index a157d1480a4..00000000000 --- a/android/app/res/values-is/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Setja inn færslu" - "Staðfesta færslu" - "Ack-færsla" - "Eyða öllum færslum" - "Í lagi" - "Eyða færslu" - "Ræsa TCP-þjón" - "Tilkynna TCP-þjóni" - diff --git a/android/app/res/values-it/strings.xml b/android/app/res/values-it/strings.xml index d0a196b2f4b..14951ad4766 100644 --- a/android/app/res/values-it/strings.xml +++ b/android/app/res/values-it/strings.xml @@ -32,7 +32,6 @@ "Attivare Bluetooth adesso?" "Annulla" "Attiva" - "Trasferimento file" "Accettare il file in arrivo?" "Rifiuta" "Accetta" @@ -42,10 +41,8 @@ "%1$s vuole inviare un file: %2$s" "Bluetooth: ricezione %1$s" "Bluetooth: %1$s ricevuto" - "Bluetooth: file %1$s non ricevuto" "Bluetooth: invio %1$s" "Bluetooth: %1$s inviato" - "100% completato" "Bluetooth: file %1$s non inviato" "Trasferimento file" "Da: \"%1$s\"" @@ -80,7 +77,6 @@ "Attendi…" "Attivazione Bluetooth…" "Il file verrà ricevuto. Controlla l\'avanzamento nel pannello Notifiche." - "Impossibile ricevere il file." "Interruzione della ricezione del file da \"%1$s\"" "Invio del file a \"%1$s\"" "Invio di %1$s file a \"%2$s\"" @@ -118,7 +114,6 @@ "Cancella" "In riproduzione" "Icona applicazione" - "Audio Bluetooth connesso" "Audio Bluetooth disconnesso" "Audio Bluetooth" "Impossibile trasferire file con dimensioni superiori a 4 GB" diff --git a/android/app/res/values-it/test_strings.xml b/android/app/res/values-it/test_strings.xml deleted file mode 100644 index 5ff58536c7c..00000000000 --- a/android/app/res/values-it/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Inserisci record" - "Conferma record" - "Record ACK" - "Elimina tutti i record" - "OK" - "Elimina record" - "Avvia server TCP" - "Invia notifica al server TCP" - diff --git a/android/app/res/values-iw/strings.xml b/android/app/res/values-iw/strings.xml index 0ab8b9ec5ce..528a0b8f6ad 100644 --- a/android/app/res/values-iw/strings.xml +++ b/android/app/res/values-iw/strings.xml @@ -32,7 +32,6 @@ "‏להפעיל Bluetooth כעת?" "ביטול" "הפעלה" - "העברת קבצים" "האם לקבל את הקובץ הנכנס?" "דחייה" "קבלה" @@ -42,10 +41,8 @@ "%1$s מוכן לשליחת קובץ: %2$s" "‏שיתוף Bluetooth: ‏%1$s מתקבל" "‏שיתוף Bluetooth‏: התקבל %1$s" - "‏שיתוף Bluetooth: הקובץ %1$s לא התקבל" "‏שיתוף Bluetooth: שליחת %1$s מתבצעת" "‏שיתוף Bluetooth‏: נשלח %1$s" - "‏הושלם ב-‎100%‎" "‏שיתוף Bluetooth: הקובץ %1$s לא נשלח" "העברת קבצים" "מאת: \"%1$s\"" @@ -80,7 +77,6 @@ "יש להמתין..." "‏הפעלת Bluetooth מתבצעת…" "הקובץ יתקבל. יש לבדוק את ההתקדמות בלוח ההתראות." - "לא ניתן לקבל את הקובץ." "הופסקה קבלת קובץ מאת \"%1$s\"" "שליחת קובץ אל \"%1$s\" מתבצעת" "שליחת %1$s קבצים אל \"%2$s\" מתבצעת" @@ -118,7 +114,6 @@ "ניקוי" "מה שומעים עכשיו?" "סמל אפליקציה" - "‏אודיו Bluetooth מחובר" "‏אודיו Bluetooth מנותק" "‏אודיו Bluetooth" "‏לא ניתן להעביר קבצים שגדולים מ-4GB" diff --git a/android/app/res/values-iw/test_strings.xml b/android/app/res/values-iw/test_strings.xml deleted file mode 100644 index 4c0557f3d95..00000000000 --- a/android/app/res/values-iw/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "הוספת רשומה" - "אישור רשומה" - "אישור רשומה" - "מחיקת כל הרשומות" - "אישור" - "מחיקת רשומה" - "‏הפעלת שרת TCP" - "‏שליחת התראה לשרת TCP" - diff --git a/android/app/res/values-ja/strings.xml b/android/app/res/values-ja/strings.xml index a0f4cbc0535..42d090a50c1 100644 --- a/android/app/res/values-ja/strings.xml +++ b/android/app/res/values-ja/strings.xml @@ -32,7 +32,6 @@ "Bluetoothを今すぐONにしますか?" "キャンセル" "ONにする" - "ファイル転送" "着信ファイルを受信しますか?" "拒否" "承諾" @@ -42,10 +41,8 @@ "%1$s さんがファイル(%2$s)を送信する準備ができました" "Bluetooth共有: %1$sを受信中" "Bluetooth共有: %1$sを受信済み" - "Bluetooth共有: ファイル%1$sの受信に失敗" "Bluetooth共有: %1$sを送信中" "Bluetooth共有: %1$sを送信済み" - "100%完了" "Bluetooth共有: ファイル%1$sの送信に失敗" "ファイル転送" "送信元: 「%1$s」" @@ -80,7 +77,6 @@ "お待ちください..." "BluetoothをONにしています..." "ファイルを受信します。進行状況は[通知]パネルでご確認ください。" - "ファイルを受信できません。" "「%1$s」からのファイルの受信を停止しました" "「%1$s」にファイルを送信中" "%1$s個のファイルを「%2$s」に送信中" @@ -118,7 +114,6 @@ "消去" "この曲なに?" "アプリアイコン" - "Bluetooth オーディオは接続されています" "Bluetooth オーディオは接続を解除されています" "Bluetooth オーディオ" "4 GB を超えるファイルは転送できません" diff --git a/android/app/res/values-ja/test_strings.xml b/android/app/res/values-ja/test_strings.xml deleted file mode 100644 index 91fe34123eb..00000000000 --- a/android/app/res/values-ja/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "記録を挿入" - "レコードを確認" - "Ackレコード" - "レコードをすべて削除" - "OK" - "レコードを削除" - "TCPサーバーを起動" - "TCPサーバーに通知" - diff --git a/android/app/res/values-ka/strings.xml b/android/app/res/values-ka/strings.xml index ca1d57e12ee..9b16a585ef0 100644 --- a/android/app/res/values-ka/strings.xml +++ b/android/app/res/values-ka/strings.xml @@ -32,7 +32,6 @@ "გსურთ Bluetooth-ის ახლა ჩართვა?" "გაუქმება" "ჩართვა" - "ფაილის ტრანსფერი" "გსურთ შემომავალი ფაილის მიღება?" "უარყოფა" "მიღება" @@ -42,10 +41,8 @@ "%1$s მზად არის შემდეგი ფაილის გასაგზავნად: %2$s" "Bluetooth გაზიარება: %1$s ფაილის მიღება" "Bluetooth გაზიარება: მიღებულია %1$s" - "Bluetooth გაზიარება: ფაილი %1$s არ მიღებულა" "Bluetooth გაზიარება: %1$s-ის გაგზავნა" "Bluetooth გაზიარება: გაიგზავნა %1$s" - "დასრულდა 100%" "Bluetooth გაზიარება: ფაილი %1$s არ გაიგზავნა" "ფაილის ტრანსფერი" "გამგზავნი: „%1$s“" @@ -80,7 +77,6 @@ "გთხოვთ, მოითმინოთ..." "Bluetooth-ის ჩართვა…" "ფაილი მიღებული იქნება. შეამოწმეთ პროგრესი შეტყობინებების დაფაზე." - "ფაილის მიღება ვერ ხერხდება." "„%1$s“-დან ფაილის მიღება შეჩერდა" "„%1$s“-თან ფაილის გაგზავნა" "%1$s ფაილის „%2$s“-თან გაგზავნა" @@ -118,7 +114,6 @@ "ამოშლა" "რა უკრავს" "აპლიკაციის ხატულა" - "Bluetooth აუდიო დაკავშირებულია" "Bluetooth აუდიო გათიშულია" "Bluetooth აუდიო" "4 გბაიტზე დიდი მოცულობის ფაილების გადატანა ვერ მოხერხდება" diff --git a/android/app/res/values-ka/test_strings.xml b/android/app/res/values-ka/test_strings.xml deleted file mode 100644 index 26869b37a16..00000000000 --- a/android/app/res/values-ka/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "ჩანაწერის ჩასმა" - "ჩანაწერის დადასტურება" - "Ack ჩანაწერი" - "ყველა ჩანაწერის წაშლა" - "კარგი" - "ჩანაწერის წაშლა" - "TCP სერვერის დაწყება" - "TCP სერვერის შეტყობინება" - diff --git a/android/app/res/values-kk/strings.xml b/android/app/res/values-kk/strings.xml index 70646f9c633..97dc22df025 100644 --- a/android/app/res/values-kk/strings.xml +++ b/android/app/res/values-kk/strings.xml @@ -32,7 +32,6 @@ "Bluetooth байланысы қазір қосылсын ба?" "Жабу" "Қосу" - "Файл жіберу" "Кіріс файлды қабылдау керек пе?" "Бас тарту" "Қабылдау" @@ -42,10 +41,8 @@ "%1$s келесі файлды жіберуге дайын: %2$s" "Bluetooth арқылы бөлісу: %1$s файлы қабылдануда" "Bluetooth бөлісу: %1$s файлы қабылданды" - "Bluetooth бөлісу: %1$s файлы қабылданбады" "Bluetooth бөлісу: %1$s файлын жіберуде" "Bluetooth бөлісу: %1$s файлы жіберілді" - "100% аяқталды" "Bluetooth бөлісу: %1$s файлы жіберілмеді." "Файл аудару" "Кімнен: \"%1$s\"" @@ -80,7 +77,6 @@ "Күте тұрыңыз…" "Bluetooth қосылуда…" "Файл қабылданады. Орындалуын Хабарлар тақтасы арқылы бақылаңыз." - "Файлды қабылдау мүмкін емес." "\"%1$s\" жіберген файлдары қабылдауды доғарды." "Файлды \"%1$s\" байланысына жіберуде" "%1$s файл \"%2$s\" байланысына жіберілуде" @@ -118,7 +114,6 @@ "Өшіру" "Қазір ойнауда" "Қолданба белгішесі" - "Bluetooth дыбысы қосылды" "Bluetooth дыбысы ажыратылды" "Bluetooth aудиосы" "Көлемі 4 ГБ-тан асатын файлдар тасымалданбайды" diff --git a/android/app/res/values-kk/test_strings.xml b/android/app/res/values-kk/test_strings.xml deleted file mode 100644 index 5b45961b24d..00000000000 --- a/android/app/res/values-kk/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Жазбаны енгізу" - "Жазбаны растау" - "Жазбаны тану" - "Барлық жазбаларды жою" - "Жарайды" - "Жазбаны жою" - "TCP серверін бастау" - "TCP (жібреуі басқару протоколы) серверін ескерту" - diff --git a/android/app/res/values-km/strings.xml b/android/app/res/values-km/strings.xml index d7f13d88f37..2edd041301e 100644 --- a/android/app/res/values-km/strings.xml +++ b/android/app/res/values-km/strings.xml @@ -32,7 +32,6 @@ "បើក​ប៊្លូធូស​ឥឡូវ​នេះ?" "បោះ​បង់​" "បើក" - "ការ​ផ្ទេរ​ឯកសារ" "ទទួលយក​ឯកសារ​ចូលឬ?" "បដិសេធ" "ទទួលយក" @@ -42,10 +41,8 @@ "%1$s អាចផ្ញើឯកសារ​បានហើយ៖ %2$s" "ចែក​រំលែកតាម​ប៊្លូ​ធូ​ស៖ កំពុងទទួល %1$s" "ការ​ចែក​រំលែក​ប៊្លូ​ធូ​ស៖ បាន​ទទួល​ %1$s" - "ការ​ចែក​រំលែក​ប៊្លូ​ធូ​ស៖ មិន​បាន​ទទួល​ឯកសារ %1$s" "ចែក​រំលែកតាម​ប៊្លូ​ធូ​ស៖ កំពុងបញ្ជូន %1$s" "ចែក​រំលែកតាម​ប៊្លូ​ធូ​ស៖ បាន​បញ្ជូន %1$s" - "​បញ្ចប់ 100​%" "ការ​ចែក​រំលែក​ប៊្លូ​ធូ​ស៖ មិន​បាន​ផ្ញើ​ឯកសារ %1$s" "ការ​ផ្ទេរ​ឯកសារ" "ពី៖ \"%1$s\"" @@ -80,7 +77,6 @@ "សូម​រង់ចាំ..." "កំពុង​បើក​ប៊្លូធូស…" "នឹង​​​​បាន​ទទួល​​​ឯកសារ។ ពិនិត្យមើល​វឌ្ឍនភាព​នៅ​ក្នុង​ផ្ទាំង​ជូនដំណឹង។" - "មិន​អាច​ទទួល​​ឯកសារ។" "បាន​បញ្ឈប់​ការ​ទទួល​​ឯកសារ​ពី \"%1$s\"" "ផ្ញើ​ឯកសារ​ទៅ \"%1$s\"" "ផ្ញើ​ឯកសារ %1$s ទៅ \"%2$s\"" @@ -118,7 +114,6 @@ "សម្អាត" "ឥឡូវកំពុងចាក់" "រូបតំណាងកម្មវិធី" - "សំឡេងប៊្លូធូសត្រូវបានភ្ជាប់" "សំឡេងប៊្លូធូសត្រូវបានផ្តាច់" "សំឡេងប៊្លូធូស" "ឯកសារ​ដែល​មាន​ទំហំ​ធំ​ជាង 4 GB មិន​អាចផ្ទេរ​បាន​ទេ" diff --git a/android/app/res/values-km/test_strings.xml b/android/app/res/values-km/test_strings.xml deleted file mode 100644 index 44a26b2b893..00000000000 --- a/android/app/res/values-km/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ប៊្លូធូស" - "បញ្ចូល​កំណត់ត្រា" - "បញ្ជាក់​កំណត់ត្រា" - "កំណត់ត្រា​ការ​ទទួល​ស្គាល់" - "លុប​កំណត់​ត្រា​ទាំងអស់" - "យល់​ព្រម​" - "លុប​កំណត់​ត្រា" - "ចាប់ផ្ដើម​​ម៉ាស៊ីន​មេ TCP" - "ជូន​ដំណឹង​ម៉ាស៊ីន​មេ TCP" - diff --git a/android/app/res/values-kn/strings.xml b/android/app/res/values-kn/strings.xml index def51b47769..5e78ee6a50a 100644 --- a/android/app/res/values-kn/strings.xml +++ b/android/app/res/values-kn/strings.xml @@ -32,7 +32,6 @@ "ಇದೀಗ ಬ್ಲೂಟೂತ್‌ ಆನ್‌ ಮಾಡಬೇಕೆ?" "ರದ್ದುಮಾಡಿ" "ಆನ್‌ ಮಾಡಿ" - "ಫೈಲ್ ವರ್ಗಾವಣೆ" "ಒಳಬರುವ ಫೈಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸುವುದೇ?" "ನಿರಾಕರಿಸಿ" "ಸ್ವೀಕರಿಸಿ" @@ -42,10 +41,8 @@ "%1$s ಅವರು ಫೈಲ್ ಒಂದನ್ನು ಕಳುಹಿಸಲು ಸಿದ್ಧರಾಗಿದ್ದಾರೆ: %2$s" "ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: %1$s ಸ್ವೀಕರಿಸಲಾಗುತ್ತಿದೆ" "ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: %1$s ಸ್ವೀಕರಿಸಲಾಗಿದೆ" - "ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: ಫೈಲ್‌ %1$s ಸ್ವೀಕರಿಸಿಲ್ಲ" "ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: %1$s ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ" "ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: %1$s ಕಳುಹಿಸಲಾಗಿದೆ" - "100% ಪೂರ್ಣವಾಗಿದೆ" "ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: %1$s ಫೈಲ್‌‌ ಕಳುಹಿಸಲಾಗಿಲ್ಲ" "ಫೈಲ್ ವರ್ಗಾವಣೆ" "ಇಂದ: \"%1$s\"" @@ -80,7 +77,6 @@ "ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ…" "ಬ್ಲೂಟೂತ್‌ ಆನ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ…" "ಫೈಲ್‌ ಸ್ವೀಕರಿಸಲಾಗುತ್ತದೆ. ನೋಟಿಫಿಕೇಶನ್ ಫಲಕದಲ್ಲಿ ಪ್ರಗತಿಯನ್ನು ಪರಿಶೀಲಿಸಿ." - "ಫೈಲ್‌ ಸ್ವೀಕರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ." "\"%1$s\" ರಿಂದ ಫೈಲ್‌ ಸ್ವೀಕರಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಲಾಗಿದೆ" "\"%1$s\" ಇವರಿಗೆ ಫೈಲ್‌‌ ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ" "\"%2$s\" ಇವರಿಗೆ %1$s ಫೈಲ್‌‌ಗಳನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ" @@ -118,7 +114,6 @@ "ತೆರವುಗೊಳಿಸು" "Now Playing" "ಅಪ್ಲಿಕೇಶನ್‌ ಐಕಾನ್‌" - "ಬ್ಲೂಟೂತ್‌ ಆಡಿಯೋ ಸಂಪರ್ಕಗೊಂಡಿದೆ" "ಬ್ಲೂಟೂತ್‌ ಆಡಿಯೋ ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ" "ಬ್ಲೂಟೂತ್‌ ಆಡಿಯೋ" "4GB ಗಿಂತ ದೊಡ್ಡದಾದ ಫೈಲ್‌ಗಳನ್ನು ವರ್ಗಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" diff --git a/android/app/res/values-kn/test_strings.xml b/android/app/res/values-kn/test_strings.xml deleted file mode 100644 index 853133f2b53..00000000000 --- a/android/app/res/values-kn/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ಬ್ಲೂಟೂತ್‌" - "ರೆಕಾರ್ಡ್‌ ಸೇರಿಸಿ" - "ರೆಕಾರ್ಡ್‌ ಅನ್ನು ಖಚಿತಪಡಿಸಿ" - "Ack ರೆಕಾರ್ಡ್‌ ಮಾಡಿ" - "ಎಲ್ಲ ರೆಕಾರ್ಡ್‌ ಅನ್ನು ಅಳಿಸಿ" - "ಸರಿ" - "ರೆಕಾರ್ಡ್‌ ಅಳಿಸಿ" - "TCP ಸರ್ವರ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ" - "TCP ಸರ್ವರ್ ಅನ್ನು ಸೂಚಿಸಿ" - diff --git a/android/app/res/values-ko/strings.xml b/android/app/res/values-ko/strings.xml index 55e4bf27323..3d827eb17fc 100644 --- a/android/app/res/values-ko/strings.xml +++ b/android/app/res/values-ko/strings.xml @@ -32,7 +32,6 @@ "지금 블루투스를 사용하시겠습니까?" "취소" "사용" - "파일 전송" "파일 수신을 수락하시겠습니까?" "거부" "수락" @@ -42,10 +41,8 @@ "%1$s에서 %2$s 파일을 전송할 준비가 되었습니다." "블루투스 공유: %1$s 받는 중" "블루투스 공유: %1$s 받음" - "블루투스 공유: %1$s 파일이 수신되지 않았습니다." "블루투스 공유: %1$s 보내는 중" "블루투스 공유: %1$s 보냄" - "100% 완료" "블루투스 공유: %1$s 파일을 보내지 못함" "파일 전송" "보낸사람: \'%1$s\'" @@ -80,7 +77,6 @@ "잠시 기다려 주세요." "블루투스 켜는 중..." "파일이 수신됩니다. 알림 패널에서 진행률을 확인하세요." - "파일을 받지 못했습니다." "\'%1$s\'님으로부터 파일 받기를 중지했습니다." "\'%1$s\'님에게 파일을 보내는 중" "\'%2$s\'에 %1$s개 파일을 보내는 중" @@ -118,7 +114,6 @@ "지우기" "지금 재생 중" "애플리케이션 아이콘" - "블루투스 오디오가 연결됨" "블루투스 오디오가 연결 해제됨" "블루투스 오디오" "4GB보다 큰 파일은 전송할 수 없습니다" diff --git a/android/app/res/values-ko/test_strings.xml b/android/app/res/values-ko/test_strings.xml deleted file mode 100644 index 800ab0609f0..00000000000 --- a/android/app/res/values-ko/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "블루투스" - "기록 삽입" - "기록 확인" - "기록 인식" - "모든 기록 삭제" - "확인" - "기록 삭제" - "TCP 서버 시작" - "TCP 서버 알림" - diff --git a/android/app/res/values-ky/strings.xml b/android/app/res/values-ky/strings.xml index 68f22ecdd2a..d3e1f65c289 100644 --- a/android/app/res/values-ky/strings.xml +++ b/android/app/res/values-ky/strings.xml @@ -32,7 +32,6 @@ "Bluetooth жандырылсынбы?" "Айнуу" "Жандыруу" - "Файл өткөрүү" "Файлды кабыл аласызбы?" "Жок" "Ооба" @@ -42,10 +41,8 @@ "%1$s түзмөгү %2$s файлын жөнөтүүгө даяр" "Bluetooth аркылуу алынууда: %1$s" "Bluetooth аркылуу алынды: %1$s" - "Файл алынган жок: %1$s" "Bluetooth аркылуу жөнөтүлдү: %1$s" "Bluetooth аркылуу жөнөтүлдү: %1$s" - "100% бүттү" "Файл жөнөтүлгөн жок: %1$s" "Файл өткөрүү" "Жөнөтүүчү: \"%1$s\"" @@ -80,7 +77,6 @@ "Күтө туруңуз…" "Bluetooth жандырылууда…" "Файл алынат. Билдирмелер тактасынан жүрүшүн байкап турсаңыз болот." - "Файлды алуу мүмкүн эмес." "\"%1$s\" жөнөткөн файлды алуу токтотулду" "Кийинкиге файл жөнөтүлүүдө: \"%1$s\"" "\"%2$s\" дарегине %1$s файл жөнөтүлүүдө" @@ -118,7 +114,6 @@ "Тазалоо" "Эмне ойноп жатат?" "Колдонмонун сүрөтчөсү" - "Bluetooth аудио туташты" "Bluetooth аудио ажыратылды" "Bluetooth аудио" "4Гб чоң файлдарды өткөрүү мүмкүн эмес" diff --git a/android/app/res/values-ky/test_strings.xml b/android/app/res/values-ky/test_strings.xml deleted file mode 100644 index bde39cc522d..00000000000 --- a/android/app/res/values-ky/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Жазуу киргизүү" - "Жазууну ырастоо" - "Ack record" - "Бардык жазууларды жок кылуу" - "OK" - "Жазууну жок кылуу" - "TCP серверин баштоо" - "TCP серверин маалымдоо" - diff --git a/android/app/res/values-lo/strings.xml b/android/app/res/values-lo/strings.xml index fb22bff77c5..ad53965a134 100644 --- a/android/app/res/values-lo/strings.xml +++ b/android/app/res/values-lo/strings.xml @@ -32,7 +32,6 @@ "ເປີດ Bluetooth ດຽວນີ້ບໍ່?" "ຍົກເລີກ" "ເປີດ" - "ການໂອນໄຟລ໌" "ຮັບເອົາໄຟລ໌ທີ່ເຂົ້າມາບໍ?" "ປະຕິເສດ" "ຮັບເອົາ" @@ -42,10 +41,8 @@ "%1$s ພ້ອມສົ່ງໄຟລ໌ແລ້ວ: %2$s" "ແບ່ງປັນໃນ Bluetooth: ກຳລັງຮັບເອົາ %1$s" "ແບ່ງປັນໃນ Bluetooth: ໄດ້ຮັບ %1$s ແລ້ວ" - "ແບ່ງປັນໃນ Bluetooth: ບໍ່ໄດ້ຮັບ %1$s" "ແບ່ງປັນໃນ Bluetooth: ກຳລັງສົ່ງ %1$s" "ແບ່ງປັນໃນ Bluetooth: ສົ່ງ %1$s ແລ້ວ" - "100​% ສໍາ​ເລັດແລ້ວ" "ແບ່ງປັນໃນ Bluetooth: ໄຟລ໌%1$s ບໍ່ໄດ້ຖືກສົ່ງ" "ໂອນໄຟລ໌" "ຈາກ: \"%1$s\"" @@ -80,7 +77,6 @@ "ກະລຸນາລໍຖ້າ..." "ກຳລັງເປີດ Bluetooth..." "ຈະໄດ້ຮັບໄຟລ໌ດັ່ງກ່າວ. ກວດສອບການດຳເນີນການໃນແຜງການແຈ້ງເຕືອນ." - "ບໍ່ສາມາດຮັບໄຟລ໌ໄດ້." "ຢຸດການຮັບໄຟລ໌ຈາກ \"%1$s\" ແລ້ວ" "ກຳລັງສົ່ງໄຟລ໌ໄປຫາ \"%1$s\"" "ກຳລັງສົ່ງ %1$s ໄຟລ​໌​ໄປຫາ \"%2$s\"" @@ -118,7 +114,6 @@ "ລຶບ" "Now Playing" "​ໄອ​ຄອນ​ແອັບ​ພລິ​ເຄ​ຊັນ" - "ເຊື່ອມຕໍ່ສຽງ Bluetooth ແລ້ວ" "ຕັດການເຊື່ອມຕໍ່ສຽງ Bluetooth ແລ້ວ" "ສຽງ Bluetooth" "ບໍ່ສາມາດໂອນຍ້າຍໄຟລ໌ທີ່ໃຫຍກວ່າ 4GB ໄດ້" diff --git a/android/app/res/values-lo/test_strings.xml b/android/app/res/values-lo/test_strings.xml deleted file mode 100644 index c23f2870a8b..00000000000 --- a/android/app/res/values-lo/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "ໃສ່ບັນທຶກ" - "ຢືນຢັນການບັນທຶກ" - "ບັນທຶກ Ack" - "ລຶບບັນທຶກທັງໝົດ" - "ຕົກລົງ" - "ລຶບການບັນທຶກ" - "ເລີ່ມ TCP ເຊີບເວີ" - "ແຈ້ງເຕືອນ TCP ເຊີບເວີ" - diff --git a/android/app/res/values-lt/strings.xml b/android/app/res/values-lt/strings.xml index fbf319316de..c41fda950c7 100644 --- a/android/app/res/values-lt/strings.xml +++ b/android/app/res/values-lt/strings.xml @@ -32,7 +32,6 @@ "Įjungti „Bluetooth“ dabar?" "Atšaukti" "Įjungti" - "Failo perkėlimas" "Priimti gaunamą failą?" "Atmesti" "Priimti" @@ -42,10 +41,8 @@ "Įrenginys („%1$s“) pasirengęs siųsti failą: „%2$s“" "„Bluetooth“ bendrinimas: gaunamas %1$s" "„Bluetooth“ bendrinimas: %1$s gautas" - "„Bluetooth“ bendrinimas: %1$s failas negautas" "„Bluetooth“ bendrinimas: siunčiamas %1$s" "„Bluetooth“ bendrinimas: %1$s išsiųstas" - "100 % baigta" "„Bluetooth“ bendrinimas: %1$s failas neišsiųstas" "Failo perkėlimas" "Nuo: %1$s" @@ -80,7 +77,6 @@ "Palaukite..." "Įjungiamas „Bluetooth“…" "Failas bus gautas. Patikrinkite eigą skydelyje „Pranešimai“." - "Failo negalima gauti." "Sustabdytas failo gavimas iš %1$s" "%1$s siunčiamas failas" "%2$s siunčiami (-a) %1$s failai (-ų)" @@ -118,7 +114,6 @@ "Išvalyti" "Dabar leidžiama" "Programos piktograma" - "„Bluetooth“ garsas prijungtas" "„Bluetooth“ garsas atjungtas" "„Bluetooth“ garsas" "Negalima perkelti didesnių nei 4 GB failų" diff --git a/android/app/res/values-lt/test_strings.xml b/android/app/res/values-lt/test_strings.xml deleted file mode 100644 index 8849db8b2f2..00000000000 --- a/android/app/res/values-lt/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Įterpti įrašą" - "Patvirtinti įrašą" - "Įrašas apie patvirtinimą" - "Ištrinti visus įrašus" - "Gerai" - "Ištrinti įrašą" - "Paleisti TCP serverį" - "Pranešti TCP serveriui" - diff --git a/android/app/res/values-lv/strings.xml b/android/app/res/values-lv/strings.xml index 1083668a130..0e0acd23d0c 100644 --- a/android/app/res/values-lv/strings.xml +++ b/android/app/res/values-lv/strings.xml @@ -32,7 +32,6 @@ "Vai ieslēgt tehnoloģiju Bluetooth?" "Atcelt" "Ieslēgt" - "Faila pārsūtīšana" "Vai pieņemt ienākošo failu?" "Noraidīt" "Piekrist" @@ -42,10 +41,8 @@ "Lietotājs %1$s ir gatavs nosūtīt failu: %2$s" "Kopīgošana, izmantojot Bluetooth: notiek faila %1$s saņemšana" "Kopīgošana, izmantojot Bluetooth: saņemts fails %1$s" - "Kopīgošana, izmantojot Bluetooth: fails %1$s netika saņemts" "Kopīgošana, izmantojot Bluetooth: notiek faila %1$s sūtīšana" "Kopīgošana, izmantojot Bluetooth: nosūtīts fails %1$s" - "100% pabeigts" "Kopīgošana, izmantojot Bluetooth: fails %1$s netika nosūtīts" "Faila pārsūtīšana" "No: %1$s" @@ -80,7 +77,6 @@ "Lūdzu, uzgaidiet…" "Tiek ieslēgts Bluetooth savienojums..." "Fails tiks saņemts. Skatiet progresu paziņojumu panelī." - "Failu nevar saņemt." "Faila saņemšana no sūtītāja %1$s tika apturēta." "Notiek faila sūtīšana saņēmējam %1$s" "Notiek %1$s failu sūtīšana saņēmējam %2$s." @@ -118,7 +114,6 @@ "Notīrīšana" "Tagad atskaņo" "Lietojumprogrammas ikona" - "Izveidots savienojums ar Bluetooth audio" "Pārtraukts savienojums ar Bluetooth audio" "Bluetooth audio" "Nevar pārsūtīt failus, kas lielāki par 4 GB." diff --git a/android/app/res/values-lv/test_strings.xml b/android/app/res/values-lv/test_strings.xml deleted file mode 100644 index 8374b3b26ed..00000000000 --- a/android/app/res/values-lv/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Ievietot ierakstu" - "Ieraksta apstiprinājums" - "Ack ieraksts" - "Dzēst visus ierakstus" - "Labi" - "Dzēst ierakstu" - "Palaist TCP serveri" - "Paziņot TCP serverim" - diff --git a/android/app/res/values-mk/strings.xml b/android/app/res/values-mk/strings.xml index 551fd57ab9a..3dccabca142 100644 --- a/android/app/res/values-mk/strings.xml +++ b/android/app/res/values-mk/strings.xml @@ -32,7 +32,6 @@ "Вклучи Bluetooth сега?" "Откажи" "Вклучи" - "Пренос на датотека" "Да се прифати дојдовната датотека?" "Одбиј" "Прифати" @@ -42,10 +41,8 @@ "%1$s е подготвен да испрати датотека: %2$s" "Bluetooth: се прима %1$s" "Bluetooth: %1$s е примена" - "Bluetooth: датотеката %1$s не е примена" "Bluetooth: се испраќа %1$s" "Bluetooth: %1$s е испратена" - "100% завршено" "Bluetooth: датотеката %1$s не е испратена" "Пренос на датотеки" "Од: „%1$s“" @@ -80,7 +77,6 @@ "Почекајте..." "Вклучување Bluetooth..." "Датотеката ќе биде примена. Напредокот проверете го во таблата за известувања." - "Датотеката не може да се прими." "Примањето на датотеката од „%1$s“ запре" "Се испраќа датотека до „%1$s“" "Се испраќаат %1$s датотеки до „%2$s“" @@ -118,7 +114,6 @@ "Исчисти" "Now Playing" "Икона на апликацијата" - "Аудиото преку Bluetooth е поврзано" "Аудиото преку Bluetooth е исклучено" "Аудио преку Bluetooth" "Не може да се пренесуваат датотеки поголеми од 4 GB" diff --git a/android/app/res/values-mk/test_strings.xml b/android/app/res/values-mk/test_strings.xml deleted file mode 100644 index 3962738a23c..00000000000 --- a/android/app/res/values-mk/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Вметни запис" - "Потврди запис" - "Ack запис" - "Избриши ги сите записи" - "Во ред" - "Избриши запис" - "Започни TCP сервер" - "Извести TCP сервер" - diff --git a/android/app/res/values-ml/strings.xml b/android/app/res/values-ml/strings.xml index 300845a12b7..4c3c7590cd3 100644 --- a/android/app/res/values-ml/strings.xml +++ b/android/app/res/values-ml/strings.xml @@ -32,7 +32,6 @@ "ഇപ്പോൾ ബ്ലൂടൂത്ത് ഓണാക്കണോ?" "റദ്ദാക്കുക" "ഓൺ ചെയ്യുക" - "ഫയൽ കൈമാറൽ" "ഇൻകമിംഗ് ഫയൽ സ്വീകരിക്കണോ?" "നിരസിക്കുക" "സ്വീകരിക്കുക" @@ -42,10 +41,8 @@ "%1$s, ഫയൽ അയയ്‌ക്കാൻ തയ്യാറാണ്: %2$s" "Bluetooth പങ്കിടൽ: %1$s എന്നത് സ്വീകരിക്കുന്നു" "ബ്ലൂടൂത്ത് പങ്കിടൽ: %1$s ലഭിച്ചു" - "ബ്ലൂടൂത്ത് പങ്കിടൽ: %1$s എന്ന ഫയൽ ലഭിച്ചില്ല." "Bluetooth പങ്കിടൽ: %1$s എന്ന ഫയൽ അയയ്‌ക്കുന്നു" "Bluetooth പങ്കിടൽ: %1$s എന്ന ഫയൽ അയച്ചു" - "100% പൂർത്തിയായി" "ബ്ലൂടൂത്ത് പങ്കിടൽ: %1$s എന്ന ഫയൽ അയച്ചില്ല" "ഫയൽ കൈമാറൽ" "അയച്ചത്: \"%1$s\"" @@ -80,7 +77,6 @@ "കാത്തിരിക്കുക…" "ബ്ലൂടൂത്ത് ഓൺ ചെയ്യുന്നു…" "ഫയൽ ലഭിക്കും. അറിയിപ്പ് പാനലിൽ പുരോഗതി പരിശോധിക്കുക." - "ഫയൽ നേടാനാകില്ല." "\"%1$s\" എന്നയാളിൽ നിന്നും ഫയൽ നേടുന്നത് നിർത്തി" "\"%1$s\" എന്നയാൾക്ക് ഫയൽ അയയ്‌ക്കുന്നു" "\"%2$s\" എന്നയാൾക്ക് %1$s ഫയലുകൾ അയയ്‌ക്കുന്നു" @@ -118,7 +114,6 @@ "മായ്‌ക്കുക" "ഇപ്പോൾ പ്ലേ ചെയ്യുന്നത്" "അപ്ലിക്കേഷൻ ഐക്കൺ" - "Bluetooth ഓഡിയോ കണക്‌റ്റുചെയ്തു" "Bluetooth ഓഡിയോ വിച്ഛേദിച്ചു" "Bluetooth ഓഡിയോ" "4GB-യിൽ കൂടുതലുള്ള ഫയലുകൾ കൈമാറാനാവില്ല" diff --git a/android/app/res/values-ml/test_strings.xml b/android/app/res/values-ml/test_strings.xml deleted file mode 100644 index 5439a5c9871..00000000000 --- a/android/app/res/values-ml/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "റെക്കോർഡ് ചേർക്കുക" - "റെക്കോർഡ് സ്ഥിരീകരിക്കുക" - "Ack റെക്കോർഡ്" - "എല്ലാ റെക്കോർഡും ഇല്ലാതാക്കുക" - "ശരി" - "റെക്കോർഡ് ഇല്ലാതാക്കുക" - "TCP സെർവർ ആരംഭിക്കുക" - "TCP സെർവറിനെ അറിയിക്കുക" - diff --git a/android/app/res/values-mn/strings.xml b/android/app/res/values-mn/strings.xml index b384c0169fd..1d6634af976 100644 --- a/android/app/res/values-mn/strings.xml +++ b/android/app/res/values-mn/strings.xml @@ -32,7 +32,6 @@ "Bluetooth-г одоо асаах уу?" "Цуцлах" "Асаах" - "Файл дамжуулалт" "Ирж байгаа файлыг авах уу?" "Татгалзах" "Зөвшөөрөх" @@ -42,10 +41,8 @@ "%1$s файлыг илгээхэд бэлэн байна: %2$s" "Bluetooth хуваалцах: Хүлээн авч байна %1$s" "Bluetooth хуваалцах: Хүлээн авсан %1$s" - "Bluetooth хуваалцах: Файл %1$s хүлээж аваагүй" "Bluetooth хуваалцах: Илгээж байна %1$s" "Bluetooth хуваалцах: Илгээсэн %1$s" - "100% дууссан" "Bluetooth хуваалцах: %1$s файл илгээгдээгүй" "Файл дамжуулалт" "Илгээгч: \"%1$s\"" @@ -80,7 +77,6 @@ "Түр хүлээнэ үү..." "Bluetooth-г асааж байна…" "Файлыг хүлээж авах болно. Мэдэгдлийн самбар дээрээс явцыг нь шалгана уу." - "Файлыг хүлээн авах боломжгүй." "\"%1$s\"-с файл хүлээн авахыг зогсоосон" "\"%1$s\" руу файлыг илгээж байна" "%1$s файлуудыг \"%2$s\" руу илгээж байна" @@ -118,7 +114,6 @@ "Арилгах" "Now Playing" "Аппликейшний дүрс" - "Bluetooth аудиог холбосон" "Bluetooth аудиог салгасан" "Bluetooth Аудио" "4ГБ-с дээш хэмжээтэй файлыг шилжүүлэх боломжгүй" diff --git a/android/app/res/values-mn/test_strings.xml b/android/app/res/values-mn/test_strings.xml deleted file mode 100644 index 3dc05cb5da2..00000000000 --- a/android/app/res/values-mn/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Бичлэг оруулах" - "Бичлэгийг баталгаажуулах" - "Ack бичлэг" - "Бүх бичлэгийг устгах" - "OK" - "Бичлэгийг устгах" - "TCP серверийг эхлүүлэх" - "TCP серверт мэдэгдэх" - diff --git a/android/app/res/values-mr/strings.xml b/android/app/res/values-mr/strings.xml index 6cba710ce48..904ca67561b 100644 --- a/android/app/res/values-mr/strings.xml +++ b/android/app/res/values-mr/strings.xml @@ -32,7 +32,6 @@ "आता ब्लूटूथ सुरू करायचे?" "रद्द करा" "सुरू करा" - "फाइल स्थानांतरण" "येणारी फाइल स्‍वीकारायची?" "नकार द्या" "स्वीकारा" @@ -42,10 +41,8 @@ "%1$s फाइल पाठवण्यास तयार आहे: %2$s" "ब्लूटूथ शेअर: %1$s मिळवत आहे" "ब्लूटूथ शेअर: %1$s प्राप्त केली" - "ब्लूटूथ शेअर: %1$s फाइल प्राप्त केली नाही" "ब्लूटूथ शेअर: %1$s पाठवत आहे" "ब्लूटूथ शेअर: %1$s पाठवली" - "100% पूर्ण" "ब्लूटूथ शेअर: %1$s फाइल पाठवली नाही" "फाइल स्थानांतरण" "प्रेेषक: \"%1$s\"" @@ -80,7 +77,6 @@ "कृपया प्रतीक्षा करा..." "ब्लूटूथ सुरू करत आहे…" "फाइल मिळेल. सूचना पॅनल मधील प्रगती तपासा." - "फाइल प्राप्त होऊ शकत नाही." "\"%1$s\" कडील फाइल प्राप्त करणे थांबविले" "\"%1$s\" ना फाइल पाठवित आहे" "\"%2$s\" ना %1$s फाइल पाठवित आहे" @@ -118,7 +114,6 @@ "साफ करा" "आता प्ले करत आहे" "ॲप्लिकेशन आयकन" - "ब्लूटूथ ऑडिओ कनेक्ट केला" "ब्लूटूथ ऑडिओ डिस्कनेक्ट केला" "ब्लूटूथ ऑडिओ" "4 GB हून मोठ्या फाइल ट्रान्सफर करता येणार नाहीत" diff --git a/android/app/res/values-mr/test_strings.xml b/android/app/res/values-mr/test_strings.xml deleted file mode 100644 index 82816017efb..00000000000 --- a/android/app/res/values-mr/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ब्लूटूथ" - "रेकॉर्ड घाला" - "रेकॉर्डची पुष्टी करा" - "Ack रेकॉर्ड" - "सर्व रेकॉर्ड हटवा" - "ठीक" - "रेकॉर्ड हटवा" - "TCP सर्व्‍हर सुरू करा" - "TCP सर्व्‍हरला सूचित करा" - diff --git a/android/app/res/values-ms/strings.xml b/android/app/res/values-ms/strings.xml index c1a0b1b52c6..45f008bb911 100644 --- a/android/app/res/values-ms/strings.xml +++ b/android/app/res/values-ms/strings.xml @@ -32,7 +32,6 @@ "Hidupkan Bluetooth sekarang?" "Batal" "Hidupkan" - "Pemindahan fail" "Terima fail masuk?" "Tolak" "Terima" @@ -42,10 +41,8 @@ "%1$s bersedia menghantar fail: %2$s" "Perkongsian Bluetooth: Menerima %1$s" "Perkongsian Bluetooth: Diterima %1$s" - "Perkongsian Bluetooth: Fail %1$s tidak diterima" "Perkongsian Bluetooth: Menghantar %1$s" "Perkongsian Bluetooth: %1$s dihantar" - "Selesai 100%" "Perkongsian Bluetooth: Fail %1$s tidak dihantar" "Pemindahan fail" "Daripada: \"%1$s\"" @@ -80,7 +77,6 @@ "Sila tunggu..." "Menghidupkan Bluetooth..." "Fail akan diterima. Semak kemajuan dalam panel Pemberitahuan." - "Fail tidak boleh diterima." "Penerimaan fail daripada \"%1$s\" dihentikan" "Menghantar fail kepada \"%1$s\"" "Menghantar %1$s fail kepada \"%2$s\"" @@ -118,7 +114,6 @@ "Padam bersih" "Now Playing" "Ikon Aplikasi" - "Audio Bluetooth disambungkan" "Audio Bluetooth diputuskan sambungannya" "Audio Bluetooth" "Fail lebih besar daripada 4GB tidak boleh dipindahkan" diff --git a/android/app/res/values-ms/test_strings.xml b/android/app/res/values-ms/test_strings.xml deleted file mode 100644 index a83adac4dbc..00000000000 --- a/android/app/res/values-ms/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Masukkan rekod" - "Sahkan rekod" - "Rekod Ack" - "Padamkan semua rekod" - "OK" - "Padamkan rekod" - "Mulakan pelayan TCP" - "Beritahu pelayan TCP" - diff --git a/android/app/res/values-my/strings.xml b/android/app/res/values-my/strings.xml index e528721c14f..e3c3812b5df 100644 --- a/android/app/res/values-my/strings.xml +++ b/android/app/res/values-my/strings.xml @@ -32,7 +32,6 @@ "ယခုပင် ဘလူးတုသ်ကိုဖွင့်မည်လား?" "မလုပ်တော့" "ဖွင့်မည်" - "ဖိုင်လွှဲပြောင်းခြင်း" "အဝင်ဖိုင်ကို လက်ခံမလား။" "လက်မခံပါ" "လက်ခံရန်" @@ -42,10 +41,8 @@ "%1$s သည် ဤဖိုင်ကို ပို့ရန်အသင့်ဖြစ်ပါပြီ- %2$s" "ဘလူးတုသ် ဝေမျှမှု - လက်ခံနေသည့်ဖိုင် %1$s" "ဘလူးတုသ် ဝေမျှမှု - ရရှိပြီး%1$s" - "ဘလူးတုသ် ဝေမျှမှု - ဖိုင် %1$s မရရှိပါ" "ဘလူးတုသ် ဝေမျှမှု - ပို့နေသည့်ဖိုင် %1$s" "ဘလူးတုသ် ဝေမျှမှု - %1$s ပို့ပြီး" - "၁၀၀%ပြီးပါပြီ" "ဘလူးတုသ် ဝေမျှမှု - ဖိုင်%1$s မပို့ပါ" "ဖိုင်လွှဲပြောင်းခြင်း" "မှ - \"%1$s\"" @@ -80,7 +77,6 @@ "ကျေးဇူးပြု၍ ခဏစောင့်ပါ…" "ဘလူးတုသ် ဖွင့်နေသည်" "ဖိုင်ကို လက်ခံပါမည် အကြောင်းကြားချက် အကန့်ထဲတွင် တိုးတက်မှုကိုကြည့်ပါ" - "ဤဖိုင်ကိုလက်ခံမရပါ" "\"%1$s\"မှ ဖိုင်ကို လက်ခံခြင်းအား ရပ်ပါ" "\"%1$s\"ထံသို့ ဖိုင်ကိုပို့ပါ" "%1$s ဖိုင်ကို \"%2$s\"ထံသို့ ပို့ပါ" @@ -118,7 +114,6 @@ "ရှင်းရန်" "Now Playing" "အပလီကေးရှင်း သင်္ကေတ" - "ဘလူးတုသ်အသံ ချိတ်ဆက်ပြီးပါပြီ" "ဘလူးတုသ်အသံ မချိတ်ဆက်ထားပါ" "ဘလူးတုသ် အသံ" "4GB ထက်ပိုကြီးသည့် ဖိုင်များကို လွှဲပြောင်းမရနိုင်ပါ" diff --git a/android/app/res/values-my/test_strings.xml b/android/app/res/values-my/test_strings.xml deleted file mode 100644 index 6544a79f221..00000000000 --- a/android/app/res/values-my/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ဘလူးတုသ်" - "မှတ်တမ်း ထည့်သွင်းရန်" - "မှတ်တမ်းအတည်ပြုရန်" - "အသိအမှတ်ပြု မှတ်တမ်း" - "မှတ်တမ်းအားလုံးကို ဖျက်ရန်" - "OK" - "မှတ်တမ်းကို ဖျက်ရန်" - "TCP ဆာဗာ စတင်ရန်" - "TCP ဆာဗာကို အကြောင်းကြားရန်" - diff --git a/android/app/res/values-nb/strings.xml b/android/app/res/values-nb/strings.xml index e693bf54f59..885544140e7 100644 --- a/android/app/res/values-nb/strings.xml +++ b/android/app/res/values-nb/strings.xml @@ -32,7 +32,6 @@ "Vil du slå på Bluetooth nå?" "Avbryt" "Slå på" - "Filoverføring" "Vil du godta den innkommende filen?" "Avslå" "Godta" @@ -42,10 +41,8 @@ "%1$s er klar til å sende en fil: %2$s" "Bluetooth-deling: Mottar %1$s" "Bluetooth-deling: %1$s er mottatt" - "Bluetooth-deling: Filen %1$s er ikke mottatt" "Bluetooth-deling: Sender %1$s" "Bluetooth-deling: Sendt %1$s" - "100 % fullført" "Bluetooth-deling: Filen %1$s ble ikke sendt" "Filoverføring" "Fra: «%1$s»" @@ -80,7 +77,6 @@ "Vent litt ..." "Aktiverer Bluetooth …" "Filen vil bli mottatt. Du kan se fremdriften i varselpanelet." - "Filen kan ikke mottas." "Stoppet mottak av fil fra «%1$s»" "Sender fil til «%1$s»" "Sender %1$s filer til «%2$s»" @@ -118,7 +114,6 @@ "Tøm" "Spilles nå" "Appikon" - "Bluetooth-lyd er tilkoblet" "Bluetooth-lyd er frakoblet" "Bluetooth-lyd" "Filer som er større enn 4 GB, kan ikke overføres" diff --git a/android/app/res/values-nb/test_strings.xml b/android/app/res/values-nb/test_strings.xml deleted file mode 100644 index 006e778c1cb..00000000000 --- a/android/app/res/values-nb/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Sett inn oppføring" - "Bekreft oppføring" - "Ack-oppføring" - "Slett hele oppføringen" - "OK" - "Slett oppføring" - "Start TPC-tjener" - "Varsle TCP-tjener" - diff --git a/android/app/res/values-ne/strings.xml b/android/app/res/values-ne/strings.xml index 3868160134a..a66476714bf 100644 --- a/android/app/res/values-ne/strings.xml +++ b/android/app/res/values-ne/strings.xml @@ -32,7 +32,6 @@ "अहिले ब्लुटुथ सक्रिय पार्ने हो?" "रद्द गर्नुहोस्" "सक्रिय पार्नुहोस्" - "फाइल स्थानान्तरण" "आगमन फाइल स्वीकार गर्नुहुन्छ?" "अस्वीकार गर्नुहोस्" "स्वीकार्नुहोस्" @@ -42,10 +41,8 @@ "%1$s निम्न फाइल पठाउन तयार हुनुहुन्छ: %2$s" "ब्लुटुथ सेयर:%1$s प्राप्त गर्दै" "ब्लुटुथ सेयर: %1$s प्राप्त भयो" - "ब्लुटुथ सेयर: फाइल: %1$s प्राप्त भएन" "ब्लुटुथ सेयर: %1$s पठाउँदै" "ब्लुटुथ सेयर: %1$s पठाइयो" - "१००% पुरा" "ब्लुटुथ सेयर: फाइल%1$s पठाइएन" "फाइल स्थानान्तरण" "बाट: \"%1$s\"" @@ -80,7 +77,6 @@ "कृपया प्रतीक्षा गर्नुहोस्..." "ब्लुटुथलाई सक्रिय पार्दै..." "फाइल प्राप्त गरिने छ। सूचना प्यानलमा प्रगति जाँच गर्नुहोस्।" - "फाइल प्राप्त गर्न सकिँदैन।" "\"%1$s \"बाट फाइल प्राप्त गर्न बन्द भयो" "\"%1$s\"लाई फाइल पठाउँदै" "%1$s फाइल \"%2$s\"लाई पठाउँदै" @@ -118,7 +114,6 @@ "हटाउनुहोस्" "Now Playing" "एप आइकन" - "ब्लुटुथ सम्बन्धी अडियो यन्त्रलाई जडान गरियो" "ब्लुटुथ सम्बन्धी अडियो यन्त्रलाई डिस्कनेक्ट गरियो" "ब्लुटुथको अडियो" "४ जि.बि. भन्दा ठूला फाइलहरूलाई स्थानान्तरण गर्न सकिँदैन" diff --git a/android/app/res/values-ne/test_strings.xml b/android/app/res/values-ne/test_strings.xml deleted file mode 100644 index fe2df12a825..00000000000 --- a/android/app/res/values-ne/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ब्लुटुथ" - "रेकर्ड राख्नुहोस्" - "रेकर्ड निश्चित गर्नुहोस्" - "Ack रेकर्ड" - "सबै रेकर्ड मेटाउनुहोस्" - "ठिक छ" - "रेकर्ड मेटाउनुहोस्" - "TCP सर्भर सुरु गर्नुहोस्" - "TCP सर्भर सूचित गर्नुहोस्" - diff --git a/android/app/res/values-nl/strings.xml b/android/app/res/values-nl/strings.xml index 47a203c3e9d..9bcf04f6216 100644 --- a/android/app/res/values-nl/strings.xml +++ b/android/app/res/values-nl/strings.xml @@ -32,7 +32,6 @@ "Bluetooth nu aanzetten?" "Annuleren" "Aanzetten" - "Bestandsoverdracht" "Inkomend bestand accepteren?" "Weigeren" "Accepteren" @@ -42,10 +41,8 @@ "%1$s is klaar om een bestand te sturen: %2$s" "Delen via bluetooth: %1$s ontvangen" "Delen via bluetooth: %1$s ontvangen" - "Delen via bluetooth: bestand %1$s niet ontvangen" "Delen via bluetooth: %1$s sturen" "Delen via bluetooth: %1$s verstuurd" - "100% voltooid" "Delen via bluetooth: bestand %1$s niet verstuurd" "Bestandsoverdracht" "Van: \'%1$s\'" @@ -80,7 +77,6 @@ "Een ogenblik geduld..." "Bluetooth aanzetten…" "Het bestand wordt ontvangen. Je kunt de voortgang controleren in het venster \'Meldingen\'." - "Het bestand kan niet worden opgehaald." "Ontvangen van bestand van \'%1$s\' is beëindigd" "Bestand verzenden naar \'%1$s\'" "%1$s bestanden verzenden naar \'%2$s\'" @@ -118,7 +114,6 @@ "Wissen" "Now Playing" "App-icoon" - "Bluetooth-audio gekoppeld" "Bluetooth-audio ontkoppeld" "Bluetooth-audio" "Bestanden groter dan 4 GB kunnen niet worden overgedragen" diff --git a/android/app/res/values-nl/test_strings.xml b/android/app/res/values-nl/test_strings.xml deleted file mode 100644 index 57eab703083..00000000000 --- a/android/app/res/values-nl/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Record invoegen" - "Record bevestigen" - "ACK-record" - "Alle records verwijderen" - "OK" - "Record verwijderen" - "TCP-server starten" - "Melden aan TCP-server" - diff --git a/android/app/res/values-or/strings.xml b/android/app/res/values-or/strings.xml index 194193aea82..146aaad9fb7 100644 --- a/android/app/res/values-or/strings.xml +++ b/android/app/res/values-or/strings.xml @@ -32,7 +32,6 @@ "ବ୍ଲୁ-ଟୁଥ୍‌କୁ ଏବେ ଅନ୍‌ କରିବେ?" "ବାତିଲ କରନ୍ତୁ" "ଚାଲୁ କରନ୍ତୁ" - "ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌ କରନ୍ତୁ" "ଆସୁଥିବା ଫାଇଲକୁ ଗ୍ରହଣ କରିବେ?" "ଅସ୍ୱୀକାର" "ସ୍ୱୀକାର କରନ୍ତୁ" @@ -42,10 +41,8 @@ "%1$s ଏକ ଫାଇଲ୍ ପଠାଇବାକୁ ପ୍ରସ୍ତୁତ ଅଛନ୍ତି: %2$s" "ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: %1$s ପ୍ରାପ୍ତ କରୁଛି" "ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: %1$s ପ୍ରାପ୍ତ କରାଯାଇଛି" - "ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: %1$s ଫାଇଲ୍‌ ପ୍ରାପ୍ତ କରାଯାଇନାହିଁ" "ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: %1$s ପଠାଉଛି" "ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: %1$s ପଠାଗଲା" - "100% ସମ୍ପୂର୍ଣ୍ଣ" "ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: %1$s ଫାଇଲ୍‌ ପଠାଯାଇନାହିଁ" "ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌ କରନ୍ତୁ" "ପ୍ରେରକ: \"%1$s\"" @@ -80,7 +77,6 @@ "ଦୟାକରି ଅପେକ୍ଷା କରନ୍ତୁ…" "ବ୍ଲୁଟୂଥ୍‍‌ ଅନ୍‌ କରୁଛି…" "ଫାଇଲ୍‌କୁ ଗ୍ରହଣ କରାଯିବ। ବିଜ୍ଞପ୍ତି ପ୍ୟାନେଲ୍‌ରେ ପ୍ରଗତିକୁ ଦେଖନ୍ତୁ।" - "ଫାଇଲ୍‌କୁ ଗ୍ରହଣ କରାଯାଇପାରିବ ନାହିଁ।" "\"%1$s\"ଙ୍କଠାରୁ ଗ୍ରହଣ କରିବା ବନ୍ଦ ହୋଇଗଲା" "\"%1$s\"ଙ୍କୁ ଫାଇଲ୍‌ ପଠାଯାଉଛି" "\"%2$s\"ଙ୍କୁ %1$sଟି ଫାଇଲ୍‌ ପଠାଯାଉଛି" @@ -118,7 +114,6 @@ "ଖାଲି କରନ୍ତୁ" "ବର୍ତ୍ତମାନ ଚାଲୁଛି" "ଆପ୍ଲିକେଶନ୍‌ ଆଇକନ୍‌" - "ବ୍ଲୁଟୂଥ୍‍‌ ଅଡିଓ ସଂଯୁକ୍ତ କରାଗଲା" "ବ୍ଲୁଟୂଥ୍‍‌ ଅଡିଓ ବିଚ୍ଛିନ୍ନ କରାଗଲା" "ବ୍ଲୁଟୂଥ୍‍‌ ଅଡିଓ" "4GBରୁ ବଡ଼ ଫାଇଲ୍‌ଗୁଡ଼ିକୁ ଟ୍ରାନ୍ସଫର୍‌ କରାଯାଇପାରିବ ନାହିଁ" diff --git a/android/app/res/values-or/test_strings.xml b/android/app/res/values-or/test_strings.xml deleted file mode 100644 index 1849219b2ce..00000000000 --- a/android/app/res/values-or/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ବ୍ଲୁଟୁଥ" - "ରେକର୍ଡ ଭର୍ତ୍ତି କରନ୍ତୁ" - "ରେକର୍ଡ ସୁନିଶ୍ଚିତ କରନ୍ତୁ" - "ରେକର୍ଡ ସ୍ୱୀକୃତ କରନ୍ତୁ" - "ସମସ୍ତ ରେକର୍ଡ ଡିଲିଟ୍‌ କରନ୍ତୁ" - "ଠିକ ଅଛି" - "ରେକର୍ଡ ଡିଲିଟ୍‌ କରନ୍ତୁ" - "TCP ସର୍ଭର୍‌ ଆରମ୍ଭ କରନ୍ତୁ" - "TCP ସର୍ଭର୍‌କୁ ସୂଚିତ କରନ୍ତୁ" - diff --git a/android/app/res/values-pa/strings.xml b/android/app/res/values-pa/strings.xml index 214145067fe..694dff5e05f 100644 --- a/android/app/res/values-pa/strings.xml +++ b/android/app/res/values-pa/strings.xml @@ -32,7 +32,6 @@ "ਕੀ ਹੁਣ Bluetooth ਚਾਲੂ ਕਰਨੀ ਹੈ?" "ਰੱਦ ਕਰੋ" "ਚਾਲੂ ਕਰੋ" - "ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ" "ਕੀ ਇਨਕਮਿੰਗ ਫ਼ਾਈਲ ਸਵੀਕਾਰ ਕਰਨੀ ਹੈ?" "ਅਸਵੀਕਾਰ ਕਰੋ" "ਸਵੀਕਾਰ ਕਰੋ" @@ -42,10 +41,8 @@ "%1$s ਫ਼ਾਈਲ ਭੇਜਣ ਲਈ ਤਿਆਰ ਹੈ: %2$s" "Bluetooth ਸ਼ੇਅਰ: %1$s ਪ੍ਰਾਪਤ ਕਰ ਰਿਹਾ ਹੈ" "Bluetooth ਸ਼ੇਅਰ: %1$s ਪ੍ਰਾਪਤ ਕੀਤੀ" - "Bluetooth ਸ਼ੇਅਰ: ਫਾਈਲ %1$s ਪ੍ਰਾਪਤ ਨਹੀਂ ਕੀਤੀ" "ਬਲੂਟੁੱਥ ਸਾਂਝਾਕਰਨ: %1$s ਨੂੰ ਭੇਜਿਆ ਜਾ ਰਿਹਾ ਹੈ" "Bluetooth ਸ਼ੇਅਰ: %1$s ਭੇਜੀ ਗਈ" - "100% ਪੂਰਾ" "Bluetooth ਸ਼ੇਅਰ: ਫਾਈਲ %1$s ਨਹੀਂ ਭੇਜੀ ਗਈ" "ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ" "ਇਨ੍ਹਾਂ ਵੱਲੋਂ: \"%1$s\"" @@ -80,7 +77,6 @@ "ਕਿਰਪਾ ਕਰਕੇ ਠਹਿਰੋ..." "Bluetooth ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ…" "ਫ਼ਾਈਲ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾਵੇਗੀ। ਸੂਚਨਾਵਾਂ ਪੈਨਲ ਵਿੱਚ ਪ੍ਰਗਤੀ ਦੀ ਜਾਂਚ ਕਰੋ।" - "ਫਾਈਲ ਪ੍ਰਾਪਤ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।" "\"%1$s\" ਤੋਂ ਫਾਈਲ ਪ੍ਰਾਪਤ ਕਰਨਾ ਰੋਕਿਆ ਗਿਆ" "\"%1$s\" ਨੂੰ ਫਾਈਲ ਭੇਜ ਰਿਹਾ ਹੈ" "\"%2$s\" ਨੂੰ %1$s ਫ਼ਾਈਲਾਂ ਭੇਜੀਆਂ ਜਾ ਰਹੀਆਂ ਹਨ" @@ -118,7 +114,6 @@ "ਕਲੀਅਰ ਕਰੋ" "Now Playing" "ਐਪਲੀਕੇਸ਼ਨ ਪ੍ਰਤੀਕ" - "ਬਲੂਟੁੱਥ ਆਡੀਓ ਕਨੈਕਟ ਕੀਤੀ ਗਈ" "ਬਲੂਟੁੱਥ ਆਡੀਓ ਡਿਸਕਨੈਕਟ ਕੀਤੀ ਗਈ" "ਬਲੂਟੁੱਥ ਆਡੀਓ" "4GB ਤੋਂ ਜ਼ਿਆਦਾ ਵੱਡੀਆਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਟ੍ਰਾਂਸਫ਼ਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" diff --git a/android/app/res/values-pa/test_strings.xml b/android/app/res/values-pa/test_strings.xml deleted file mode 100644 index 26da27eeacc..00000000000 --- a/android/app/res/values-pa/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "ਬਲੂਟੁੱਥ" - "ਰਿਕਾਰਡ ਦਾਖਲ ਕਰੋ" - "ਰਿਕਾਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ" - "Ack ਰਿਕਾਰਡ" - "ਸਾਰੇ ਰਿਕਾਰਡ ਮਿਟਾਓ" - "ਠੀਕ" - "ਰਿਕਾਰਡ ਮਿਟਾਓ" - "TCP ਸਰਵਰ ਚਾਲੂ ਕਰੋ" - "TCP ਸਰਵਰ ਨੂੰ ਸੂਚਿਤ ਕਰੋ" - diff --git a/android/app/res/values-pl/strings.xml b/android/app/res/values-pl/strings.xml index 4a54a184bc7..c718acdff62 100644 --- a/android/app/res/values-pl/strings.xml +++ b/android/app/res/values-pl/strings.xml @@ -32,7 +32,6 @@ "Czy włączyć teraz moduł Bluetooth?" "Anuluj" "Włącz" - "Przesyłanie pliku" "Zaakceptować przesyłany plik?" "Odrzuć" "Akceptuj" @@ -42,10 +41,8 @@ "%1$s może już wysłać plik: %2$s" "Udostępnianie Bluetooth: odbieranie %1$s" "Udostępnianie Bluetooth: odebrano plik %1$s" - "Udostępnianie Bluetooth: nie odebrano pliku %1$s" "Udostępnianie Bluetooth: wysyłanie %1$s" "Udostępnianie Bluetooth: wysłano plik %1$s" - "Ukończono w 100%" "Udostępnianie Bluetooth: nie wysłano pliku %1$s" "Przesyłanie pliku" "Od: „%1$s”" @@ -80,7 +77,6 @@ "Czekaj…" "Włączanie Bluetooth…" "Plik zostanie odebrany. Sprawdzaj postęp w panelu powiadomień." - "Nie można odebrać pliku." "Zatrzymano odbiór pliku z urządzenia „%1$s”" "Wysyłanie pliku do urządzenia „%1$s”" "Wysyłanie %1$s plików do urządzenia „%2$s”" @@ -118,7 +114,6 @@ "Wyczyść" "Co jest grane" "Ikona aplikacji" - "Dźwięk Bluetooth podłączony" "Dźwięk Bluetooth odłączony" "Dźwięk Bluetooth" "Nie można przenieść plików przekraczających 4 GB" diff --git a/android/app/res/values-pl/test_strings.xml b/android/app/res/values-pl/test_strings.xml deleted file mode 100644 index 611c277cc33..00000000000 --- a/android/app/res/values-pl/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Wstaw rekord" - "Potwierdź rekord" - "Rekord Ack" - "Usuń wszystkie rekordy" - "OK" - "Usuń rekord" - "Uruchom serwer TCP" - "Powiadom serwer TCP" - diff --git a/android/app/res/values-pt-rPT/strings.xml b/android/app/res/values-pt-rPT/strings.xml index 9abb75423ff..53bd49f60f4 100644 --- a/android/app/res/values-pt-rPT/strings.xml +++ b/android/app/res/values-pt-rPT/strings.xml @@ -32,7 +32,6 @@ "Ativar o Bluetooth agora?" "Cancelar" "Ativar" - "Transferência do ficheiro" "Aceitar e receber o ficheiro?" "Recusar" "Aceitar" @@ -42,10 +41,8 @@ "%1$s tem tudo pronto para enviar um ficheiro: %2$s" "Partilha Bluetooth: a receber %1$s" "Partilha Bluetooth: %1$s recebido" - "Partilha Bluetooth: Ficheiro %1$s não recebido" "Partilha Bluetooth: a enviar %1$s" "Partilha Bluetooth: %1$s enviado" - "100% concluído" "Partilha Bluetooth: ficheiro %1$s não enviado" "Transferência do ficheiro" "De: \"%1$s\"" @@ -80,7 +77,6 @@ "Aguarde..." "A ligar Bluetooth…" "O ficheiro será recebido. Consulte o progresso no painel Notificações." - "Não é possível receber o ficheiro." "A recepção do ficheiro de \"%1$s\" foi interrompida" "A enviar ficheiro para \"%1$s\"" "A enviar %1$s ficheiros para \"%2$s\"" @@ -118,7 +114,6 @@ "Limpar" "A tocar" "Ícone de app" - "Áudio Bluetooth ligado" "Áudio Bluetooth desligado" "Áudio Bluetooth" "Não é possível transferir os ficheiros com mais de 4 GB." diff --git a/android/app/res/values-pt-rPT/test_strings.xml b/android/app/res/values-pt-rPT/test_strings.xml deleted file mode 100644 index 37dbfad808b..00000000000 --- a/android/app/res/values-pt-rPT/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Inserir registo" - "Confirmar registo" - "Registo de confirmação" - "Eliminar todo o registo" - "OK" - "Eliminar registo" - "Iniciar servidor TCP" - "Notificar servidor TCP" - diff --git a/android/app/res/values-pt/strings.xml b/android/app/res/values-pt/strings.xml index 5954cb275c5..2d7ddb5a7a4 100644 --- a/android/app/res/values-pt/strings.xml +++ b/android/app/res/values-pt/strings.xml @@ -32,7 +32,6 @@ "Ativar Bluetooth agora?" "Cancelar" "Ativar" - "Transferência de arquivo" "Aceitar o arquivo transferido?" "Recusar" "Aceitar" @@ -42,10 +41,8 @@ "%1$s já pode enviar um arquivo: %2$s" "Bluetooth: recebendo %1$s" "Bluetooth: %1$s recebido" - "Bluetooth: arquivo %1$s não recebido" "Bluetooth: enviando %1$s" "Bluetooth: %1$s enviado" - "100% concluído" "Bluetooth: arquivo %1$s não enviado" "Transferência de arquivo" "De: \"%1$s\"" @@ -80,7 +77,6 @@ "Aguarde..." "Ativando Bluetooth..." "O arquivo será recebido. Verifique o andamento no painel de Notificações." - "Não é possível receber o arquivo." "O recebimento do arquivo de \"%1$s\" foi interrompido" "Enviando arquivo para \"%1$s\"" "Enviando %1$s arquivos para \"%2$s\"" @@ -118,7 +114,6 @@ "Limpar" "Tocando agora" "Ícone do app" - "Áudio Bluetooth conectado" "Áudio Bluetooth desconectado" "Áudio Bluetooth" "Não é possível transferir arquivos maiores que 4 GB" diff --git a/android/app/res/values-pt/test_strings.xml b/android/app/res/values-pt/test_strings.xml deleted file mode 100644 index 7cca62e933b..00000000000 --- a/android/app/res/values-pt/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Inserir registro" - "Confirmar registro" - "Confirmar registro" - "Excluir todos os registros" - "OK" - "Excluir registro" - "Iniciar servidor TCP" - "Notificar servidor TCP" - diff --git a/android/app/res/values-ro/strings.xml b/android/app/res/values-ro/strings.xml index 63ea8c124e4..06deaef5924 100644 --- a/android/app/res/values-ro/strings.xml +++ b/android/app/res/values-ro/strings.xml @@ -32,7 +32,6 @@ "Activezi acum Bluetooth?" "Anulează" "Activează" - "Transfer de fișier" "Accepți fișierul primit?" "Refuză" "Acceptă" @@ -42,10 +41,8 @@ "%1$s este gata să trimită un fișier: %2$s" "Distribuire prin Bluetooth: se primește %1$s" "Distribuire prin Bluetooth: s-a primit %1$s" - "Distribuire prin Bluetooth: fișierul %1$s nu s-a primit" "Distribuire prin Bluetooth: se trimite %1$s" "Distribuire prin Bluetooth: s-a trimis %1$s" - "100 % finalizat" "Distribuire prin Bluetooth: fișierul %1$s nu a fost trimis" "Transfer de fișier" "De la: „%1$s”" @@ -80,7 +77,6 @@ "Așteaptă..." "Se activează Bluetooth..." "Se va primi fișierul. Verifică progresul în panoul de notificări." - "Fișierul nu poate fi primit." "Primirea fișierului de la „%1$s” a fost anulată" "Se trimite fișierul către „%1$s”" "Se trimit %1$s fișiere către „%2$s”" @@ -118,7 +114,6 @@ "Șterge" "Now Playing" "Pictograma aplicației" - "Audio prin Bluetooth conectat" "Audio prin Bluetooth deconectat" "Audio prin Bluetooth" "Fișierele mai mari de 4 GB nu pot fi transferate" diff --git a/android/app/res/values-ro/test_strings.xml b/android/app/res/values-ro/test_strings.xml deleted file mode 100644 index c2393c5fb0a..00000000000 --- a/android/app/res/values-ro/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Inserează o înregistrare" - "Confirmă înregistrarea" - "Înregistrare Ack" - "Șterge toate înregistrările" - "OK" - "Șterge înregistrarea" - "Pornește serverul TCP" - "Notifică serverul TCP" - diff --git a/android/app/res/values-ru/strings.xml b/android/app/res/values-ru/strings.xml index 04ef278346b..98fd8e6b76b 100644 --- a/android/app/res/values-ru/strings.xml +++ b/android/app/res/values-ru/strings.xml @@ -32,7 +32,6 @@ "Включить Bluetooth?" "Отмена" "Включить" - "Передача файла" "Принять файл?" "Отклонить" "Принять" @@ -42,10 +41,8 @@ "Устройство \"%1$s\" готово к отправке файла \"%2$s\"" "Передача по Bluetooth: %1$s" "Получено по Bluetooth: %1$s" - "Файл не передан: %1$s" "Отправка по Bluetooth: %1$s" "Передано по Bluetooth: %1$s" - "100% завершено." "Файл не передан: %1$s" "Передача файла" "От: \"%1$s\"" @@ -80,7 +77,6 @@ "Подождите..." "Включение Bluetooth..." "Этот файл будет получен. Ход выполнения отображается на панели уведомлений." - "Невозможно получить файл." "Получение файла от \"%1$s\" прервано" "Отправка файла на \"%1$s\"" "Отправка файлов (%1$s) на \"%2$s\"" @@ -118,7 +114,6 @@ "Очистить" "Что сейчас играет?" "Значок приложения" - "Звук через Bluetooth включен" "Звук через Bluetooth отключен" "Звук через Bluetooth" "Можно перенести только файлы размером до 4 ГБ." diff --git a/android/app/res/values-ru/test_strings.xml b/android/app/res/values-ru/test_strings.xml deleted file mode 100644 index b0d723a95b5..00000000000 --- a/android/app/res/values-ru/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Вставить запись" - "Подтвердить запись" - "Запись подтверждения" - "Удалить все записи" - "ОК" - "Удалить запись" - "Запустить TCP-сервер" - "Уведомить TCP-сервер" - diff --git a/android/app/res/values-si/strings.xml b/android/app/res/values-si/strings.xml index b3ee8a44f48..3242bc62a34 100644 --- a/android/app/res/values-si/strings.xml +++ b/android/app/res/values-si/strings.xml @@ -32,7 +32,6 @@ "දැන් බ්ලූටූත් සක්‍රිය කරන්නද?" "අවලංගු කරන්න" "ක්‍රියාත්මක කරන්න" - "ගොනු මාරුව" "ඇතුළට එන ගොනුව පිළිගන්නද?" "ප්‍රතික්ෂේප කරන්න" "පිළිගන්න" @@ -42,10 +41,8 @@ "%1$s ගොනුවක් යැවීමට සූදානම්ය: %2$s" "බ්ලූටූත් බෙදා ගැනීම: %1$s ලැබේ" "බ්ලූටූත් බෙදා ගැනීම: %1$s ලැබිණි" - "බ්ලූටූත් බෙදා ගැනීම: %1$s ගොනුව නොලැබිණි" "බ්ලූටූත් බෙදා ගැනීම: %1$s යැවේ" "බ්ලූටූත් බෙදා ගැනීම: %1$s යවන්න" - "100% සම්පූර්ණයි" "බ්ලූටූත් බෙදා ගැනීම: %1$s ගොනුව නොයැවිණි" "ගොනු මාරුව" "වෙතින්: \"%1$s\"" @@ -80,7 +77,6 @@ "කරුණාකර රැඳී සිටින්න..." "බ්ලූටූත් සක්‍රිය කෙරේ…" "ගොනුව ලැබෙනු ඇත. දැනුම්දීම් පුවරුව තුළ ප්‍රගතිය පරික්ෂා කරන්න." - "ගොනුව ලැබිය නොහැක." "\"%1$s\" වෙතින් ගොනුව ලැබීම නතර විය" "\"%1$s\" වෙත ගොනුව යැවේ" "\"%2$s\" වෙත %1$s ගොනු යැවේ" @@ -118,7 +114,6 @@ "හිස් කරන්න" "දැන් වාදනය වේ" "යෙදුම් නිරූපකය" - "බ්ලූටූත් ශ්‍රව්‍යය සම්බන්ධ කරන ලදී" "බ්ලූටූත් ශ්‍රව්‍යය විසන්ධි කරන ලදී" "බ්ලූටූත් ශ්‍රව්‍යය" "4GBට වඩා විශාල ගොනු මාරු කළ නොහැකිය" diff --git a/android/app/res/values-si/test_strings.xml b/android/app/res/values-si/test_strings.xml deleted file mode 100644 index 0b2b09c7d06..00000000000 --- a/android/app/res/values-si/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "බ්ලූටූත්" - "වාර්තාව ඇතුළු කරන්න" - "වාර්තාව සහතික කරන්න" - "Ack වාර්තාව" - "සියලු වාර්තා මකන්න" - "හරි" - "වාර්තාව මකන්න" - "TCP සේවාදායකය ආරම්භ කරන්න" - "TCP සේවාදායකයට දැනුම් දෙන්න" - diff --git a/android/app/res/values-sk/strings.xml b/android/app/res/values-sk/strings.xml index 95389370b43..b6a01f2eecd 100644 --- a/android/app/res/values-sk/strings.xml +++ b/android/app/res/values-sk/strings.xml @@ -32,7 +32,6 @@ "Zapnúť Bluetooth?" "Zrušiť" "Zapnúť" - "Prenos súborov" "Prijať prichádzajúci súbor?" "Odmietnuť" "Prijať" @@ -42,10 +41,8 @@ "Používateľ %1$s je pripravený odoslať súbor %2$s" "Bluetooth: Prijíma sa %1$s" "Bluetooth: %1$s prijatý" - "Bluetooth: %1$s neprijatý" "Bluetooth: Odosiela sa %1$s" "Bluetooth: %1$s odoslaný" - "100 % hotovo" "Bluetooth: %1$s neodoslaný" "Prenos súborov" "Od: %1$s" @@ -80,7 +77,6 @@ "Čakajte..." "Prebieha zapínanie rozhrania Bluetooth..." "Prebehne prijatie súboru. Priebeh môžete sledovať na paneli Oznámenie." - "Súbor nemôže byť prijatý." "Prijímanie súboru od používateľa %1$s bolo zastavené" "Odosielanie súboru používateľovi %1$s" "Odosielanie súborov (počet: %1$s) používateľovi %2$s" @@ -118,7 +114,6 @@ "Vymazať" "Čo to hrá" "Ikona aplikácie" - "Rozhranie Bluetooth Audio je pripojené" "Rozhranie Bluetooth Audio je odpojené" "Bluetooth Audio" "Súbory väčšie ako 4 GB sa nedajú preniesť" diff --git a/android/app/res/values-sk/test_strings.xml b/android/app/res/values-sk/test_strings.xml deleted file mode 100644 index 619d58a1ce9..00000000000 --- a/android/app/res/values-sk/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Vložiť záznam" - "Potvrdiť záznam" - "Záznam ACK" - "Odstrániť všetky záznamy" - "OK" - "Odstrániť záznam" - "Spustiť server TCP" - "Upozorniť server TCP" - diff --git a/android/app/res/values-sl/strings.xml b/android/app/res/values-sl/strings.xml index fc978512e5c..b134e176da6 100644 --- a/android/app/res/values-sl/strings.xml +++ b/android/app/res/values-sl/strings.xml @@ -32,7 +32,6 @@ "Vklopim Bluetooth?" "Prekliči" "Vklopi" - "Prenos datoteke" "Želite sprejeti dohodno datoteko?" "Zavrni" "Sprejmi" @@ -42,10 +41,8 @@ "Naprava %1$s je pripravljena na pošiljanje datoteke %2$s." "Bluetooth: Prejemanje %1$s" "Bluetooth: Prejeto %1$s" - "Bluetooth: Datoteka %1$s ni bila prejeta" "Bluetooth: Pošiljanje %1$s" "Bluetooth: Poslano %1$s" - "Dokončano: 100 %" "Bluetooth: Datoteka %1$s ni bila poslana" "Prenos datoteke" "Od: »%1$s«" @@ -80,7 +77,6 @@ "Počakajte ..." "Vklop Bluetootha …" "Datoteka bo prejeta. Potek preverite na plošči »Obvestila«." - "Datoteke ni mogoče prejeti." "Prejemanje datoteke pošiljatelja »%1$s« je ustavljeno" "Pošiljanje datoteke prejemniku »%1$s«" "Pošiljanje %1$s datotek prejemniku »%2$s«" @@ -118,7 +114,6 @@ "Počisti" "Zdaj se predvaja" "Ikona aplikacije" - "Zvok prek Bluetootha je povezan" "Zvok prek Bluetootha ni povezan" "Zvok prek Bluetootha" "Datotek, večjih od 4 GB, ni mogoče prenesti" diff --git a/android/app/res/values-sl/test_strings.xml b/android/app/res/values-sl/test_strings.xml deleted file mode 100644 index 50d76a43996..00000000000 --- a/android/app/res/values-sl/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Vstavi zapis" - "Potrdi zapis" - "Zapis potrditve" - "Izbriši ves zapis" - "V redu" - "Izbriši zapis" - "Zaženi strežnik TCP" - "Obvesti strežnik TCP" - diff --git a/android/app/res/values-sq/strings.xml b/android/app/res/values-sq/strings.xml index 7954937a818..50f94d2b88d 100644 --- a/android/app/res/values-sq/strings.xml +++ b/android/app/res/values-sq/strings.xml @@ -32,7 +32,6 @@ "Të aktivizohet bluetooth-i tani?" "Anulo" "Aktivizo" - "Transferimi i skedarit" "Të pranohet skedari?" "Refuzo" "Prano" @@ -42,10 +41,8 @@ "%1$s është gati të dërgojë një skedar: %2$s" "Ndarja përmes bluetooth-it: Po merret skedari %1$s" "Ndarja përmes bluetooth-it: U pranua skedari %1$s" - "Ndarja përmes bluetooth-it: Skedari %1$s nuk u pranua" "Ndarja përmes bluetooth-it: Po dërgohet skedari %1$s" "Ndarja përmes Bluetooth-it: Skedari %1$s u dërgua" - "100% i përfunduar" "Ndarja përmes Bluetooth-it: Skedari %1$s nuk u dërgua" "Transferimi i skedarit" "Nga: \"%1$s\"" @@ -80,7 +77,6 @@ "Qëndro në pritje..." "Po aktivizon bluetooth-in…" "Skedari do të pranohet. Kontrollo ecurinë në panelin \"Njoftimet\"." - "Ky skedar nuk mund të pranohet." "Ndaloi marrjen e skedarit nga \"%1$s\"" "Po e dërgon skedarin te \"%1$s\"" "Po dërgon %1$s skedarë te \"%2$s\"" @@ -118,7 +114,6 @@ "Pastro" "Po luhet tani" "Ikona e aplikacionit" - "Audioja e \"bluetooth-it\" e lidhur" "Audioja e \"bluetooth-it\" e shkëputur" "Audioja e \"bluetooth-it\"" "Skedarët më të mëdhenj se 4 GB nuk mund të transferohen" diff --git a/android/app/res/values-sq/test_strings.xml b/android/app/res/values-sq/test_strings.xml deleted file mode 100644 index a44def6cd54..00000000000 --- a/android/app/res/values-sq/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth-i" - "Fut të dhëna" - "Konfirmo të dhënat" - "Të dhënat \"Ack\"" - "Fshiji të gjitha të dhënat" - "Në rregull" - "Fshi të dhënat" - "Nis serverin TCP" - "Njofto serverin TCP" - diff --git a/android/app/res/values-sr/strings.xml b/android/app/res/values-sr/strings.xml index 6156e52c75c..2d3f284f856 100644 --- a/android/app/res/values-sr/strings.xml +++ b/android/app/res/values-sr/strings.xml @@ -32,7 +32,6 @@ "Желите ли одмах да укључите Bluetooth?" "Откажи" "Укључи" - "Пренос датотеке" "Желите ли да прихватите долазну датотеку?" "Одбиј" "Прихвати" @@ -42,10 +41,8 @@ "%1$s је спреман/на за слање фајла: %2$s" "Bluetooth дељење: пријем %1$s" "Bluetooth дељење: примљено %1$s" - "Bluetooth дељење: датотека %1$s није примљена" "Bluetooth дељење: слање %1$s" "Bluetooth дељење: послато %1$s" - "Довршено је 100%" "Bluetooth дељење: датотека %1$s није послата" "Пренос датотеке" "Од: „%1$s“" @@ -80,7 +77,6 @@ "Сачекајте…" "Укључивање Bluetooth-а…" "Датотека ће бити примљена. Проверавајте ток на табли са обавештењима." - "Није могуће примити датотеку." "Заустављен пријем датотеке од пошиљаоца „%1$s“" "Слање датотеке примаоцу „%1$s“" "Слање%1$s датотека примаоцу „%2$s“" @@ -118,7 +114,6 @@ "Брисање" "Тренутно свира" "Икона апликације" - "Bluetooth аудио је повезан" "Веза са Bluetooth аудијом је прекинута" "Bluetooth аудио" "Не могу да се преносе датотеке веће од 4 GB" diff --git a/android/app/res/values-sr/test_strings.xml b/android/app/res/values-sr/test_strings.xml deleted file mode 100644 index e36fdb4a4dc..00000000000 --- a/android/app/res/values-sr/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Уметни запис" - "Потврди запис" - "Ack запис" - "Избриши све записе" - "Потврди" - "Избриши запис" - "Покрени TCP сервер" - "Обавести TCP сервер" - diff --git a/android/app/res/values-sv/strings.xml b/android/app/res/values-sv/strings.xml index c3872fb3ca2..ca5870136d5 100644 --- a/android/app/res/values-sv/strings.xml +++ b/android/app/res/values-sv/strings.xml @@ -32,7 +32,6 @@ "Vill du aktivera Bluetooth nu?" "Avbryt" "Aktivera" - "Filöverföring" "Vill du ta emot den inkommande filen?" "Avvisa" "Godkänn" @@ -42,10 +41,8 @@ "%1$s är redo att skicka en fil: %2$s" "Bluetooth-delning: tar emot %1$s" "Bluetooth-delning: %1$s har tagits emot" - "Bluetooth-delning: filen %1$s har inte tagits emot" "Bluetooth-delning: skickar %1$s" "Bluetooth-delning: %1$s har skickats" - "100 % slutfört" "Bluetooth-delning: filen %1$s har inte skickats" "Filöverföring" "Från: %1$s" @@ -80,7 +77,6 @@ "Vänta …" "Bluetooth aktiveras …" "Filen tas emot. Du kan se förloppet på aviseringspanelen." - "Filen kan inte tas emot." "Slutade ta emot fil från %1$s" "Skickar fil till %1$s" "Skickar %1$s filer till %2$s" @@ -118,7 +114,6 @@ "Rensa" "Nu spelas" "Appikon" - "Bluetooth-ljud är anslutet" "Bluetooth-ljud är frånkopplat" "Bluetooth-ljud" "Det går inte att överföra filer som är större än 4 GB" diff --git a/android/app/res/values-sv/test_strings.xml b/android/app/res/values-sv/test_strings.xml deleted file mode 100644 index 0367b921ab5..00000000000 --- a/android/app/res/values-sv/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Infoga post" - "Bekräfta post" - "Bekräftelsepost" - "Ta bort alla poster" - "OK" - "Ta bort post" - "Starta TCP-server" - "Avisera TCP-server" - diff --git a/android/app/res/values-sw/strings.xml b/android/app/res/values-sw/strings.xml index b7476bbb4a9..7e083f204ce 100644 --- a/android/app/res/values-sw/strings.xml +++ b/android/app/res/values-sw/strings.xml @@ -32,7 +32,6 @@ "Je wataka kuwasha Bluetooth sasa?" "Ghairi" "Washa" - "Uhamishaji faili" "Ungependa kupokea faili inayoingia?" "Kataa" "Kubali" @@ -42,10 +41,8 @@ "Faili kutoka %1$s iko tayari kutumwa: %2$s" "Kushiriki kwa bluetooth: Inapokea %1$s" "Kushiriki kwa bluetooth: Imepokea %1$s" - "Kushiriki kwa Bluetooth: Faili %1$s haijapokewa" "Kushiriki kwa bluetooth: Inatuma %1$s" "Kushiriki kwa bluetooth: Imetuma %1$s" - "Imekamilika 100%" "Kushiriki kwa bluetooth: Faili %1$s haijatumwa" "Uhamishaji faili" "Kutoka: \"%1$s\"" @@ -80,7 +77,6 @@ "Tafadhali subiri…" "Inawasha Bluetooth..." "Faili itapokelewa. Kagua maendeleo katika paneli ya Arifa." - "Faili haiwezi kupokewa." "Ilikomesha upokeaji wa faili kutoka \"%1$s\"" "Inatuma faili kwa \"%1$s\"" "Inatuma faili %1$s kwa \"%2$s\"" @@ -118,7 +114,6 @@ "Futa" "Inayocheza Sasa" "Aikoni ya programu" - "Imeunganisha sauti ya Bluetooth" "Imeondoa sauti ya Bluetooth" "Sauti ya Bluetooth" "Haiwezi kutuma faili zinazozidi GB 4" diff --git a/android/app/res/values-sw/test_strings.xml b/android/app/res/values-sw/test_strings.xml deleted file mode 100644 index 2d1a95e0d83..00000000000 --- a/android/app/res/values-sw/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Ingiza rekodi" - "Thibitisha rekodi" - "Rekodi ya Ack" - "Futa rekodi zote" - "Sawa" - "Futa rekodi" - "Anzisha seva ya TCP" - "Arifu seva ya TCP" - diff --git a/android/app/res/values-ta/strings.xml b/android/app/res/values-ta/strings.xml index a909ce2ee03..86a84e024f5 100644 --- a/android/app/res/values-ta/strings.xml +++ b/android/app/res/values-ta/strings.xml @@ -32,7 +32,6 @@ "இப்போது புளூடூத்தை இயக்கவா?" "ரத்துசெய்" "இயக்கு" - "ஃபைல் பரிமாற்றம்" "உள்வரும் ஃபைலை ஏற்கவா?" "நிராகரி" "ஏற்கிறேன்" @@ -42,10 +41,8 @@ "%2$s ஃபைலை அனுப்ப %1$s தயாராக உள்ளார்" "புளூடூத் பகிர்வு: %1$s ஐப் பெறுகிறது" "புளூடூத் பகிர்வு: %1$s பெறப்பட்டது" - "புளூடூத் பகிர்வு: %1$s ஐப் பெறவில்லை" "புளூடூத் பகிர்வு: %1$s ஐ அனுப்புகிறது" "புளூடூத் பகிர்வு: %1$s அனுப்பப்பட்டது" - "100% முடிந்தது" "புளூடூத் பகிர்வு: %1$s ஃபைல் அனுப்பப்படவில்லை" "ஃபைல் பரிமாற்றம்" "அனுப்புநர்: \"%1$s\"" @@ -80,7 +77,6 @@ "காத்திருக்கவும்…" "புளூடூத்தை இயக்குகிறது…" "ஃபைல் பெறப்படும். அறிவிப்புகள் பலகத்தில் செயல்நிலையைப் பார்க்கவும்." - "ஃபைல் பெறப்படவில்லை." "\"%1$s\" இடமிருந்து ஃபைல் பெறுவது நிறுத்தப்பட்டது" "\"%1$s\" க்கு ஃபைல் அனுப்பப்படுகிறது" "%1$s ஃபைல்கள் \"%2$s\" க்கு அனுப்பப்படுகின்றன" @@ -118,7 +114,6 @@ "அழி" "பாடல் விவரம்" "ஆப்ஸ் ஐகான்" - "புளூடூத் ஆடியோ இணைக்கப்பட்டது" "புளூடூத் ஆடியோ துண்டிக்கப்பட்டது" "புளூடூத் ஆடியோ" "4ஜி.பை.க்கு மேலிருக்கும் ஃபைல்களை இடமாற்ற முடியாது" diff --git a/android/app/res/values-ta/test_strings.xml b/android/app/res/values-ta/test_strings.xml deleted file mode 100644 index bb6b0cd2605..00000000000 --- a/android/app/res/values-ta/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "புளூடூத்" - "பதிவைச் செருகு" - "பதிவை உறுதிப்படுத்து" - "ஒப்புதல் பதிவு" - "எல்லா பதிவையும் நீக்கு" - "சரி" - "பதிவை நீக்கு" - "TCP சேவையகத்தைத் தொடங்கு" - "TCP சேவையகத்தைத் தெரிவி" - diff --git a/android/app/res/values-te/strings.xml b/android/app/res/values-te/strings.xml index 6d80268cfe3..bb4224812bb 100644 --- a/android/app/res/values-te/strings.xml +++ b/android/app/res/values-te/strings.xml @@ -32,7 +32,6 @@ "ఇప్పుడే బ్లూటూత్‌ను ప్రారంభించాలా?" "రద్దు చేయండి" "ప్రారంభించండి" - "ఫైల్ బదిలీ" "ఇన్‌కమింగ్ ఫైల్‌ను ఆమోదించాలా?" "తిరస్కరిస్తున్నాను" "అంగీకరిస్తున్నాను" @@ -42,10 +41,8 @@ "%1$s ఫైల్‌ను పంపడానికి సిద్ధంగా ఉన్నారు: %2$s" "బ్లూటూత్ షేర్: %1$sను స్వీకరిస్తోంది" "బ్లూటూత్ షేర్: %1$s స్వీకరించబడింది" - "బ్లూటూత్ షేర్: %1$s ఫైల్ స్వీకరించబడలేదు" "బ్లూటూత్ షేర్: %1$sను పంపుతోంది" "బ్లూటూత్ షేర్: %1$s పంపబడింది" - "100% పూర్తయింది" "బ్లూటూత్ షేర్: %1$s ఫైల్ పంపబడలేదు" "ఫైల్ బదిలీ" "వీరి నుండి: \"%1$s\"" @@ -80,7 +77,6 @@ "దయచేసి వేచి ఉండండి..." "బ్లూటూత్‌ను ప్రారంభిస్తోంది…" "ఫైల్ స్వీకరించబడుతుంది. నోటిఫికేషన్‌ల ప్యానెల్‌లో ప్రోగ్రెస్‌ను చెక్ చేయండి." - "ఫైల్ స్వీకరించబడలేదు." "\"%1$s\" పంపిన ఫైల్‌ను స్వీకరించడం ఆపివేయబడింది" "ఫైల్‌ను \"%1$s\"కి పంపుతోంది" "%1$s ఫైళ్లను \"%2$s\"కి పంపుతోంది" @@ -118,7 +114,6 @@ "క్లియర్ చేయండి" "ప్రస్తుతం ప్లే అవుతున్నవి" "యాప్‌ చిహ్నం" - "బ్లూటూత్ ఆడియో కనెక్ట్ చేయబడింది" "బ్లూటూత్ ఆడియో డిస్‌కనెక్ట్ చేయబడింది" "బ్లూటూత్ ఆడియో" "4GB కన్నా పెద్ద ఫైళ్లు బదిలీ చేయబడవు" diff --git a/android/app/res/values-te/test_strings.xml b/android/app/res/values-te/test_strings.xml deleted file mode 100644 index 33a03f286c0..00000000000 --- a/android/app/res/values-te/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "బ్లూటూత్" - "రికార్డ్‌ను చొప్పించండి" - "రికార్డ్‌ను నిర్ధారించండి" - "సమ్మతి ధృవీకరణ రికార్డ్" - "మొత్తం రికార్డ్‌ను తొలగించండి" - "సరే" - "రికార్డ్‌ను తొలగించండి" - "TCP సర్వర్‌ను ప్రారంభించండి" - "TCP సర్వర్‌కు తెలియజేయండి" - diff --git a/android/app/res/values-th/strings.xml b/android/app/res/values-th/strings.xml index 498e093660b..59638e383b2 100644 --- a/android/app/res/values-th/strings.xml +++ b/android/app/res/values-th/strings.xml @@ -32,7 +32,6 @@ "ต้องการเปิดบลูทูธเดี๋ยวนี้หรือไม่" "ยกเลิก" "เปิด" - "การถ่ายโอนไฟล์" "ยอมรับไฟล์ที่เข้ามาใหม่ไหม" "ปฏิเสธ" "ยอมรับ" @@ -42,10 +41,8 @@ "%1$s พร้อมที่จะส่งไฟล์: %2$s" "การแชร์ทางบลูทูธ: กำลังรับ %1$s" "การแชร์ทางบลูทูธ: รับ %1$s แล้ว" - "การแชร์ทางบลูทูธ: ไม่ได้รับไฟล์ %1$s" "การแชร์ทางบลูทูธ: กำลังส่ง %1$s" "การแชร์ทางบลูทูธ: ส่ง %1$s แล้ว" - "เสร็จสมบูรณ์ 100%" "การแชร์ทางบลูทูธ: ไฟล์ %1$s ไม่ถูกส่ง" "การถ่ายโอนไฟล์" "จาก: \"%1$s\"" @@ -80,7 +77,6 @@ "โปรดรอสักครู่..." "กำลังเปิดบลูทูธ…" "ไฟล์จะถูกรับ ดูความคืบหน้าในแผงการแจ้งเตือน" - "ไม่สามารถรับไฟล์" "หยุดรับไฟล์จาก \"%1$s\"" "กำลังส่งไฟล์ถึง \"%1$s\"" "กำลังส่ง %1$s ไฟล์ถึง \"%2$s\"" @@ -118,7 +114,6 @@ "ล้าง" "กำลังเล่น" "ไอคอนแอปพลิเคชัน" - "เชื่อมต่อ Bluetooth Audio แล้ว" "ยกเลิกการเชื่อมต่อ Bluetooth Audio แล้ว" "Bluetooth Audio" "โอนไฟล์ที่มีขนาดใหญ่กว่า 4 GB ไม่ได้" diff --git a/android/app/res/values-th/test_strings.xml b/android/app/res/values-th/test_strings.xml deleted file mode 100644 index 05b2a5c0c29..00000000000 --- a/android/app/res/values-th/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "บลูทูธ" - "แทรกบันทึก" - "ยืนยันบันทึก" - "บันทึก Ack" - "ลบบันทึกทั้งหมด" - "ตกลง" - "ลบบันทึก" - "เริ่มต้นเซิร์ฟเวอร์ TCP" - "แจ้งเตือนเซิร์ฟเวอร์ TCP" - diff --git a/android/app/res/values-tl/strings.xml b/android/app/res/values-tl/strings.xml index e516b4583ec..7596fb9298c 100644 --- a/android/app/res/values-tl/strings.xml +++ b/android/app/res/values-tl/strings.xml @@ -32,7 +32,6 @@ "I-on ang Bluetooth ngayon?" "Kanselahin" "I-on" - "Paglilipat ng file" "Tanggapin ang papasok na file?" "Tanggihan" "Tanggapin" @@ -42,10 +41,8 @@ "Handa nang magpadala ng file si %1$s: %2$s" "Pagbahagi sa Bluetooth: Tinatanggap ang %1$s" "Pagbahagi sa Bluetooth: Natanggap ang %1$s" - "Pagbahagi sa Bluetooth: Hindi natanggap ang file na %1$s" "Pagbabahagi sa Bluetooth: Ipinapadala ang %1$s" "Pagbahagi sa Bluetooth: Ipinadala ang %1$s" - "100% kumpleto" "Pagbahagi sa Bluetooth: Hindi naipadala ang file na %1$s" "Paglilipat ng file" "Mula: \"%1$s\"" @@ -80,7 +77,6 @@ "Pakihintay…" "Ino-on ang Bluetooth…" "Matatanggap ang file. Suriin ang pagsulong sa panel na Mga Notification." - "Hindi matanggap ang file." "Ihininto ang pagtanggap ng file mula kay \"%1$s\"" "Nagpapadala ng file kay \"%1$s\"" "Ipinapadala ang %1$s (na) file kay \"%2$s\"" @@ -118,7 +114,6 @@ "I-clear" "Nagpi-play Ngayon" "Icon ng Application" - "Nakakonekta ang Bluetooth audio" "Nadiskonekta ang Bluetooth audio" "Bluetooth Audio" "Hindi maililipat ang mga file na mas malaki sa 4GB" diff --git a/android/app/res/values-tl/test_strings.xml b/android/app/res/values-tl/test_strings.xml deleted file mode 100644 index 6e94ab7bc51..00000000000 --- a/android/app/res/values-tl/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Ipasok ang tala" - "Kumpirmahin ang tala" - "Ack na tala" - "I-delete ang lahat ng tala" - "OK" - "I-delete ang tala" - "Simulan ang TCP server" - "I-notify ang TCP server" - diff --git a/android/app/res/values-tr/strings.xml b/android/app/res/values-tr/strings.xml index 5f8adc10a88..7b2a5c4f6e8 100644 --- a/android/app/res/values-tr/strings.xml +++ b/android/app/res/values-tr/strings.xml @@ -32,7 +32,6 @@ "Bluetooth\'u şimdi açmak istiyor musunuz?" "İptal" "Aç" - "Dosya aktarımı" "Gelen dosya kabul edilsin mi?" "Reddet" "Kabul Et" @@ -42,10 +41,8 @@ "%1$s, dosya göndermeye hazır: %2$s" "Bluetooth paylaşımı: %1$s alınıyor" "Bluetooth paylaşımı: %1$s alındı" - "Bluetooth paylaşımı: %1$s dosyası alınamadı" "Bluetooth paylaşımı: %1$s gönderiliyor" "Bluetooth paylaşımı: %1$s gönderildi" - "%100 tamamlandı" "Bluetooth paylaşımı: %1$s dosyası gönderilmedi" "Dosya aktarımı" "Gönderen: \"%1$s\"" @@ -80,7 +77,6 @@ "Lütfen bekleyin..." "Bluetooth açılıyor..." "Dosya alınacak. İlerlemeyi Bildirimler panelinden izleyebilirsiniz." - "Dosya alınamıyor." "\"%1$s\" kaynağından dosya alımı durduruldu" "Dosya \"%1$s\" hedefine gönderiliyor" "%1$s dosya \"%2$s\" hedefine gönderiliyor" @@ -118,7 +114,6 @@ "Temizle" "Ne Çalıyor?" "Uygulama Simgesi" - "Bluetooth ses bağlandı" "Bluetooth ses bağlantısı kesildi" "Bluetooth Ses" "4 GB\'tan büyük dosyalar aktarılamaz" diff --git a/android/app/res/values-tr/test_strings.xml b/android/app/res/values-tr/test_strings.xml deleted file mode 100644 index 2e1af59173f..00000000000 --- a/android/app/res/values-tr/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Kayıt ekle" - "Kaydı onayla" - "Onay kaydı" - "Tüm kayıtları silin" - "Tamam" - "Kaydı sil" - "TCP sunucusunu başlat" - "TCP sunucusuna bildir" - diff --git a/android/app/res/values-uk/strings.xml b/android/app/res/values-uk/strings.xml index a76fc67cafa..067e53955a3 100644 --- a/android/app/res/values-uk/strings.xml +++ b/android/app/res/values-uk/strings.xml @@ -32,7 +32,6 @@ "Увімк. Bluetooth зараз?" "Скасувати" "Увімкнути" - "Пересилка файлу" "Прийняти вхідний файл?" "Відхилити" "Прийняти" @@ -42,10 +41,8 @@ "Пристрій %1$s готовий надіслати файл: %2$s" "Через Bluetooth: отримання %1$s" "Через Bluetooth: отримано %1$s" - "Через Bluetooth: файл %1$s не отримано" "Через Bluetooth: надсилання %1$s" "Через Bluetooth: надісл. %1$s" - "100% виконано" "Через Bluetooth: файл %1$s не надісл." "Передача файлів" "Від: \"%1$s\"" @@ -80,7 +77,6 @@ "Зачекайте…" "Увімкнення Bluetooth..." "Файл буде отримано. Перевіряйте прогрес на панелі сповіщень." - "Неможливо отримати файл." "Зупинено отримання файлу від \"%1$s\"" "Надсил-ня файлу до \"%1$s\"" "Надсил-ня файлів (%1$s) до \"%2$s\"" @@ -118,7 +114,6 @@ "Очистити" "Зараз грає" "Значок додатка" - "Аудіо Bluetooth під’єднано" "Аудіо Bluetooth від’єднано" "Bluetooth Audio" "Не можна перенести файли, більші за 4 ГБ" diff --git a/android/app/res/values-uk/test_strings.xml b/android/app/res/values-uk/test_strings.xml deleted file mode 100644 index c7d65f41a7f..00000000000 --- a/android/app/res/values-uk/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Вставити запис" - "Підтвердити запис" - "Запис TCP" - "Видалити всі записи" - "OK" - "Видалити запис" - "Запустити TCP сервер" - "Повідом. TCP сервер" - diff --git a/android/app/res/values-ur/strings.xml b/android/app/res/values-ur/strings.xml index 83556b8c1c6..381e201dabb 100644 --- a/android/app/res/values-ur/strings.xml +++ b/android/app/res/values-ur/strings.xml @@ -32,7 +32,6 @@ "بلوٹوتھ کو ابھی آن کریں؟" "منسوخ کریں" "آن کریں" - "فائل کی منتقلی" "اِن کمنگ فائل قبول کریں؟" "مسترد کریں" "قبول کریں" @@ -42,10 +41,8 @@ "%1$s فائل بھیجنے کیلئے تیار ہے: %2$s" "بلوٹوتھ اشتراک: %1$s موصول ہو رہی ہے" "بلوٹوتھ اشتراک: %1$s موصول ہوئی" - "بلوٹوتھ اشتراک: فائل %1$s موصول نہیں ہوئی" "بلوٹوتھ اشتراک: %1$s بھیجی جا رہی ہے" "بلوٹوتھ اشتراک: %1$s بھیج دی گئی" - "100% مکمل" "بلوٹوتھ اشتراک: %1$s نہیں بھیجی گئی" "فائل کی منتقلی" "منجانب: \"%1$s\"" @@ -80,7 +77,6 @@ "براہ کرم انتظار کریں…" "بلوٹوتھ آن ہو رہا ہے…" "فائل موصول ہوگی۔ اطلاعاتی پینل میں پیشرفت چیک کریں۔" - "فائل موصول نہیں ہو سکتی۔" "\"%1$s\" کی جانب سے فائل موصول ہونا بند ہو گئی" "\"%1$s\" کو فائل بھیجی جا رہی ہے" "%1$s فائلیں \"%2$s\" کو بھیجی جا رہی ہیں" @@ -118,7 +114,6 @@ "صاف کریں" "Now Playing" "ایپلیکیشن کا آئیکن" - "بلوٹوتھ آڈیو منسلک ہے" "بلوٹوتھ آڈیو غیر منسلک ہے" "بلوٹوتھ آڈیو" "‏4GB سے بڑی فائلیں منتقل نہیں کی جا سکتیں" diff --git a/android/app/res/values-ur/test_strings.xml b/android/app/res/values-ur/test_strings.xml deleted file mode 100644 index 34d374de850..00000000000 --- a/android/app/res/values-ur/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "بلوٹوتھ" - "ریکارڈ داخل کریں" - "ریکارڈ کی توثیق کریں" - "‏Ack ریکارڈ" - "سبھی ریکارڈ حذف کریں" - "ٹھیک ہے" - "ریکارڈ حذف کریں" - "‏TCP سرور شروع کریں" - "‏TCP سرور کی اطلاع دیں" - diff --git a/android/app/res/values-uz/strings.xml b/android/app/res/values-uz/strings.xml index df549b988ef..a39c0c471f3 100644 --- a/android/app/res/values-uz/strings.xml +++ b/android/app/res/values-uz/strings.xml @@ -32,7 +32,6 @@ "Bluetooth hozir yoqilsinmi?" "Bekor qilish" "Yoqish" - "Fayl uzatish" "Fayl qabul qilinsinmi?" "Rad etish" "Qabul qilish" @@ -42,10 +41,8 @@ "%1$s fayl yuborishga tayyor: %2$s" "Bluetooth orqali yuborildi: %1$s" "Bluetooth orqali olindi: %1$s" - "Fayl qabul qilinmadi: %1$s" "Bluetooth orqali yuborish: %1$s" "Bluetooth orqali yuborildi: %1$s" - "100% tugadi" "Fayl yuborilmadi: %1$s" "Fayl uzatish" "Yuboruvchi: \"%1$s\"" @@ -80,7 +77,6 @@ "Kutib turing…" "Bluetooth yoqilmoqda…" "Fayl qabul qilinadi. Jarayonni \"Xabarnomalar\" panelida kuzating." - "Faylni qabul qilib bo‘lmaydi." "\"%1$s\"dan fayl qabul qilish to‘xtatildi." "\"%1$s\"ga fayl jo‘natilmoqda" "%1$s ta fayl \"%2$s\"ga jo‘natimoqda" @@ -118,7 +114,6 @@ "Tozalash" "Bu qaysi musiqa" "Ilova ikonkasi" - "Bluetooth orqali ovoz yoqildi" "Bluetooth orqali ovoz o‘chirildi" "Bluetooth orqali ovoz" "4 GBdan katta hajmli videolar o‘tkazilmaydi" diff --git a/android/app/res/values-uz/test_strings.xml b/android/app/res/values-uz/test_strings.xml deleted file mode 100644 index 2e678dc30c4..00000000000 --- a/android/app/res/values-uz/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Yozuvni kiriting" - "Yozuvni tasdiqlash" - "Ack yozuvi" - "Barcha yozuvlarni o‘chirish" - "OK" - "Yozuvni o‘chirish" - "TCP serverni ishga tushirish" - "TCP serverga xabar berish" - diff --git a/android/app/res/values-vi/strings.xml b/android/app/res/values-vi/strings.xml index d6480b09a2f..2c30acb8f57 100644 --- a/android/app/res/values-vi/strings.xml +++ b/android/app/res/values-vi/strings.xml @@ -32,7 +32,6 @@ "Bật Bluetooth ngay bây giờ?" "Hủy" "Bật" - "Chuyển tệp" "Chấp nhận tệp đến?" "Từ chối" "Chấp nhận" @@ -42,10 +41,8 @@ "%1$s đã sẵn sàng gửi một tệp: %2$s" "Chia sẻ qua Bluetooth: Đang nhận %1$s" "Chia sẻ qua Bluetooth: Đã nhận %1$s" - "Chia sẻ qua Bluetooth: Chưa nhận được tệp %1$s" "Chia sẻ qua Bluetooth: Đang gửi %1$s" "Chia sẻ qua Bluetooth: Đã gửi %1$s" - "Hoàn tất 100%" "Chia sẻ qua Bluetooth: Chưa gửi được tệp %1$s" "Chuyển tệp" "Từ: \"%1$s\"" @@ -80,7 +77,6 @@ "Vui lòng đợi..." "Đang bật Bluetooth…" "Tệp sẽ được nhận. Hãy kiểm tra tiến trình trong bảng điều khiển Thông báo." - "Không thể nhận được tệp." "Đã dừng nhận tệp từ \"%1$s\"" "Đang gửi tệp tới \"%1$s\"" "Đang gửi %1$s tệp tới \"%2$s\"" @@ -118,7 +114,6 @@ "Xóa" "Phát hiện nhạc" "Biểu tượng ứng dụng" - "Đã kết nối âm thanh Bluetooth" "Đã ngắt kết nối âm thanh Bluetooth" "Âm thanh Bluetooth" "Không thể chuyển những tệp lớn hơn 4 GB" diff --git a/android/app/res/values-vi/test_strings.xml b/android/app/res/values-vi/test_strings.xml deleted file mode 100644 index ef0775495d3..00000000000 --- a/android/app/res/values-vi/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "Bluetooth" - "Chèn bản ghi" - "Xác nhận bản ghi" - "Bản ghi Ack" - "Xóa tất cả bản ghi" - "OK" - "Xóa bản ghi" - "Khởi động máy chủ TCP" - "Thông báo cho máy chủ TCP" - diff --git a/android/app/res/values-zh-rCN/strings.xml b/android/app/res/values-zh-rCN/strings.xml index 8da5f36cdff..68a1883ef71 100644 --- a/android/app/res/values-zh-rCN/strings.xml +++ b/android/app/res/values-zh-rCN/strings.xml @@ -32,7 +32,6 @@ "要现在开启蓝牙吗?" "取消" "开启" - "文件传输" "要接受传入的文件吗?" "拒绝" "接受" @@ -42,10 +41,8 @@ "“%1$s”准备发送以下文件:%2$s" "蓝牙共享:正在接收“%1$s”" "蓝牙共享:已接收“%1$s”" - "蓝牙共享:未收到文件“%1$s”" "蓝牙共享:正在发送“%1$s”" "蓝牙共享:已发送“%1$s”" - "已完成100%" "蓝牙共享:未发送文件“%1$s”" "文件传输" "来自:“%1$s”" @@ -80,7 +77,6 @@ "请稍候..." "正在打开蓝牙..." "系统将会接收该文件。请在通知面板中检查进度。" - "无法接收该文件。" "已停止接收来自“%1$s”的文件" "正在向“%1$s”发送文件" "正在向“%2$s”发送%1$s个文件" @@ -118,7 +114,6 @@ "清除" "闻曲知音" "应用图标" - "蓝牙音频已连接" "蓝牙音频已断开连接" "蓝牙音频" "无法传输 4GB 以上的文件" diff --git a/android/app/res/values-zh-rCN/test_strings.xml b/android/app/res/values-zh-rCN/test_strings.xml deleted file mode 100644 index c1db232fd8a..00000000000 --- a/android/app/res/values-zh-rCN/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "蓝牙" - "插入记录" - "确认记录" - "Ack记录" - "删除所有记录" - "确定" - "删除记录" - "启动TCP服务器" - "通知TCP服务器" - diff --git a/android/app/res/values-zh-rHK/strings.xml b/android/app/res/values-zh-rHK/strings.xml index 761975c041c..4c9adac4fd1 100644 --- a/android/app/res/values-zh-rHK/strings.xml +++ b/android/app/res/values-zh-rHK/strings.xml @@ -32,7 +32,6 @@ "立即開啟藍牙功能?" "取消" "開啟" - "檔案傳輸" "接受傳來的檔案?" "拒絕" "接受" @@ -42,10 +41,8 @@ "%1$s 準備傳送檔案:%2$s" "藍牙分享:正在接收 %1$s" "藍牙分享:已接收 %1$s" - "藍牙分享:未收到檔案 %1$s" "藍牙分享:正在傳送 %1$s" "藍牙分享:已傳送 %1$s" - "傳送完成" "藍牙分享:未傳送檔案 %1$s" "檔案傳輸" "寄件者:「%1$s」" @@ -80,7 +77,6 @@ "請稍候…" "正在開啟藍牙..." "即將接收檔案,請在通知面板中查看進度。" - "無法接收檔案。" "已停止接收來自「%1$s」的檔案" "正在將檔案傳送給「%1$s」" "正在將 %1$s 個檔案傳送給「%2$s」" @@ -118,7 +114,6 @@ "清除" "歌曲識別" "應用程式圖示" - "已與藍牙音訊連接" "已與藍牙音訊解除連接" "藍牙音訊" "無法轉移 4 GB 以上的檔案" diff --git a/android/app/res/values-zh-rHK/test_strings.xml b/android/app/res/values-zh-rHK/test_strings.xml deleted file mode 100644 index 74a2d5302f2..00000000000 --- a/android/app/res/values-zh-rHK/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "藍牙" - "插入記錄" - "確認記錄" - "Ack 記錄" - "刪除所有記錄" - "確定" - "刪除記錄" - "啟動 TCP 伺服器" - "通知 TCP 伺服器" - diff --git a/android/app/res/values-zh-rTW/strings.xml b/android/app/res/values-zh-rTW/strings.xml index b1244bb8c9e..bdc8a7ef754 100644 --- a/android/app/res/values-zh-rTW/strings.xml +++ b/android/app/res/values-zh-rTW/strings.xml @@ -32,7 +32,6 @@ "立即開啟藍牙功能?" "取消" "開啟" - "檔案傳輸" "接受傳來的檔案?" "拒絕" "接受" @@ -42,10 +41,8 @@ "「%1$s」準備要傳送檔案:%2$s" "藍牙分享:正在接收 %1$s" "藍牙分享:已接收 %1$s" - "藍牙分享:未收到檔案 %1$s" "藍牙分享:正在傳送 %1$s" "藍牙分享:已傳送 %1$s" - "已傳送所有檔案" "藍牙分享:未傳送檔案 %1$s" "檔案傳輸" "寄件者:「%1$s」" @@ -80,7 +77,6 @@ "請稍候…" "正在開啟藍牙…" "即將接收檔案,請在通知面板中查看進度。" - "無法接收檔案。" "已停止接收來自「%1$s」的檔案" "正在將檔案傳送給「%1$s」" "正在將 %1$s 個檔案傳送給「%2$s」" @@ -118,7 +114,6 @@ "清除" "聽聲辨曲" "應用程式圖示" - "已與藍牙音訊連線" "已中斷與藍牙音訊的連線" "藍牙音訊" "無法轉移大於 4GB 的檔案" diff --git a/android/app/res/values-zh-rTW/test_strings.xml b/android/app/res/values-zh-rTW/test_strings.xml deleted file mode 100644 index 74a2d5302f2..00000000000 --- a/android/app/res/values-zh-rTW/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "藍牙" - "插入記錄" - "確認記錄" - "Ack 記錄" - "刪除所有記錄" - "確定" - "刪除記錄" - "啟動 TCP 伺服器" - "通知 TCP 伺服器" - diff --git a/android/app/res/values-zu/strings.xml b/android/app/res/values-zu/strings.xml index a52082b6ee7..23758fbe5c1 100644 --- a/android/app/res/values-zu/strings.xml +++ b/android/app/res/values-zu/strings.xml @@ -32,7 +32,6 @@ "Vula i-Bluetooth manje?" "Khansela" "Vula" - "Ukudlulisa ifayela" "Yamukela ifayela elingenayo?" "Nqaba" "Yamukela" @@ -42,10 +41,8 @@ "U-%1$s uselungele ukuthumela ifayela: %2$s" "Abelana ne-Bluetooth: Ithola%1$s" "Abelana ne-Bluetooth: Itholakele %1$s" - "Abelana ne-Bluetooth: Ifayela %1$s ayitholakalanga" "Abelana ne-Bluetooth: Ithumela %1$s" "Abelana ne-Bluetooth: Thunyelwe %1$s" - "Iqede ngo-100%" "Abelana ne-Bluetooth: Ifayela %1$s ayithunyelwanga" "Dlulisa ifayela" "Isuka ku: \"%1$s\"" @@ -80,7 +77,6 @@ "Sicela ulinde..." "Ivula i-Bluetooth..." "Ifayela izotholwa. Hlola intuthuki kwiphaneli Yezaziso." - "Ifayela alikwazi ukutholakala." "Imise ukuthola ifayela kusuka ku- \"%1$s\"" "Ithumela ifayela ku- \"%1$s\"" "Ithumela %1$s amafayela ku- \"%2$s\"" @@ -118,7 +114,6 @@ "Sula" "Okudlala manje" "Isithonjana sohlelo lokusebenza" - "Umsindo we-Bluetooth uxhunyiwe" "Umsindo we-Bluetooth unqanyuliwe" "Umsindo we-Bluetooth" "Amafayela amakhulu kuno-4GB awakwazi ukudluliselwa" diff --git a/android/app/res/values-zu/test_strings.xml b/android/app/res/values-zu/test_strings.xml deleted file mode 100644 index a100bd60f76..00000000000 --- a/android/app/res/values-zu/test_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - "I-Bluetooth" - "Faka irekhodi" - "Qinisekisa irekhodi" - "Irekhodi ye-Ack" - "Susa yonke irekhodi" - "KULUNGILE" - "Susa irekhodi" - "Qala iseva ye-TCP" - "Yazisa iseva ye-TCP" - diff --git a/android/app/tests/unit/res/values/test_strings.xml b/android/app/tests/unit/res/values/test_strings.xml index b35c933cfb7..656befdd887 100644 --- a/android/app/tests/unit/res/values/test_strings.xml +++ b/android/app/tests/unit/res/values/test_strings.xml @@ -1,11 +1,11 @@ - Insert record - Confirm record - Ack record - Delete all record - OK - Delete record - Start TCP server - Notify TCP server + Insert record + Confirm record + Ack record + Delete all record + OK + Delete record + Start TCP server + Notify TCP server -- GitLab From 8b65d260cded007b1193dfe23c2d9e41c105ba33 Mon Sep 17 00:00:00 2001 From: Evan Severson Date: Thu, 10 Oct 2024 15:10:28 -0700 Subject: [PATCH 263/875] Print the AttributionSource that permission was checked for This method creates a new attribution source that historically has been missing essential information such as packageName (this was a bug), the error message prints the original attribution source claiming that the original fails the permission check when the permission check was actually against the new one which was rightfully failing permission checks. Bug: 333931259 Test: m droid Flag: EXEMPT bugfix Change-Id: Ia5307dcae66d3559eddee0ff30ccb6a45849c074 --- android/app/src/com/android/bluetooth/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/com/android/bluetooth/Utils.java b/android/app/src/com/android/bluetooth/Utils.java index 32067e24fb8..8c55dd5a903 100644 --- a/android/app/src/com/android/bluetooth/Utils.java +++ b/android/app/src/com/android/bluetooth/Utils.java @@ -650,7 +650,7 @@ public final class Utils { } final String msg = - "Need " + permission + " permission for " + attributionSource + ": " + message; + "Need " + permission + " permission for " + currentAttribution + ": " + message; if (result == PERMISSION_HARD_DENIED) { throw new SecurityException(msg); } else { -- GitLab From 351dc1df5ad1f00a8fa9cd8d27a53a06a410e8d0 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 9 Oct 2024 18:09:37 -0700 Subject: [PATCH 264/875] btif_a2dp_source: Inline the call to btif_a2dp_setup_codec btif_a2dp_setup_codec is only called from btif_a2dp_start_session, and scheduules a task on the a2dp_source_worker thread to be run right before btif_a2dp_start_session_delayed As such the call can be safely inlined in btif_a2dp_start_session_delayed without chaning the behavior Bug: 365022887 Test: m com.android.btservices Test: manual streaming test Flag: EXEMPT, no logical change Change-Id: Iea312630471d456655e7372d954a2a014f609e4c --- system/btif/src/btif_a2dp_source.cc | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index b9004718dc1..4f216ef1bd0 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -246,7 +246,6 @@ static void btif_a2dp_source_audio_tx_flush_event(void); // The peer address is |peer_addr|. // This function should be called prior to starting A2DP streaming. static void btif_a2dp_source_setup_codec(const RawAddress& peer_addr); -static void btif_a2dp_source_setup_codec_delayed(const RawAddress& peer_address); static void btif_a2dp_source_cleanup_codec(); static void btif_a2dp_source_cleanup_codec_delayed(); static void btif_a2dp_source_encoder_user_config_update_event( @@ -424,7 +423,9 @@ static void btif_a2dp_source_startup_delayed() { bool btif_a2dp_source_start_session(const RawAddress& peer_address, std::promise peer_ready_promise) { log::info("peer_address={} state={}", peer_address, btif_a2dp_source_cb.StateStr()); - btif_a2dp_source_setup_codec(peer_address); + + btif_a2dp_source_audio_tx_flush_req(); + if (btif_a2dp_source_thread.DoInThread( FROM_HERE, base::BindOnce(&btif_a2dp_source_start_session_delayed, peer_address, std::move(peer_ready_promise)))) { @@ -440,11 +441,15 @@ bool btif_a2dp_source_start_session(const RawAddress& peer_address, static void btif_a2dp_source_start_session_delayed(const RawAddress& peer_address, std::promise peer_ready_promise) { log::info("peer_address={} state={}", peer_address, btif_a2dp_source_cb.StateStr()); + + btif_a2dp_source_setup_codec(peer_address); + if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateRunning) { log::error("A2DP Source media task is not running"); peer_ready_promise.set_value(); return; } + if (bluetooth::audio::a2dp::is_hal_enabled()) { bluetooth::audio::a2dp::start_session(); bluetooth::audio::a2dp::set_remote_delay(btif_av_get_audio_delay(A2dpType::kSource)); @@ -454,6 +459,7 @@ static void btif_a2dp_source_start_session_delayed(const RawAddress& peer_addres BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); } + peer_ready_promise.set_value(); } @@ -571,18 +577,6 @@ bool btif_a2dp_source_media_task_is_shutting_down(void) { // This runs on worker thread bool btif_a2dp_source_is_streaming(void) { return btif_a2dp_source_cb.media_alarm.IsScheduled(); } -static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) { - log::info("peer_address={} state={}", peer_address, btif_a2dp_source_cb.StateStr()); - - // Check to make sure the platform has 8 bits/byte since - // we're using that in frame size calculations now. - static_assert(CHAR_BIT == 8, "assert failed: CHAR_BIT == 8"); - - btif_a2dp_source_audio_tx_flush_req(); - btif_a2dp_source_thread.DoInThread( - FROM_HERE, base::BindOnce(&btif_a2dp_source_setup_codec_delayed, peer_address)); -} - /// Return the MTU for the active peer audio connection. static uint16_t btif_a2dp_get_peer_mtu(A2dpCodecConfig* a2dp_config) { uint8_t codec_info[AVDT_CODEC_SIZE]; @@ -618,7 +612,7 @@ static uint16_t btif_a2dp_get_peer_mtu(A2dpCodecConfig* a2dp_config) { return peer_mtu; } -static void btif_a2dp_source_setup_codec_delayed(const RawAddress& peer_address) { +static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) { log::info("peer_address={} state={}", peer_address, btif_a2dp_source_cb.StateStr()); tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; -- GitLab From 6a426fda1ffbb8c21147a69316f085fb1b0a4555 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 10 Oct 2024 18:02:33 -0700 Subject: [PATCH 265/875] GetNameAndAddress: run on proper thread Bug: 372775662 Bug: 371659191 Bug: 368114370 Flag: com.android.bluetooth.flags.get_name_and_address_as_callback Test: m Bluetooth Change-Id: Ibf5d5cc4ac08feb37013ffe10907ecd6a5145685 --- .../android/bluetooth/btservice/AdapterService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 4489bf6f89a..17ce026d796 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -1200,6 +1200,11 @@ public class AdapterService extends Service { } void updateAdapterName(String name) { + // TODO: b/372775662 - remove post once caller is on correct thread + mHandler.post(() -> updateAdapterNameInternal(name)); + } + + private void updateAdapterNameInternal(String name) { int n = mRemoteCallbacks.beginBroadcast(); Log.d(TAG, "updateAdapterName(" + name + ")"); for (int i = 0; i < n; i++) { @@ -1213,6 +1218,11 @@ public class AdapterService extends Service { } void updateAdapterAddress(String address) { + // TODO: b/372775662 - remove post once caller is on correct thread + mHandler.post(() -> updateAdapterAddressInternal(address)); + } + + private void updateAdapterAddressInternal(String address) { int n = mRemoteCallbacks.beginBroadcast(); Log.d(TAG, "updateAdapterAddress(" + BluetoothUtils.toAnonymizedAddress(address) + ")"); for (int i = 0; i < n; i++) { -- GitLab From f4d4928b100b45c9892b3cf76fcf13f9fe228cfa Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 11 Oct 2024 00:50:47 +0000 Subject: [PATCH 266/875] system/btif: Enforce -Wmissing-prototypes Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor refactor Change-Id: I045c588bf2ac499ba5065b4bca87444ec78552a9 --- system/btif/include/btif_rc.h | 9 ++-- system/btif/src/btif_rc.cc | 76 +++++++++++++++----------------- system/btif/test/btif_rc_test.cc | 1 + 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/system/btif/include/btif_rc.h b/system/btif/include/btif_rc.h index 94d365cc4dc..66ffef21a9d 100644 --- a/system/btif/include/btif_rc.h +++ b/system/btif/include/btif_rc.h @@ -14,14 +14,17 @@ * limitations under the License. */ -#ifndef BTIF_RC_H -#define BTIF_RC_H +#pragma once #include "bta_av_api.h" +#include "hardware/bt_rc.h" #include "types/raw_address.h" class RawAddress; +const btrc_interface_t* btif_rc_get_interface(void); +const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(void); + void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data); uint8_t btif_rc_get_connected_peer_handle(const RawAddress& peer_addr); void btif_rc_check_handle_pending_play(const RawAddress& peer_addr, bool bSendToApp); @@ -29,5 +32,3 @@ bool btif_rc_is_connected_peer(const RawAddress& peer_addr); void btif_rc_check_pending_cmd(const RawAddress& peer_addr); void btif_rc_get_addr_by_handle(uint8_t handle, RawAddress& rc_addr); void btif_debug_rc_dump(int fd); - -#endif // BTIF_RC_H diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index cf6ffe20bce..a059d5a05fa 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -108,9 +108,6 @@ } \ } while (0) -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -271,7 +268,7 @@ static const uint8_t status_code_map[] = { AVRC_STS_ADDR_PLAYER_CHG, /* BTRC_STS_ADDR_PLAY_CHGD */ }; -void initialize_device(btif_rc_device_cb_t* p_dev); +static void initialize_device(btif_rc_device_cb_t* p_dev); static void send_reject_response(uint8_t rc_handle, uint8_t label, uint8_t pdu, uint8_t status, uint8_t opcode); static uint8_t opcode_from_pdu(uint8_t pdu); @@ -330,9 +327,11 @@ static bt_status_t list_player_app_setting_attrib_cmd(btif_rc_device_cb_t* p_dev static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id, btif_rc_device_cb_t* p_dev); static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids, btif_rc_device_cb_t* p_dev); -void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item); -void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item); -void get_folder_item_type_player(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item); +static void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item); +static void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item, + btrc_folder_items_t* btrc_item); +static void get_folder_item_type_player(const tAVRC_ITEM* avrc_item, + btrc_folder_items_t* btrc_item); static bt_status_t get_folder_items_cmd(const RawAddress& bd_addr, uint8_t scope, uint32_t start_item, uint32_t end_item); @@ -404,7 +403,7 @@ static btif_rc_device_cb_t* alloc_device() { return NULL; } -void initialize_device(btif_rc_device_cb_t* p_dev) { +static void initialize_device(btif_rc_device_cb_t* p_dev) { if (p_dev == nullptr) { return; } @@ -455,7 +454,7 @@ static btif_rc_device_cb_t* get_connected_device(int index) { return &btif_rc_cb.rc_multi_cb[index]; } -btif_rc_device_cb_t* btif_rc_get_device_by_bda(const RawAddress& bd_addr) { +static btif_rc_device_cb_t* btif_rc_get_device_by_bda(const RawAddress& bd_addr) { log::verbose("bd_addr: {}", bd_addr); for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { @@ -468,7 +467,7 @@ btif_rc_device_cb_t* btif_rc_get_device_by_bda(const RawAddress& bd_addr) { return NULL; } -btif_rc_device_cb_t* btif_rc_get_device_by_handle(uint8_t handle) { +static btif_rc_device_cb_t* btif_rc_get_device_by_handle(uint8_t handle) { log::verbose("handle: 0x{:x}", handle); for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { if ((btif_rc_cb.rc_multi_cb[idx].rc_state != BTRC_CONNECTION_STATE_DISCONNECTED) && @@ -482,25 +481,25 @@ btif_rc_device_cb_t* btif_rc_get_device_by_handle(uint8_t handle) { return NULL; } -const uint32_t* get_requested_attributes_list(btif_rc_device_cb_t* p_dev) { +static const uint32_t* get_requested_attributes_list(btif_rc_device_cb_t* p_dev) { return p_dev->rc_features & BTA_AV_FEAT_COVER_ARTWORK ? media_attr_list : media_attr_list_no_cover_art; } -uint8_t get_requested_attributes_list_size(btif_rc_device_cb_t* p_dev) { +static uint8_t get_requested_attributes_list_size(btif_rc_device_cb_t* p_dev) { return p_dev->rc_features & BTA_AV_FEAT_COVER_ARTWORK ? media_attr_list_size : media_attr_list_no_cover_art_size; } -void fill_pdu_queue(int index, uint8_t ctype, uint8_t label, bool pending, - btif_rc_device_cb_t* p_dev) { +static void fill_pdu_queue(int index, uint8_t ctype, uint8_t label, bool pending, + btif_rc_device_cb_t* p_dev) { p_dev->rc_pdu_info[index].ctype = ctype; p_dev->rc_pdu_info[index].label = label; p_dev->rc_pdu_info[index].is_rsp_pending = pending; } -void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs, - btrc_element_attr_val_t* p_attrs) { +static void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs, + btrc_element_attr_val_t* p_attrs) { for (int attr_cnt = 0; attr_cnt < num_attrs; attr_cnt++) { attr_vals[attr_cnt].attr_id = p_attrs[attr_cnt].attr_id; attr_vals[attr_cnt].name.charset_id = AVRC_CHARSET_ID_UTF8; @@ -513,7 +512,7 @@ void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs, } } -void handle_rc_ctrl_features_all(btif_rc_device_cb_t* p_dev) { +static void handle_rc_ctrl_features_all(btif_rc_device_cb_t* p_dev) { if (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCTG) && (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCCT) || !(p_dev->peer_tg_features & BTA_AV_FEAT_ADV_CTRL))) { @@ -575,7 +574,7 @@ void handle_rc_ctrl_features_all(btif_rc_device_cb_t* p_dev) { } } -void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) { +static void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) { if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) { handle_rc_ctrl_features_all(p_dev); return; @@ -657,7 +656,7 @@ void btif_rc_check_pending_cmd(const RawAddress& peer_address) { p_dev->launch_cmd_pending = 0; } -void handle_rc_ctrl_psm(btif_rc_device_cb_t* p_dev) { +static void handle_rc_ctrl_psm(btif_rc_device_cb_t* p_dev) { uint16_t cover_art_psm = p_dev->rc_cover_art_psm; log::verbose("Update rc cover art psm to CTRL: {}", cover_art_psm); if (bt_rc_ctrl_callbacks != NULL) { @@ -666,7 +665,7 @@ void handle_rc_ctrl_psm(btif_rc_device_cb_t* p_dev) { } } -void handle_rc_features(btif_rc_device_cb_t* p_dev) { +static void handle_rc_features(btif_rc_device_cb_t* p_dev) { log::assert_that(bt_rc_callbacks != nullptr, "assert failed: bt_rc_callbacks != nullptr"); btrc_remote_features_t rc_features = BTRC_FEAT_NONE; @@ -719,7 +718,7 @@ void handle_rc_features(btif_rc_device_cb_t* p_dev) { * - Description: browse RC connection event handler * ***************************************************************************/ -void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) { +static void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) { log::verbose("rc_handle {} status {}", p_rc_br_open->rc_handle, p_rc_br_open->status); btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(p_rc_br_open->rc_handle); @@ -762,7 +761,7 @@ void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) { * - Description: RC connection event handler * ***************************************************************************/ -void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) { +static void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) { log::verbose("rc_handle: {}", p_rc_open->rc_handle); btif_rc_device_cb_t* p_dev = alloc_device(); @@ -841,7 +840,7 @@ void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) { * - Description: RC disconnection event handler * ***************************************************************************/ -void handle_rc_disconnect(tBTA_AV_RC_CLOSE* p_rc_close) { +static void handle_rc_disconnect(tBTA_AV_RC_CLOSE* p_rc_close) { btif_rc_device_cb_t* p_dev = NULL; log::verbose("rc_handle: {}", p_rc_close->rc_handle); @@ -877,7 +876,7 @@ void handle_rc_disconnect(tBTA_AV_RC_CLOSE* p_rc_close) { * - Description: Remote control command handler * ***************************************************************************/ -void handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD* p_remote_cmd) { +static void handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD* p_remote_cmd) { if (p_remote_cmd == NULL) { log::error("No remote command!"); return; @@ -929,7 +928,7 @@ void handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD* p_remote_cmd) { * - Description: Remote control passthrough response handler * ***************************************************************************/ -void handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { +static void handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { btif_rc_device_cb_t* p_dev = NULL; p_dev = btif_rc_get_device_by_handle(p_remote_rsp->rc_handle); @@ -961,7 +960,7 @@ void handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { * - Description: Remote control vendor unique response handler * ***************************************************************************/ -void handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { +static void handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { btif_rc_device_cb_t* p_dev = NULL; const char* status; uint8_t vendor_id = 0; @@ -1007,7 +1006,7 @@ void handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) { * - Description: Remote control metamsg command handler (AVRCP 1.3) * ***************************************************************************/ -void handle_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) { +static void handle_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) { /* Parse the metamsg command and pass it on to BTL-IFS */ uint8_t scratch_buf[512] = {0}; tAVRC_COMMAND avrc_command = {0}; @@ -2793,7 +2792,7 @@ static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg, btif_rc_device_cb * Returns true to continue iterating, false to stop * **************************************************************************/ -bool iterate_supported_event_list_for_interim_rsp(void* data, void* cb_data) { +static bool iterate_supported_event_list_for_interim_rsp(void* data, void* cb_data) { uint8_t* p_event_id; btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data; @@ -3034,7 +3033,7 @@ static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg, tAVRC_GE } } -bool rc_is_track_id_valid(tAVRC_UID uid) { +static bool rc_is_track_id_valid(tAVRC_UID uid) { tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0) { @@ -3840,7 +3839,8 @@ static void cleanup_btrc_folder_items(btrc_folder_items_t* btrc_items, uint8_t i * Returns None * **************************************************************************/ -void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item) { +static void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, + btrc_folder_items_t* btrc_item) { btrc_item->item_type = BTRC_ITEM_MEDIA; const tAVRC_ITEM_MEDIA* avrc_item_media = &(avrc_item->u.media); btrc_item_media_t* btrc_item_media = &(btrc_item->media); @@ -3918,7 +3918,8 @@ void get_folder_item_type_media(const tAVRC_ITEM* avrc_item, btrc_folder_items_t * Returns None * **************************************************************************/ -void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item) { +static void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item, + btrc_folder_items_t* btrc_item) { btrc_item->item_type = BTRC_ITEM_FOLDER; const tAVRC_ITEM_FOLDER* avrc_item_folder = &(avrc_item->u.folder); btrc_item_folder_t* btrc_item_folder = &(btrc_item->folder); @@ -3973,7 +3974,8 @@ void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item, btrc_folder_items_ * Returns None * **************************************************************************/ -void get_folder_item_type_player(const tAVRC_ITEM* avrc_item, btrc_folder_items_t* btrc_item) { +static void get_folder_item_type_player(const tAVRC_ITEM* avrc_item, + btrc_folder_items_t* btrc_item) { btrc_item->item_type = BTRC_ITEM_PLAYER; const tAVRC_ITEM_PLAYER* avrc_item_player = &(avrc_item->u.player); btrc_item_player_t* btrc_item_player = &(btrc_item->player); @@ -5058,10 +5060,7 @@ static const btrc_ctrl_interface_t bt_rc_ctrl_interface = { * Returns btrc_interface_t * ******************************************************************************/ -const btrc_interface_t* btif_rc_get_interface(void) { - log::verbose(""); - return &bt_rc_interface; -} +const btrc_interface_t* btif_rc_get_interface(void) { return &bt_rc_interface; } /******************************************************************************* * @@ -5072,10 +5071,7 @@ const btrc_interface_t* btif_rc_get_interface(void) { * Returns btrc_ctrl_interface_t * ******************************************************************************/ -const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(void) { - log::verbose(""); - return &bt_rc_ctrl_interface; -} +const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(void) { return &bt_rc_ctrl_interface; } /******************************************************************************* * Function initialize_transaction diff --git a/system/btif/test/btif_rc_test.cc b/system/btif/test/btif_rc_test.cc index 0de07934294..1c2405747fc 100644 --- a/system/btif/test/btif_rc_test.cc +++ b/system/btif/test/btif_rc_test.cc @@ -29,6 +29,7 @@ #include "common/message_loop_thread.h" #include "device/include/interop.h" #include "include/hardware/bt_rc.h" +#include "stack/include/main_thread.h" #include "test/common/mock_functions.h" #include "test/mock/mock_osi_alarm.h" #include "test/mock/mock_osi_allocator.h" -- GitLab From ebac27c66c67ec6ef4d393813fe3c2763cd97dcc Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Fri, 11 Oct 2024 05:02:46 +0000 Subject: [PATCH 267/875] Fix typo in A2dpService.java Bug: 372328032 Change-Id: Ia4aae11db3d2ffba4c3f83e293d703261302f93f Flag: exempt, logging change Test: m p/m/B --- android/app/src/com/android/bluetooth/a2dp/A2dpService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java index 45d667e37e0..d370baaeec7 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java @@ -1055,7 +1055,7 @@ public class A2dpService extends ProfileService { } } - /* Notifications of audio device connection/disconn events. */ + /* Notifications of audio device connection/disconnection events. */ private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { @Override public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { -- GitLab From bb17446bfcbdcd7cd718a8c11cd02b1c0b943682 Mon Sep 17 00:00:00 2001 From: Omair Kamil Date: Wed, 9 Oct 2024 20:38:49 -0700 Subject: [PATCH 268/875] Include attribution tag if available in dumpsys for LE clients. Bug: 372576833 Fix: 372576833 Test: atest BluetoothInstrumentationTests Flag: EXEMPT, dumpsys change only Change-Id: I43329cf14da63fd1ea56b3d2c768f599e098e088 --- .../bluetooth/gatt/AdvertiseManager.java | 6 ++- .../android/bluetooth/gatt/AdvertiserMap.java | 5 ++- .../bluetooth/gatt/AppAdvertiseStats.java | 18 ++++++-- .../android/bluetooth/gatt/ContextMap.java | 14 ++++-- .../android/bluetooth/gatt/GattService.java | 25 ++++++++--- .../bluetooth/le_audio/LeAudioService.java | 4 +- .../bluetooth/le_scan/AppScanStats.java | 25 ++++++----- .../android/bluetooth/le_scan/ScanClient.java | 4 +- .../android/bluetooth/le_scan/ScannerMap.java | 44 ++++++++++++++----- .../le_scan/TransitionalScanHelper.java | 12 ++--- .../bluetooth/util/AttributionSourceUtil.java | 39 ++++++++++++++++ .../bluetooth/gatt/AdvertiseManagerTest.java | 4 +- .../bluetooth/gatt/AdvertiserMapTest.java | 17 ++++--- .../bluetooth/gatt/AppAdvertiseStatsTest.java | 35 ++++++++++----- .../bluetooth/gatt/ContextMapTest.java | 15 ++++++- .../bluetooth/gatt/GattServiceTest.java | 2 +- .../bluetooth/le_scan/ScannerMapTest.java | 17 +++++-- .../le_scan/TransitionalScanHelperTest.java | 9 +++- 18 files changed, 226 insertions(+), 69 deletions(-) create mode 100644 android/app/src/com/android/bluetooth/util/AttributionSourceUtil.java diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java index 7ca12908c39..f3ccb8a9c17 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java @@ -21,6 +21,7 @@ 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 android.os.Binder; import android.os.Handler; import android.os.HandlerThread; @@ -246,7 +247,8 @@ public class AdvertiseManager { int duration, int maxExtAdvEvents, int serverIf, - IAdvertisingSetCallback callback) { + IAdvertisingSetCallback callback, + AttributionSource attrSource) { // If we are using an isolated server, force usage of an NRPA if (serverIf != 0 && parameters.getOwnAddressType() @@ -294,7 +296,7 @@ public class AdvertiseManager { Log.d(TAG, "startAdvertisingSet() - reg_id=" + cbId + ", callback: " + binder); - mAdvertiserMap.addAppAdvertiseStats(cbId, mService); + mAdvertiserMap.addAppAdvertiseStats(cbId, mService, attrSource); mAdvertiserMap.recordAdvertiseStart( cbId, parameters, diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiserMap.java b/android/app/src/com/android/bluetooth/gatt/AdvertiserMap.java index 18701e282eb..c1169f77f34 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiserMap.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiserMap.java @@ -18,6 +18,7 @@ package com.android.bluetooth.gatt; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertisingSetParameters; import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.AttributionSource; import android.content.Context; import android.os.Binder; import android.util.Log; @@ -45,7 +46,7 @@ class AdvertiserMap { EvictingQueue.create(ADVERTISE_STATE_MAX_SIZE); /** Add an entry to the stats map if it doesn't already exist. */ - void addAppAdvertiseStats(int id, Context context) { + void addAppAdvertiseStats(int id, Context context, AttributionSource attrSource) { int appUid = Binder.getCallingUid(); String appName = context.getPackageManager().getNameForUid(appUid); if (appName == null) { @@ -55,7 +56,7 @@ class AdvertiserMap { synchronized (this) { if (!mAppAdvertiseStats.containsKey(id)) { - addAppAdvertiseStats(id, new AppAdvertiseStats(appUid, id, appName)); + addAppAdvertiseStats(id, new AppAdvertiseStats(appUid, id, appName, attrSource)); } } } diff --git a/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java b/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java index 1456d1271de..1746194f174 100644 --- a/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java +++ b/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java @@ -15,12 +15,16 @@ */ package com.android.bluetooth.gatt; +import static com.android.bluetooth.util.AttributionSourceUtil.getLastAttributionTag; + +import android.annotation.Nullable; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertisingSetCallback; import android.bluetooth.le.AdvertisingSetParameters; import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.AttributionSource; import android.os.ParcelUuid; import android.util.SparseArray; @@ -82,6 +86,7 @@ class AppAdvertiseStats { private int mAppUid; @VisibleForTesting String mAppName; + @Nullable private String mAttributionTag; private int mId; private boolean mAdvertisingEnabled = false; private boolean mPeriodicAdvertisingEnabled = false; @@ -93,17 +98,18 @@ class AppAdvertiseStats { private boolean mAnonymous = false; private boolean mConnectable = false; private boolean mScannable = false; - private AppAdvertiserData mAdvertisingData = null; - private AppAdvertiserData mScanResponseData = null; - private AppAdvertiserData mPeriodicAdvertisingData = null; + @Nullable private AppAdvertiserData mAdvertisingData = null; + @Nullable private AppAdvertiserData mScanResponseData = null; + @Nullable private AppAdvertiserData mPeriodicAdvertisingData = null; private boolean mPeriodicIncludeTxPower = false; private int mPeriodicInterval = 0; public ArrayList mAdvertiserRecords = new ArrayList(); - AppAdvertiseStats(int appUid, int id, String name) { + AppAdvertiseStats(int appUid, int id, String name, AttributionSource attrSource) { this.mAppUid = appUid; this.mId = id; this.mAppName = name; + this.mAttributionTag = getLastAttributionTag(attrSource); } void recordAdvertiseStart( @@ -553,6 +559,10 @@ class AppAdvertiseStats { Instant currentTime = Instant.now(); sb.append("\n ").append(stats.mAppName); + if (stats.mAttributionTag != null) { + sb.append("\n Tag : ") + .append(stats.mAttributionTag); + } sb.append("\n Advertising ID : ").append(stats.mId); for (int i = 0; i < stats.mAdvertiserRecords.size(); i++) { AppAdvertiserRecord record = stats.mAdvertiserRecords.get(i); diff --git a/android/app/src/com/android/bluetooth/gatt/ContextMap.java b/android/app/src/com/android/bluetooth/gatt/ContextMap.java index ab0af41b469..e43927a4b0c 100644 --- a/android/app/src/com/android/bluetooth/gatt/ContextMap.java +++ b/android/app/src/com/android/bluetooth/gatt/ContextMap.java @@ -15,6 +15,10 @@ */ package com.android.bluetooth.gatt; +import static com.android.bluetooth.util.AttributionSourceUtil.getLastAttributionTag; + +import android.annotation.Nullable; +import android.content.AttributionSource; import android.content.Context; import android.os.Binder; import android.os.IBinder; @@ -75,6 +79,9 @@ public class ContextMap { /** The package name of the application */ public final String name; + /** The last attribution tag of the caller */ + @Nullable public final String attributionTag; + /** Application callbacks */ public C callback; @@ -88,11 +95,12 @@ public class ContextMap { private List mCongestionQueue = new ArrayList<>(); /** Creates a new app context. */ - App(UUID uuid, C callback, int appUid, String name) { + App(UUID uuid, C callback, int appUid, String name, AttributionSource attrSource) { this.uuid = uuid; this.callback = callback; this.appUid = appUid; this.name = name; + this.attributionTag = getLastAttributionTag(attrSource); } /** Link death recipient */ @@ -146,7 +154,7 @@ public class ContextMap { private final Object mConnectionsLock = new Object(); /** Add an entry to the application context list. */ - public App add(UUID uuid, C callback, Context context) { + public App add(UUID uuid, C callback, Context context, AttributionSource attrSource) { int appUid = Binder.getCallingUid(); String appName = context.getPackageManager().getNameForUid(appUid); if (appName == null) { @@ -154,7 +162,7 @@ public class ContextMap { appName = "Unknown App (UID: " + appUid + ")"; } synchronized (mAppsLock) { - App app = new App(uuid, callback, appUid, appName); + App app = new App(uuid, callback, appUid, appName, attrSource); mApps.add(app); return app; } diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 1f7593fa2c7..cf50002922e 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -1943,7 +1943,8 @@ public class GattService extends ProfileService { duration, maxExtAdvEvents, serverIf, - callback); + callback, + attributionSource); } @RequiresPermission(BLUETOOTH_ADVERTISE) @@ -2102,7 +2103,7 @@ public class GattService extends ProfileService { } Log.d(TAG, "registerClient() - UUID=" + uuid); - mClientMap.add(uuid, callback, this); + mClientMap.add(uuid, callback, this, attributionSource); mNativeInterface.gattClientRegisterApp( uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support); } @@ -3161,7 +3162,7 @@ public class GattService extends ProfileService { } Log.d(TAG, "registerServer() - UUID=" + uuid); - mServerMap.add(uuid, callback, this); + mServerMap.add(uuid, callback, this, attributionSource); mNativeInterface.gattServerRegisterApp( uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support); } @@ -3551,11 +3552,25 @@ public class GattService extends ProfileService { mTransitionalScanHelper.getScannerMap().dumpApps(sb, ProfileService::println); sb.append(" Client:\n"); for (Integer appId : mClientMap.getAllAppsIds()) { - println(sb, " app_if: " + appId + ", appName: " + mClientMap.getById(appId).name); + ContextMap.App app = mClientMap.getById(appId); + println( + sb, + " app_if: " + + appId + + ", appName: " + + app.name + + (app.attributionTag == null ? "" : ", tag: " + app.attributionTag)); } sb.append(" Server:\n"); for (Integer appId : mServerMap.getAllAppsIds()) { - println(sb, " app_if: " + appId + ", appName: " + mServerMap.getById(appId).name); + ContextMap.App app = mServerMap.getById(appId); + println( + sb, + " app_if: " + + appId + + ", appName: " + + app.name + + (app.attributionTag == null ? "" : ", tag: " + app.attributionTag)); } sb.append("\n\n"); } 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 1f7e07e3173..b4a8853433d 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -1930,12 +1930,12 @@ public class LeAudioService extends ProfileService { mAdapterService .getBluetoothScanController() .getTransitionalScanHelper() - .registerScannerInternal(this, null); + .registerScannerInternal(this, getAttributionSource(), null); } else { mAdapterService .getBluetoothGattService() .getTransitionalScanHelper() - .registerScannerInternal(this, null); + .registerScannerInternal(this, getAttributionSource(), null); } } 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 1d8ad00082c..7438921f332 100644 --- a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java +++ b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java @@ -135,7 +135,7 @@ public class AppScanStats { } } - public String appName; + String mAppName; private WorkSource mWorkSource; // Used for BatteryStatsManager private final WorkSourceUtil mWorkSourceUtil; // Used for BluetoothStatsLog private int mScansStarted = 0; @@ -168,14 +168,14 @@ public class AppScanStats { ScannerMap map, Context context, TransitionalScanHelper scanHelper) { - appName = name; + mAppName = name; mScannerMap = map; mScanHelper = scanHelper; mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class); if (source == null) { // Bill the caller if the work source isn't passed through - source = new WorkSource(Binder.getCallingUid(), appName); + source = new WorkSource(Binder.getCallingUid(), mAppName); } mWorkSource = source; mWorkSourceUtil = new WorkSourceUtil(source); @@ -298,7 +298,7 @@ public class AppScanStats { BluetoothMetricsProto.ScanEvent.ScanTechnologyType .SCAN_TECH_TYPE_LE) .setEventTimeMillis(System.currentTimeMillis()) - .setInitiator(truncateAppName(appName)) + .setInitiator(truncateAppName(mAppName)) .build(); mScanHelper.addScanEvent(scanEvent); @@ -349,7 +349,7 @@ public class AppScanStats { BluetoothMetricsProto.ScanEvent.ScanTechnologyType .SCAN_TECH_TYPE_LE) .setEventTimeMillis(System.currentTimeMillis()) - .setInitiator(truncateAppName(appName)) + .setInitiator(truncateAppName(mAppName)) .setNumberResults(scan.results) .build(); mScanHelper.addScanEvent(scanEvent); @@ -1000,7 +1000,7 @@ public class AppScanStats { + ambientDiscoveryScanTime * AMBIENT_DISCOVERY_WEIGHT) / 100; - sb.append(" ").append(appName); + sb.append(" ").append(mAppName); if (isRegistered) { sb.append(" (Registered)"); } @@ -1153,10 +1153,15 @@ public class AppScanStats { } } - ScannerMap.ScannerApp appEntry = mScannerMap.getByName(appName); - if (appEntry != null && isRegistered) { - sb.append("\n Application ID : ").append(appEntry.mId); - sb.append("\n UUID : ").append(appEntry.mUuid); + if (isRegistered) { + List appEntries = mScannerMap.getByName(mAppName); + for (ScannerMap.ScannerApp appEntry : appEntries) { + sb.append("\n Application ID: ").append(appEntry.mId); + sb.append(", UUID: ").append(appEntry.mUuid); + if (appEntry.mAttributionTag != null) { + sb.append(", Tag: ").append(appEntry.mAttributionTag); + } + } } sb.append("\n\n"); } diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanClient.java b/android/app/src/com/android/bluetooth/le_scan/ScanClient.java index dd1589e5a0c..0973ea37844 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanClient.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanClient.java @@ -89,8 +89,8 @@ public class ScanClient { .append(scanModeApp) .append(" scanModeUsed ") .append(settings.getScanMode()); - if (stats != null && stats.appName != null) { - sb.append(" [appScanStats ").append(stats.appName).append("]"); + if (stats != null && stats.mAppName != null) { + sb.append(" [appScanStats ").append(stats.mAppName).append("]"); } sb.append("]"); return sb.toString(); diff --git a/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java b/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java index 0e0d747e0b5..9f02de3cca9 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java @@ -15,8 +15,11 @@ */ package com.android.bluetooth.le_scan; +import static com.android.bluetooth.util.AttributionSourceUtil.getLastAttributionTag; + import android.annotation.Nullable; import android.bluetooth.le.IScannerCallback; +import android.content.AttributionSource; import android.content.Context; import android.os.Binder; import android.os.IBinder; @@ -47,24 +50,27 @@ public class ScannerMap { /** Add an entry to the application context list with a callback. */ ScannerApp add( UUID uuid, + AttributionSource attributionSource, WorkSource workSource, IScannerCallback callback, Context context, TransitionalScanHelper scanHelper) { - return add(uuid, workSource, callback, null, context, scanHelper); + return add(uuid, attributionSource, workSource, callback, null, context, scanHelper); } /** Add an entry to the application context list with a pending intent. */ ScannerApp add( UUID uuid, + AttributionSource attributionSource, TransitionalScanHelper.PendingIntentInfo piInfo, Context context, TransitionalScanHelper scanHelper) { - return add(uuid, null, null, piInfo, context, scanHelper); + return add(uuid, attributionSource, null, null, piInfo, context, scanHelper); } private ScannerApp add( UUID uuid, + AttributionSource attributionSource, @Nullable WorkSource workSource, @Nullable IScannerCallback callback, @Nullable TransitionalScanHelper.PendingIntentInfo piInfo, @@ -88,7 +94,14 @@ public class ScannerMap { appScanStats = new AppScanStats(appName, workSource, this, context, scanHelper); mAppScanStatsMap.put(appUid, appScanStats); } - ScannerApp app = new ScannerApp(uuid, callback, piInfo, appName, appScanStats); + ScannerApp app = + new ScannerApp( + uuid, + getLastAttributionTag(attributionSource), + callback, + piInfo, + appName, + appScanStats); mApps.add(app); appScanStats.isRegistered = true; return app; @@ -147,13 +160,9 @@ public class ScannerMap { return app; } - /** Get an application context by the calling Apps name. */ - ScannerApp getByName(String name) { - ScannerApp app = getAppByPredicate(entry -> entry.mName.equals(name)); - if (app == null) { - Log.e(TAG, "Context not found for name " + name); - } - return app; + /** Get application contexts by the calling app's name. */ + List getByName(String name) { + return mApps.stream().filter(app -> app.mName.equals(name)).toList(); } /** Get an application context by the pending intent info object. */ @@ -187,7 +196,15 @@ public class ScannerMap { /** Logs all apps for debugging. */ public void dumpApps(StringBuilder sb, BiConsumer bf) { for (ScannerApp entry : mApps) { - bf.accept(sb, " app_if: " + entry.mId + ", appName: " + entry.mName); + bf.accept( + sb, + " app_if: " + + entry.mId + + ", appName: " + + entry.mName + + (entry.mAttributionTag == null + ? "" + : ", tag: " + entry.mAttributionTag)); } } @@ -204,6 +221,9 @@ public class ScannerMap { /** The package name of the application */ final String mName; + /** The last attribution tag in the attribution source chain */ + @Nullable final String mAttributionTag; + /** Application callbacks */ @Nullable IScannerCallback mCallback; @@ -238,11 +258,13 @@ public class ScannerMap { /** Creates a new app context. */ ScannerApp( UUID uuid, + @Nullable String attributionTag, @Nullable IScannerCallback callback, @Nullable TransitionalScanHelper.PendingIntentInfo info, String name, AppScanStats appScanStats) { this.mUuid = uuid; + this.mAttributionTag = attributionTag; this.mCallback = callback; this.mName = name; this.mInfo = info; diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java index 102bf9d42be..b164b06693f 100644 --- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java +++ b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java @@ -1066,7 +1066,7 @@ public class TransitionalScanHelper { if (app != null && app.isScanningTooFrequently() && !Utils.checkCallerHasPrivilegedPermission(mContext)) { - Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); + Log.e(TAG, "App '" + app.mAppName + "' is scanning too frequently"); try { callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); } catch (RemoteException e) { @@ -1074,15 +1074,16 @@ public class TransitionalScanHelper { } return; } - registerScannerInternal(callback, workSource); + registerScannerInternal(callback, attributionSource, workSource); } /** Intended for internal use within the Bluetooth app. Bypass permission check */ - public void registerScannerInternal(IScannerCallback callback, WorkSource workSource) { + public void registerScannerInternal( + IScannerCallback callback, AttributionSource attrSource, WorkSource workSource) { UUID uuid = UUID.randomUUID(); Log.d(TAG, "registerScanner() - UUID=" + uuid); - mScannerMap.add(uuid, workSource, callback, mContext, this); + mScannerMap.add(uuid, attrSource, workSource, callback, mContext, this); mScanManager.registerScanner(uuid); } @@ -1252,7 +1253,8 @@ public class TransitionalScanHelper { return; } - ScannerMap.ScannerApp app = mScannerMap.add(uuid, piInfo, mContext, this); + ScannerMap.ScannerApp app = + mScannerMap.add(uuid, attributionSource, piInfo, mContext, this); app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid()); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); diff --git a/android/app/src/com/android/bluetooth/util/AttributionSourceUtil.java b/android/app/src/com/android/bluetooth/util/AttributionSourceUtil.java new file mode 100644 index 00000000000..4eae558bdd3 --- /dev/null +++ b/android/app/src/com/android/bluetooth/util/AttributionSourceUtil.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 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. + */ + +package com.android.bluetooth.util; + +import android.annotation.Nullable; +import android.content.AttributionSource; + +/** Class for general helper methods for AttributionSource operations. */ +public final class AttributionSourceUtil { + + private AttributionSourceUtil() {} + + /** Gets the last available attribution tag in a chain of {@link AttributionSource}. */ + @Nullable + public static String getLastAttributionTag(@Nullable AttributionSource source) { + String attributionTag = null; + while (source != null) { + if (source.getAttributionTag() != null) { + attributionTag = source.getAttributionTag(); + } + source = source.getNext(); + } + return attributionTag; + } +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java index 1ce6314a873..6621a433316 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java @@ -28,6 +28,7 @@ import android.bluetooth.le.IAdvertisingSetCallback; import android.bluetooth.le.PeriodicAdvertisingParameters; import android.os.IBinder; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -91,7 +92,8 @@ public class AdvertiseManagerTest { duration, maxExtAdvEvents, 0, - mCallback); + mCallback, + InstrumentationRegistry.getTargetContext().getAttributionSource()); mAdvertiserId = AdvertiseManager.sTempRegistrationId; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java index e29b833555c..6dc7132eeaf 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java @@ -26,9 +26,11 @@ import static org.mockito.Mockito.verify; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertisingSetParameters; import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.AttributionSource; import android.content.pm.PackageManager; import android.os.Binder; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -55,6 +57,9 @@ public class AdvertiserMapTest { @Mock private AdapterService mAdapterService; @Mock private PackageManager mMockPackageManager; + private final AttributionSource mAttributionSource = + InstrumentationRegistry.getTargetContext().getAttributionSource(); + @Before public void setUp() throws Exception { TestUtils.setAdapterService(mAdapterService); @@ -73,7 +78,7 @@ public class AdvertiserMapTest { AdvertiserMap advertiserMap = new AdvertiserMap(); int id = 12345; - advertiserMap.addAppAdvertiseStats(id, mAdapterService); + advertiserMap.addAppAdvertiseStats(id, mAdapterService, mAttributionSource); AppAdvertiseStats stats = advertiserMap.getAppAdvertiseStatsById(id); assertThat(stats.mAppName).isEqualTo(APP_NAME); @@ -84,7 +89,7 @@ public class AdvertiserMapTest { AdvertiserMap advertiserMap = new AdvertiserMap(); int id = 12345; - advertiserMap.addAppAdvertiseStats(id, mAdapterService); + advertiserMap.addAppAdvertiseStats(id, mAdapterService, mAttributionSource); AppAdvertiseStats stats = advertiserMap.getAppAdvertiseStatsById(id); assertThat(stats.mAppName).isEqualTo(APP_NAME); @@ -98,7 +103,9 @@ public class AdvertiserMapTest { AdvertiserMap advertiserMap = new AdvertiserMap(); int id = 12345; AppAdvertiseStats appAdvertiseStats = - spy(new AppAdvertiseStats(Binder.getCallingUid(), id, APP_NAME)); + spy( + new AppAdvertiseStats( + Binder.getCallingUid(), id, APP_NAME, mAttributionSource)); advertiserMap.addAppAdvertiseStats(id, appAdvertiseStats); int duration = 60; @@ -155,11 +162,11 @@ public class AdvertiserMapTest { AdvertiserMap advertiserMap = new AdvertiserMap(); int id = 12345; - advertiserMap.addAppAdvertiseStats(id, mAdapterService); + advertiserMap.addAppAdvertiseStats(id, mAdapterService, mAttributionSource); advertiserMap.recordAdvertiseStop(id); int idSecond = 54321; - advertiserMap.addAppAdvertiseStats(idSecond, mAdapterService); + advertiserMap.addAppAdvertiseStats(idSecond, mAdapterService, mAttributionSource); advertiserMap.dump(sb); } } 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 38c86c67cc8..28cb4074ef5 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 @@ -26,10 +26,12 @@ import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertisingSetParameters; import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.AttributionSource; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Log; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -68,6 +70,9 @@ public class AppAdvertiseStatsTest { @Captor ArgumentCaptor mAdvDurationCaptor; + private final AttributionSource mAttributionSource = + InstrumentationRegistry.getTargetContext().getAttributionSource(); + @Before public void setUp() throws Exception { MetricsLogger.setInstanceForTesting(mMetricsLogger); @@ -96,7 +101,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); assertThat(appAdvertiseStats.mAdvertiserRecords.size()).isEqualTo(0); @@ -134,7 +140,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); int duration = 1; int maxExtAdvEvents = 2; @@ -174,7 +181,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); int duration = 1; int maxExtAdvEvents = 2; @@ -196,7 +204,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); AdvertiseData advertiseData = new AdvertiseData.Builder().build(); appAdvertiseStats.setAdvertisingData(advertiseData); @@ -210,7 +219,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); AdvertiseData scanResponse = new AdvertiseData.Builder().build(); appAdvertiseStats.setScanResponseData(scanResponse); @@ -224,7 +234,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build(); appAdvertiseStats.setAdvertisingParameters(parameters); @@ -236,7 +247,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); PeriodicAdvertisingParameters periodicParameters = new PeriodicAdvertisingParameters.Builder().build(); @@ -249,7 +261,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); AdvertiseData periodicData = new AdvertiseData.Builder().build(); appAdvertiseStats.setPeriodicAdvertisingData(periodicData); @@ -265,7 +278,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build(); AdvertiseData advertiseData = new AdvertiseData.Builder().build(); @@ -297,7 +311,8 @@ public class AppAdvertiseStatsTest { int id = 1; String name = "name"; - AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name); + AppAdvertiseStats appAdvertiseStats = + new AppAdvertiseStats(appUid, id, name, mAttributionSource); AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().setConnectable(true).build(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java index 04cb38e6b58..e0fb8671df1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.doReturn; import android.bluetooth.IBluetoothGattCallback; import android.content.pm.PackageManager; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; @@ -172,9 +173,19 @@ public class ContextMapTest { private ContextMap getMapWithAppAndConnection() { ContextMap contextMap = new ContextMap<>(); - App app = contextMap.add(RANDOM_UUID1, mMockCallback, mAdapterService); + App app = + contextMap.add( + RANDOM_UUID1, + mMockCallback, + mAdapterService, + InstrumentationRegistry.getTargetContext().getAttributionSource()); app.id = APP_ID1; - app = contextMap.add(RANDOM_UUID2, mMockCallback, mAdapterService); + app = + contextMap.add( + RANDOM_UUID2, + mMockCallback, + mAdapterService, + InstrumentationRegistry.getTargetContext().getAttributionSource()); app.id = APP_ID2; contextMap.addConnection(APP_ID1, CONN_ID1, ADDRESS1); 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 da45445ac2e..bb675ed5a6d 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 @@ -374,7 +374,7 @@ public class GattServiceTest { IBluetoothGattCallback callback = mock(IBluetoothGattCallback.class); mService.registerClient(uuid, callback, /* eattSupport= */ true, mAttributionSource); - verify(mClientMap, never()).add(any(), any(), any()); + verify(mClientMap, never()).add(any(), any(), any(), any()); verify(mNativeInterface, never()).gattClientRegisterApp(anyLong(), anyLong(), anyBoolean()); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java index e5bf535dc4b..83cdcceae9c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.doReturn; import android.app.PendingIntent; import android.bluetooth.le.IScannerCallback; +import android.content.AttributionSource; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Binder; @@ -62,6 +63,8 @@ public class ScannerMapTest { @Mock private PackageManager mMockPackageManager; @Mock private TransitionalScanHelper mMockTransitionalScanHelper; @Mock private IScannerCallback mMockScannerCallback; + private final AttributionSource mAttributionSource = + InstrumentationRegistry.getTargetContext().getAttributionSource(); @Spy private BluetoothMethodProxy mMapMethodProxy = BluetoothMethodProxy.getInstance(); @@ -94,7 +97,12 @@ public class ScannerMapTest { PendingIntent.FLAG_IMMUTABLE); UUID uuid = UUID.randomUUID(); ScannerMap.ScannerApp app = - scannerMap.add(uuid, info, mAdapterService, mMockTransitionalScanHelper); + scannerMap.add( + uuid, + mAttributionSource, + info, + mAdapterService, + mMockTransitionalScanHelper); app.mId = SCANNER_ID; ScannerMap.ScannerApp scannerMapById = scannerMap.getById(SCANNER_ID); @@ -103,7 +111,7 @@ public class ScannerMapTest { ScannerMap.ScannerApp scannerMapByUuid = scannerMap.getByUuid(uuid); assertThat(scannerMapByUuid.mName).isEqualTo(APP_NAME); - ScannerMap.ScannerApp scannerMapByName = scannerMap.getByName(APP_NAME); + ScannerMap.ScannerApp scannerMapByName = scannerMap.getByName(APP_NAME).get(0); assertThat(scannerMapByName.mName).isEqualTo(APP_NAME); ScannerMap.ScannerApp scannerMapByPii = scannerMap.getByPendingIntentInfo(info); @@ -120,6 +128,7 @@ public class ScannerMapTest { ScannerMap.ScannerApp app = scannerMap.add( uuid, + mAttributionSource, null, mMockScannerCallback, mAdapterService, @@ -134,7 +143,7 @@ public class ScannerMapTest { ScannerMap.ScannerApp scannerMapByUuid = scannerMap.getByUuid(uuid); assertThat(scannerMapByUuid.mName).isEqualTo(APP_NAME); - ScannerMap.ScannerApp scannerMapByName = scannerMap.getByName(APP_NAME); + ScannerMap.ScannerApp scannerMapByName = scannerMap.getByName(APP_NAME).get(0); assertThat(scannerMapByName.mName).isEqualTo(APP_NAME); assertThat(scannerMap.getAppScanStatsById(SCANNER_ID)).isNotNull(); @@ -148,6 +157,7 @@ public class ScannerMapTest { ScannerMap.ScannerApp app = scannerMap.add( uuid, + mAttributionSource, null, mMockScannerCallback, mAdapterService, @@ -167,6 +177,7 @@ public class ScannerMapTest { ScannerMap scannerMap = new ScannerMap(); scannerMap.add( UUID.randomUUID(), + mAttributionSource, null, mMockScannerCallback, mAdapterService, diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java index 1305da683ad..f49529c65e5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java @@ -270,7 +270,14 @@ public class TransitionalScanHelperTest { doReturn(appScanStats).when(mScannerMap).getAppScanStatsByUid(Binder.getCallingUid()); mScanHelper.registerScanner(callback, workSource, mAttributionSource); - verify(mScannerMap).add(any(), eq(workSource), eq(callback), any(), eq(mScanHelper)); + verify(mScannerMap) + .add( + any(), + eq(mAttributionSource), + eq(workSource), + eq(callback), + any(), + eq(mScanHelper)); verify(mScanManager).registerScanner(any()); } -- GitLab From c2627e7ba412378ae2e48b95cb3dcbe7e914e7eb Mon Sep 17 00:00:00 2001 From: Yun-Hao Chung Date: Fri, 11 Oct 2024 04:38:38 +0000 Subject: [PATCH 269/875] Floss: Ignore the timeout-ed HCI command instead of crash Some old controllers are known to be non-responsive in some random situations. Since these controllers are unlikely to get updated and ChromeOS doesn't like crashes, this patch skips the debug info collecting procedures on timeout and directly terminates the process. Bug: 259344636 Tag: #floss Test: mmm packages/modules/Bluetooth Flag: EXEMPT, Floss-only change Change-Id: I27fa56761521efed5d5cbdf170214bf77c70b03c --- system/gd/hci/hci_layer.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc index 70a5f43b567..f9847101c03 100644 --- a/system/gd/hci/hci_layer.cc +++ b/system/gd/hci/hci_layer.cc @@ -279,6 +279,17 @@ struct HciLayer::impl { command_queue_.clear(); command_credits_ = 1; waiting_command_ = OpCode::NONE; + +#ifdef TARGET_FLOSS + 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->markControllerBroken(); + kill(getpid(), SIGTERM); + return; +#endif + // Ignore the response, since we don't know what might come back. enqueue_command(ControllerDebugInfoBuilder::Create(), module_.GetHandler()->BindOnce([](CommandCompleteView) {})); -- GitLab From ac3c7e64ec37097026d1099f5d03817dbd8da030 Mon Sep 17 00:00:00 2001 From: Bao Do Date: Mon, 7 Oct 2024 10:40:41 +0800 Subject: [PATCH 270/875] Add lock_guard to FetchAudioProvider. Audio provider are refetched mainly due to the service being restarted. Adding lock_guard to this function prevent service access while refetching for other important functions (StartSession, EndSession, ...) to prevent BT crashes. Also add lock_guard access to some other important functions. Bug: 341856622 Test: mmm packages/modules/Bluetooth Flag: EXEMPT trivial change Change-Id: I0e8ad04414dd79105ad8339e866b82a7d2ab8ad2 --- system/audio_hal_interface/aidl/client_interface_aidl.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.cc b/system/audio_hal_interface/aidl/client_interface_aidl.cc index fc6555223f0..87e29cdab99 100644 --- a/system/audio_hal_interface/aidl/client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/client_interface_aidl.cc @@ -135,6 +135,8 @@ void BluetoothAudioClientInterface::FetchAudioProvider() { if (provider_ != nullptr) { log::warn("refetch"); } + // Prevent other access to the AIDL if currently fetching new service + std::lock_guard guard(internal_mutex_); // Retry if audioserver restarts in the middle of fetching. // When audioserver restarts, IBluetoothAudioProviderFactory service is also // re-registered, so we need to re-fetch the service. @@ -164,7 +166,7 @@ void BluetoothAudioClientInterface::FetchAudioProvider() { toString(transport_->GetSessionType()), capabilities_.size()); aidl_retval = provider_factory->openProvider(transport_->GetSessionType(), &provider_); - if (!aidl_retval.isOk()) { + if (!aidl_retval.isOk() || provider_ == nullptr) { log::error("BluetoothAudioHal::openProvider failure: {}, retry number {}", aidl_retval.getDescription(), retry_no + 1); } else { @@ -220,6 +222,7 @@ void BluetoothAudioClientInterface::binderDiedCallbackAidl(void* ptr) { } bool BluetoothAudioClientInterface::UpdateAudioConfig(const AudioConfiguration& audio_config) { + std::lock_guard guard(internal_mutex_); bool is_software_session = (transport_->GetSessionType() == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || transport_->GetSessionType() == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH || @@ -603,6 +606,7 @@ BluetoothAudioClientInterface::GetLeAudioAseConfiguration( std::vector>>& remoteSourceAudioCapabilities, std::vector& requirements) { + std::lock_guard guard(internal_mutex_); log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); std::vector configurations; @@ -670,6 +674,7 @@ BluetoothAudioClientInterface::getLeAudioBroadcastConfiguration( std::vector>>& remoteSinkAudioCapabilities, const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& requirement) { + std::lock_guard guard(internal_mutex_); log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr"); IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting setting; -- GitLab From ea4a80945b715580bd2c509f22896bda494fc92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 11 Oct 2024 08:38:19 +0000 Subject: [PATCH 271/875] flags: Add leaudio_mono_location_errata_api Bug: 372840605 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: Iac8dd049596624630c36ad6af15ae2c36881d544 --- flags/leaudio.aconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 3a437baf520..dfd73ac48d9 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -98,6 +98,14 @@ flag { } } +flag { + name: "leaudio_mono_location_errata_api" + is_exported: true + namespace: "bluetooth" + description: "Add mono location as per Bluetooth Assigned Numbers to API" + bug: "372840605" +} + flag { name: "leaudio_getting_active_state_support" namespace: "bluetooth" -- GitLab From 8916949bbde921050bea8241f4bfb6f1b04ebb79 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 11 Oct 2024 09:12:46 -0700 Subject: [PATCH 272/875] Replace fmt::throw_format_error with fmt::report_error fmt::throw_format_error is deprecated in favor of fmt::report_error. The behaviour is exactly the same. Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I6f98eca50e77fbedf9d4284590600f3a07384dc7 --- tools/rootcanal/include/hci/address.h | 2 +- tools/rootcanal/include/hci/address_with_type.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rootcanal/include/hci/address.h b/tools/rootcanal/include/hci/address.h index fe4d454d5d2..fc694f3fe09 100644 --- a/tools/rootcanal/include/hci/address.h +++ b/tools/rootcanal/include/hci/address.h @@ -122,7 +122,7 @@ struct fmt::formatter { // Check if reached the end of the range: if (it != end && *it != '}') { - throw_format_error("invalid format"); + report_error("invalid format"); } // Return an iterator past the end of the parsed range: diff --git a/tools/rootcanal/include/hci/address_with_type.h b/tools/rootcanal/include/hci/address_with_type.h index 1172ac7fa22..f9560f44668 100644 --- a/tools/rootcanal/include/hci/address_with_type.h +++ b/tools/rootcanal/include/hci/address_with_type.h @@ -153,7 +153,7 @@ struct fmt::formatter { // Check if reached the end of the range: if (it != end && *it != '}') { - throw_format_error("invalid format"); + report_error("invalid format"); } // Return an iterator past the end of the parsed range: -- GitLab From 741cf430854b278bfee74c9438b636d45b24f968 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 11 Oct 2024 17:22:17 +0000 Subject: [PATCH 273/875] Remove the unused procedure counter Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 368617974 Test: m com.android.btservices Change-Id: I4ec310dd02312fd334abb6cae950e44565ab9be4 --- system/gd/hci/distance_measurement_manager.cc | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index b8ce2f4263e..af17402bea4 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -143,8 +143,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { struct CsTracker { Address address; hci::Role local_hci_role; - uint16_t local_counter; - uint16_t remote_counter; + uint16_t procedure_counter; CsRole role; bool local_start = false; // If the CS was started by the local device. bool measurement_ongoing = false; @@ -856,7 +855,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } CsProcedureData* procedure_data = init_cs_procedure_data(connection_handle, cs_event_result.GetProcedureCounter(), - cs_event_result.GetNumAntennaPaths(), true); + cs_event_result.GetNumAntennaPaths()); if (cs_trackers_[connection_handle].role == CsRole::INITIATOR) { procedure_data->frequency_compensation.push_back( cs_event_result.GetFrequencyCompensation()); @@ -886,7 +885,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } - uint16_t counter = cs_trackers_[connection_handle].local_counter; + uint16_t counter = cs_trackers_[connection_handle].procedure_counter; log::debug( "Connection_handle {}, procedure_done_status: {}, subevent_done_status: {}, counter: " "{}", @@ -1185,13 +1184,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } CsProcedureData* init_cs_procedure_data(uint16_t connection_handle, uint16_t procedure_counter, - uint8_t num_antenna_paths, bool local) { + uint8_t num_antenna_paths) { // Update procedure count - if (local) { - cs_trackers_[connection_handle].local_counter = procedure_counter; - } else { - cs_trackers_[connection_handle].remote_counter = procedure_counter; - } + cs_trackers_[connection_handle].procedure_counter = procedure_counter; std::vector& data_list = cs_trackers_[connection_handle].procedure_data_list; for (auto& data : data_list) { -- GitLab From 9007fa407ecdca1ccef221a35fec5b0004634c38 Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Wed, 9 Oct 2024 19:42:07 +0800 Subject: [PATCH 274/875] flags: add metadata_api_microphone_for_call_enabled Bug: 372395197 Bug: 315241296 Test: m service-bluetooth Change-Id: I1f409d8890023477048c6ed3c6a02f871d132eb9 --- flags/leaudio.aconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 3a437baf520..e0e831fe06e 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -375,3 +375,11 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "metadata_api_microphone_for_call_enabled" + is_exported: true + namespace: "bluetooth" + description: "API to get and set microphone for call enable status" + bug: "372395197" +} -- GitLab From 1f1282e0437cd473adcb08c8db0034d722da91d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 9 Oct 2024 15:26:06 +0000 Subject: [PATCH 275/875] l2cap: Fix setting FCS Option As per BT Core specification, FCS option shall be preset if ERTM or Streaming mode is used and peer supports it. Since Android supports FCS option, lets set it here, and later, code will check if peer supports it as well in: l2cu_process_our_cfg_req() Bug: 371947246 Bug: 372605959 Test: manual PTS test case Test: mmm packages/modules/Bluetooth Flag: com::android::bluetooth::flags::l2cap_fcs_option_fix Change-Id: I5a2333207a9b27c1253aa4e33ca06389a68655ec --- system/stack/l2cap/l2c_csm.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system/stack/l2cap/l2c_csm.cc b/system/stack/l2cap/l2c_csm.cc index 290fa82b877..1c7021ffc70 100644 --- a/system/stack/l2cap/l2c_csm.cc +++ b/system/stack/l2cap/l2c_csm.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -74,6 +75,13 @@ static void l2c_csm_send_config_req(tL2C_CCB* p_ccb) { if (p_ccb->p_rcb->ertm_info.preferred_mode != L2CAP_FCR_BASIC_MODE) { config.fcr_present = true; config.fcr = kDefaultErtmOptions; + + if (com::android::bluetooth::flags::l2cap_fcs_option_fix()) { + /* Later l2cu_process_our_cfg_req() will check if remote supports it, and if not, it will be + * cleared as per spec. */ + config.fcs_present = true; + config.fcs = 1; + } } p_ccb->our_cfg = config; l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONFIG_REQ, &config); -- GitLab From 7ac301122a06beb0c5480862fe7c63f0f717395d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 11 Oct 2024 14:54:10 +0000 Subject: [PATCH 276/875] l2cap: Store remote FCS Configuration options Make sure to remember remote configuration. Bug: 371948052 Bug: 372605959 Test: mmm packages/modules/Bluetooth Test: manual PTS tests L2CAP/FOC/BV-05-C Flag: com.android.bluetooth.flags.l2cap_fcs_option_fix Change-Id: I173ecff48efc74c424d9f671c89646a569413f2f --- system/stack/l2cap/l2c_utils.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index a45d2c1e688..9efa7dea3e8 100644 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -1884,6 +1884,11 @@ uint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE; } + if (com::android::bluetooth::flags::l2cap_fcs_option_fix() && p_cfg->fcs_present) { + p_ccb->peer_cfg.fcs_present = 1; + p_ccb->peer_cfg.fcs = p_cfg->fcs; + } + if (!p_cfg->mtu_present && required_remote_mtu > L2CAP_DEFAULT_MTU) { // We reject if we have a MTU requirement higher than default MTU p_cfg->mtu = required_remote_mtu; -- GitLab From 44d9c45883bc3bce245a294462773b1fbbd410b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 11 Oct 2024 14:55:43 +0000 Subject: [PATCH 277/875] l2cap: Fix using FCS field in S/I frames As per Version 6.0 | Vol 3, Part A, 5.5 Frame Check Sequence (FCS) option If both sides configure channel for `No FCS`, then this field shall be skipped. Android by default uses FCS and this fix is needed only for PTS tests and in case other products would like to configure stack in a different way. Bug: 371948052 Bug: 372605959 Test: mmm packages/modules/Bluetooth Test: manual PTS tests L2CAP/FOC/BV-05-C Flag: com.android.bluetooth.flags.l2cap_fcs_option_fix Change-Id: I62eeeb0e497be1819d8f83bf25997641392c022a --- system/stack/l2cap/l2c_fcr.cc | 73 ++++++++++++++++++++------------- system/stack/l2cap/l2c_int.h | 1 + system/stack/l2cap/l2c_utils.cc | 24 +++++++++++ 3 files changed, 69 insertions(+), 29 deletions(-) diff --git a/system/stack/l2cap/l2c_fcr.cc b/system/stack/l2cap/l2c_fcr.cc index fdcbdb0506c..9b144ec8977 100644 --- a/system/stack/l2cap/l2c_fcr.cc +++ b/system/stack/l2cap/l2c_fcr.cc @@ -280,6 +280,8 @@ static void prepare_I_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, bool is_retransmissi uint16_t ctrl_word; bool set_f_bit = p_fcrb->send_f_rsp; + uint8_t fcs_len = l2cu_get_fcs_len(p_ccb); + p_fcrb->send_f_rsp = false; if (is_retransmission) { @@ -317,21 +319,23 @@ static void prepare_I_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, bool is_retransmissi /* Compute the FCS and add to the end of the buffer if not bypassed */ /* length field in l2cap header has to include FCS length */ p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; - UINT16_TO_STREAM(p, p_buf->len + L2CAP_FCS_LEN - L2CAP_PKT_OVERHEAD); + UINT16_TO_STREAM(p, p_buf->len + fcs_len - L2CAP_PKT_OVERHEAD); - /* Calculate the FCS */ - fcs = l2c_fcr_tx_get_fcs(p_buf); + if (fcs_len != 0) { + /* Calculate the FCS */ + fcs = l2c_fcr_tx_get_fcs(p_buf); - /* Point to the end of the buffer and put the FCS there */ - /* - * NOTE: Here we assume the allocated buffer is large enough - * to include extra L2CAP_FCS_LEN octets at the end. - */ - p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len; + /* Point to the end of the buffer and put the FCS there */ + /* + * NOTE: Here we assume the allocated buffer is large enough + * to include extra L2CAP_FCS_LEN octets at the end. + */ + p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len; - UINT16_TO_STREAM(p, fcs); + UINT16_TO_STREAM(p, fcs); - p_buf->len += L2CAP_FCS_LEN; + p_buf->len += fcs_len; + } if (is_retransmission) { log::verbose( @@ -397,16 +401,20 @@ void l2c_fcr_send_S_frame(tL2C_CCB* p_ccb, uint16_t function_code, uint16_t pf_b /* Set the pointer to the beginning of the data */ p = (uint8_t*)(p_buf + 1) + p_buf->offset; + uint8_t fcs_len = l2cu_get_fcs_len(p_ccb); + /* Put in the L2CAP header */ - UINT16_TO_STREAM(p, L2CAP_FCR_OVERHEAD + L2CAP_FCS_LEN); + UINT16_TO_STREAM(p, L2CAP_FCR_OVERHEAD + fcs_len); UINT16_TO_STREAM(p, p_ccb->remote_cid); UINT16_TO_STREAM(p, ctrl_word); - /* Compute the FCS and add to the end of the buffer if not bypassed */ - fcs = l2c_fcr_tx_get_fcs(p_buf); + if (fcs_len != 0) { + /* Compute the FCS and add to the end of the buffer if not bypassed */ + fcs = l2c_fcr_tx_get_fcs(p_buf); - UINT16_TO_STREAM(p, fcs); - p_buf->len += L2CAP_FCS_LEN; + UINT16_TO_STREAM(p, fcs); + p_buf->len += fcs_len; + } /* Now, the HCI transport header */ p_buf->layer_specific = L2CAP_NON_FLUSHABLE_PKT; @@ -462,7 +470,9 @@ void l2c_fcr_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf) { uint16_t ctrl_word; /* Check the length */ - min_pdu_len = (uint16_t)(L2CAP_FCS_LEN + L2CAP_FCR_OVERHEAD); + uint8_t fcs_len = l2cu_get_fcs_len(p_ccb); + + min_pdu_len = (uint16_t)(fcs_len + L2CAP_FCR_OVERHEAD); if (p_buf->len < min_pdu_len) { log::warn("Rx L2CAP PDU: CID: 0x{:04x} Len too short: {}", p_ccb->local_cid, p_buf->len); @@ -514,17 +524,19 @@ void l2c_fcr_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf) { p_ccb->fcrb.last_ack_sent, fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q), p_ccb->fcrb.num_tries); - /* Verify FCS if using */ - p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len - L2CAP_FCS_LEN; + if (fcs_len != 0) { + /* Verify FCS if using */ + p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len - fcs_len; - /* Extract and drop the FCS from the packet */ - STREAM_TO_UINT16(fcs, p); - p_buf->len -= L2CAP_FCS_LEN; + /* Extract and drop the FCS from the packet */ + STREAM_TO_UINT16(fcs, p); + p_buf->len -= fcs_len; - if (l2c_fcr_rx_get_fcs(p_buf) != fcs) { - log::warn("Rx L2CAP PDU: CID: 0x{:04x} BAD FCS", p_ccb->local_cid); - osi_free(p_buf); - return; + if (l2c_fcr_rx_get_fcs(p_buf) != fcs) { + log::warn("Rx L2CAP PDU: CID: 0x{:04x} BAD FCS", p_ccb->local_cid); + osi_free(p_buf); + return; + } } /* Get the control word */ @@ -1466,6 +1478,7 @@ BT_HDR* l2c_fcr_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb, uint16_t max_packet_lengt } prepare_I_frame(p_ccb, p_xmit, false); + uint8_t fcs_len = l2cu_get_fcs_len(p_ccb); if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) { BT_HDR* p_wack = l2c_fcr_clone_buf(p_xmit, HCI_DATA_PREAMBLE_SIZE, p_xmit->len); @@ -1475,14 +1488,14 @@ BT_HDR* l2c_fcr_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb, uint16_t max_packet_lengt p_xmit->len); /* We will not save the FCS in case we reconfigure and change options */ - p_xmit->len -= L2CAP_FCS_LEN; + p_xmit->len -= fcs_len; /* Pretend we sent it and it got lost */ fixed_queue_enqueue(p_ccb->fcrb.waiting_for_ack_q, p_xmit); return NULL; } else { /* We will not save the FCS in case we reconfigure and change options */ - p_wack->len -= L2CAP_FCS_LEN; + p_wack->len -= fcs_len; p_wack->layer_specific = p_xmit->layer_specific; fixed_queue_enqueue(p_ccb->fcrb.waiting_for_ack_q, p_wack); @@ -1793,6 +1806,8 @@ uint8_t l2c_fcr_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { } } + uint8_t fcs_len = l2cu_get_fcs_len(p_ccb); + /* Configuration for FCR channels so make any adjustments and fwd to upper * layer */ if (fcr_ok == L2CAP_PEER_CFG_OK) { @@ -1807,7 +1822,7 @@ uint8_t l2c_fcr_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { } max_retrans_size = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR) - L2CAP_MIN_OFFSET - - L2CAP_SDU_LEN_OFFSET - L2CAP_FCS_LEN; + L2CAP_SDU_LEN_OFFSET - fcs_len; /* Ensure the MPS is not bigger than the MTU */ if ((p_cfg->fcr.mps == 0) || (p_cfg->fcr.mps > p_ccb->peer_cfg.mtu)) { diff --git a/system/stack/l2cap/l2c_int.h b/system/stack/l2cap/l2c_int.h index ac8e62f17cc..94396b7577e 100644 --- a/system/stack/l2cap/l2c_int.h +++ b/system/stack/l2cap/l2c_int.h @@ -762,6 +762,7 @@ void l2cu_release_ble_rcb(tL2C_RCB* p_rcb); tL2C_RCB* l2cu_allocate_ble_rcb(uint16_t psm); tL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm); +uint8_t l2cu_get_fcs_len(tL2C_CCB* p_ccb); uint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg); void l2cu_process_peer_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg); void l2cu_process_our_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg); diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index 9efa7dea3e8..6497bb1c370 100644 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -1849,6 +1849,30 @@ tL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm) { return NULL; } +/************************************************************************************* + * + * Function l2cu_get_fcs_len + * + * Description This function is called to determine FCS len in S/I Frames. + * + * + * Returns 0 or L2CAP_FCS_LEN: 0 is returned when both sides configure `No FCS` + * + **************************************************************************************/ +uint8_t l2cu_get_fcs_len(tL2C_CCB* p_ccb) { + log::verbose("our.fcs_present: {} our.fcs: {}, peer.fcs_present: {} peer.fcs: {}", + p_ccb->our_cfg.fcs_present, p_ccb->our_cfg.fcs, p_ccb->peer_cfg.fcs_present, + p_ccb->peer_cfg.fcs); + + if (com::android::bluetooth::flags::l2cap_fcs_option_fix() && + (p_ccb->peer_cfg.fcs_present && p_ccb->peer_cfg.fcs == 0x00) && + (p_ccb->our_cfg.fcs_present && p_ccb->our_cfg.fcs == 0x00)) { + return 0; + } + + return L2CAP_FCS_LEN; +} + /******************************************************************************* * * Function l2cu_process_peer_cfg_req -- GitLab From 268ed8d577d8b6b58e7dc8c995ec6d4adb9a45ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 9 Oct 2024 15:27:11 +0000 Subject: [PATCH 278/875] sdp: Use ERTM for PTS testing To avoid creating additional tools, use SDP for testing L2CAP/FOC test cases Bug:371947246 Flag: TEST_ONLY Test: mmm packages/modules/Bluetooth Test: PTS Change-Id: Iaa34cdaa5c9e30607a8ef0a040219eb2edd63aac --- system/stack/sdp/sdp_main.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/stack/sdp/sdp_main.cc b/system/stack/sdp/sdp_main.cc index f166bb601e1..8ae52118a99 100644 --- a/system/stack/sdp/sdp_main.cc +++ b/system/stack/sdp/sdp_main.cc @@ -423,9 +423,16 @@ void sdp_init(void) { sdp_cb.reg_info.pL2CA_DataInd_Cb = sdp_data_ind; sdp_cb.reg_info.pL2CA_Error_Cb = sdp_on_l2cap_error; + tL2CAP_ERTM_INFO ertm_info; + ertm_info.preferred_mode = L2CAP_FCR_BASIC_MODE; + +#if (L2CAP_CONFORMANCE_TESTING == TRUE) + ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE; +#endif + /* Now, register with L2CAP */ if (!stack::l2cap::get_interface().L2CA_RegisterWithSecurity(BT_PSM_SDP, sdp_cb.reg_info, - true /* enable_snoop */, nullptr, + true /* enable_snoop */, &ertm_info, SDP_MTU_SIZE, 0, BTM_SEC_NONE)) { log::error("SDP Registration failed"); } -- GitLab From 7560a5281fdfb5d83ef22a970ea1e9c508695d47 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Fri, 11 Oct 2024 05:32:42 +0000 Subject: [PATCH 279/875] Broadcast active device only when Audio Fwk update AudioDevices when HFP SCO Management is enabled, HFP will behavior similar as A2DP and LE Audio, in which only sends broadcast when Audio Fwk updates Audio Device Bug: 372328032 Bug: 315234036 Flag: com::android::bluetooth::flags::is_sco_managed_by_audio Test: atest HeadsetServiceTest Change-Id: I56e10c8829b7996d56dad47af39bb0e93878dc79 --- .../android/bluetooth/hfp/HeadsetService.java | 140 ++++++++++++++++-- .../bluetooth/hfp/HeadsetSystemInterface.java | 1 - 2 files changed, 125 insertions(+), 16 deletions(-) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index 7e89394ee36..a29b2c902df 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -40,6 +40,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; @@ -141,6 +142,7 @@ public class HeadsetService extends ProfileService { private final HeadsetSystemInterface mSystemInterface; private int mMaxHeadsetConnections = 1; + private BluetoothDevice mExposedActiveDevice; private BluetoothDevice mActiveDevice; private boolean mAudioRouteAllowed = true; // Indicates whether SCO audio needs to be forced to open regardless ANY OTHER restrictions @@ -155,6 +157,8 @@ public class HeadsetService extends ProfileService { // Timeout when voice recognition is started by remote device @VisibleForTesting static int sStartVrTimeoutMs = 5000; private ArrayList mPendingClccResponses = new ArrayList<>(); + private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback = + new AudioManagerAudioDeviceCallback(); private static HeadsetService sHeadsetService; @VisibleForTesting boolean mIsAptXSwbEnabled = false; @@ -208,7 +212,14 @@ public class HeadsetService extends ProfileService { mNativeInterface.init(mMaxHeadsetConnections + 1, isInbandRingingEnabled()); enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, mIsAptXSwbEnabled, mActiveDevice); - // Step 6: Setup broadcast receivers + // Step 6: Register Audio Device callback + if (Utils.isScoManagedByAudioEnabled()) { + mSystemInterface + .getAudioManager() + .registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); + } + + // Step 7: Setup broadcast receivers IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(Intent.ACTION_BATTERY_CHANGED); @@ -229,11 +240,20 @@ public class HeadsetService extends ProfileService { @Override public void stop() { Log.i(TAG, "stop()"); - // Step 6: Tear down broadcast receivers + // Step 7: Tear down broadcast receivers unregisterReceiver(mHeadsetReceiver); + + // Step 6: Unregister Audio Device Callback + if (Utils.isScoManagedByAudioEnabled()) { + mSystemInterface + .getAudioManager() + .unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); + } + synchronized (mStateMachines) { // Reset active device to null if (mActiveDevice != null) { + mExposedActiveDevice = null; mActiveDevice = null; broadcastActiveDevice(null); } @@ -1397,18 +1417,19 @@ public class HeadsetService extends ProfileService { } // Make sure the Audio Manager knows the previous active device is no longer active. + mActiveDevice = null; + mNativeInterface.setActiveDevice(null); if (Utils.isScoManagedByAudioEnabled()) { mSystemInterface - .getAudioManager() - .handleBluetoothActiveDeviceChanged( - null, - mActiveDevice, - BluetoothProfileConnectionInfo.createHfpInfo()); + .getAudioManager() + .handleBluetoothActiveDeviceChanged( + null, + mActiveDevice, + BluetoothProfileConnectionInfo.createHfpInfo()); + } else { + broadcastActiveDevice(null); } - mActiveDevice = null; - mNativeInterface.setActiveDevice(null); - broadcastActiveDevice(null); if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(null, true); } @@ -1480,8 +1501,9 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); + } else { + broadcastActiveDevice(mActiveDevice); } - broadcastActiveDevice(mActiveDevice); if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(device, true); } @@ -1494,12 +1516,10 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); - } - broadcastActiveDevice(mActiveDevice); - if (Utils.isScoManagedByAudioEnabled()) { // Audio Framework will handle audio transition return true; } + broadcastActiveDevice(mActiveDevice); int connectStatus = connectAudio(mActiveDevice); if (connectStatus != BluetoothStatusCodes.SUCCESS) { Log.e( @@ -1525,8 +1545,9 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); + } else { + broadcastActiveDevice(mActiveDevice); } - broadcastActiveDevice(mActiveDevice); if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(device, true); } @@ -2398,6 +2419,95 @@ public class HeadsetService extends ProfileService { Utils.getTempBroadcastOptions().toBundle()); } + /* Notifications of audio device connection/disconnection events. */ + private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { + @Override + public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { + if (mSystemInterface.getAudioManager() == null || mAdapterService == null) { + Log.e(TAG, "Callback called when A2dpService is stopped"); + return; + } + + synchronized (mStateMachines) { + for (AudioDeviceInfo deviceInfo : addedDevices) { + if (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { + continue; + } + + String address = deviceInfo.getAddress(); + if (address.equals("00:00:00:00:00:00")) { + continue; + } + + byte[] addressBytes = Utils.getBytesFromAddress(address); + BluetoothDevice device = mAdapterService.getDeviceFromByte(addressBytes); + + Log.d( + TAG, + " onAudioDevicesAdded: " + + device + + ", device type: " + + deviceInfo.getType()); + + /* Don't expose already exposed active device */ + if (device.equals(mExposedActiveDevice)) { + Log.d(TAG, " onAudioDevicesAdded: " + device + " is already exposed"); + return; + } + + if (!device.equals(mActiveDevice)) { + Log.e( + TAG, + "Added device does not match to the one activated here. (" + + device + + " != " + + mActiveDevice + + " / " + + mActiveDevice + + ")"); + continue; + } + + mExposedActiveDevice = device; + broadcastActiveDevice(device); + return; + } + } + } + + @Override + public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { + if (mSystemInterface.getAudioManager() == null || mAdapterService == null) { + Log.e(TAG, "Callback called when LeAudioService is stopped"); + return; + } + + synchronized (mStateMachines) { + for (AudioDeviceInfo deviceInfo : removedDevices) { + if (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { + continue; + } + + String address = deviceInfo.getAddress(); + if (address.equals("00:00:00:00:00:00")) { + continue; + } + + mExposedActiveDevice = null; + + Log.d( + TAG, + " onAudioDevicesRemoved: " + + address + + ", device type: " + + deviceInfo.getType() + + ", mActiveDevice: " + + mActiveDevice); + } + } + } + } + /** * Check whether it is OK to accept a headset connection from a remote device * diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java b/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java index b2ac928a44a..0fea05430e9 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java @@ -83,7 +83,6 @@ class HeadsetSystemInterface { * * @return audio manager for setting audio parameters */ - @VisibleForTesting public AudioManager getAudioManager() { return mAudioManager; } -- GitLab From eca2c8eae54c6ad43d8c43b4e4e07deef7005845 Mon Sep 17 00:00:00 2001 From: Pomai Ahlo Date: Fri, 11 Oct 2024 11:07:04 -0700 Subject: [PATCH 280/875] New Flag: allow_free_last_scn Create new flag declaration in aconfig Bug: 372923869 Bug: 315241296 Test: m com.android.btservices Flag: com::android::bluetooth::flags::allow_free_last_scn Change-Id: Ib1e1f1d4b19ac954f51eecf43e8dee3ed187694c --- flags/rfcomm.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/rfcomm.aconfig b/flags/rfcomm.aconfig index 6d3f804095f..d5c5f1ab05b 100644 --- a/flags/rfcomm.aconfig +++ b/flags/rfcomm.aconfig @@ -27,3 +27,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "allow_free_last_scn" + namespace: "bluetooth" + description: "Allow SCN 30 to be freed" + bug: "372923869" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From f4cbadecb92e4577fe58a69996489c3456072e01 Mon Sep 17 00:00:00 2001 From: Pomai Ahlo Date: Fri, 11 Oct 2024 11:37:06 -0700 Subject: [PATCH 281/875] Allow SCN 30 to be freed BTA_FreeSCN currently treats SCN 30 as invalid. It is valid and should be able to be freed. Bug: 372923869 Bug: 372922664 Test: atest BtaRfcommScnTest Flag: com::android::bluetooth::flags::allow_free_last_scn Change-Id: I2a1bdf439ae559ebdc7e24ab719636d205bfa09a --- system/bta/rfcomm/bta_rfcomm_scn.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/system/bta/rfcomm/bta_rfcomm_scn.cc b/system/bta/rfcomm/bta_rfcomm_scn.cc index 064d95aa2ba..0e4d729631d 100644 --- a/system/bta/rfcomm/bta_rfcomm_scn.cc +++ b/system/bta/rfcomm/bta_rfcomm_scn.cc @@ -19,6 +19,7 @@ #define LOG_TAG "bta" #include +#include #include @@ -64,7 +65,7 @@ uint8_t BTA_AllocateSCN(void) { return i + 1; // allocated scn is index + 1 } } - log::debug("Unable to allocate an scn"); + log::warn("Unable to allocate an scn"); return 0; /* No free ports */ } @@ -109,12 +110,21 @@ bool BTA_FreeSCN(uint8_t scn) { /* Since this isn't used by HFP, this function will only free valid SCNs * that aren't reserved for HFP, which is range [2, RFCOMM_MAX_SCN]. */ - if (scn < RFCOMM_MAX_SCN && scn > 1) { - bta_jv_cb.scn_in_use[scn - 1] = false; - log::debug("Freed SCN: {}", scn); - return true; + + if (com::android::bluetooth::flags::allow_free_last_scn()) { + if (scn <= RFCOMM_MAX_SCN && scn > 1) { + bta_jv_cb.scn_in_use[scn - 1] = false; + log::debug("Freed SCN: {}", scn); + return true; + } } else { - log::warn("Invalid SCN: {}", scn); - return false; /* Illegal SCN passed in */ + if (scn < RFCOMM_MAX_SCN && scn > 1) { + bta_jv_cb.scn_in_use[scn - 1] = false; + log::debug("Freed SCN: {}", scn); + return true; + } } + + log::warn("Invalid SCN: {}", scn); + return false; /* Illegal SCN passed in */ } -- GitLab From 3298309e32d22efa067742d8431c951a7e6def1b Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 11 Oct 2024 16:23:53 +0000 Subject: [PATCH 282/875] system/btif: Enforce -Wmissing-prototypes Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor refactor Change-Id: Id0e3cb0c02bdb3923217b70bd1cd1379979e5278 --- system/btif/include/btif_hearing_aid.h | 21 +++++++++++++++++++++ system/btif/include/btif_pan.h | 10 ++++------ system/btif/src/bluetooth.cc | 5 +---- system/btif/src/btif_core.cc | 4 +--- system/btif/src/btif_hearing_aid.cc | 5 ++--- system/btif/src/btif_pan.cc | 13 ++----------- system/include/hardware/bt_pan.h | 2 ++ 7 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 system/btif/include/btif_hearing_aid.h diff --git a/system/btif/include/btif_hearing_aid.h b/system/btif/include/btif_hearing_aid.h new file mode 100644 index 00000000000..09011fd5c7d --- /dev/null +++ b/system/btif/include/btif_hearing_aid.h @@ -0,0 +1,21 @@ +/* + * 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 "hardware/bt_hearing_aid.h" + +bluetooth::hearing_aid::HearingAidInterface* btif_hearing_aid_get_interface(); diff --git a/system/btif/include/btif_pan.h b/system/btif/include/btif_pan.h index dada5b36eb7..12a17bcde8a 100644 --- a/system/btif/include/btif_pan.h +++ b/system/btif/include/btif_pan.h @@ -24,13 +24,11 @@ * ******************************************************************************/ -#ifndef BTIF_PAN_H -#define BTIF_PAN_H +#pragma once -#include +#include "hardware/bluetooth.h" +#include "hardware/bt_pan.h" -btpan_interface_t* btif_pan_interface(); +const btpan_interface_t* btif_pan_get_interface(); void btif_pan_init(); void btif_pan_cleanup(); - -#endif diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 8438dee7601..815e29ff817 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -69,6 +69,7 @@ #include "btif/include/btif_debug_conn.h" #include "btif/include/btif_dm.h" #include "btif/include/btif_hd.h" +#include "btif/include/btif_hearing_aid.h" #include "btif/include/btif_hf.h" #include "btif/include/btif_hf_client.h" #include "btif/include/btif_hh.h" @@ -168,8 +169,6 @@ extern const btsock_interface_t* btif_sock_get_interface(); extern const bthh_interface_t* btif_hh_get_interface(); /* hid device profile */ extern const bthd_interface_t* btif_hd_get_interface(); -/*pan*/ -extern const btpan_interface_t* btif_pan_get_interface(); /* gatt */ extern const btgatt_interface_t* btif_gatt_get_interface(); /* avrc target */ @@ -178,8 +177,6 @@ extern const btrc_interface_t* btif_rc_get_interface(); extern const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(); /*SDP search client*/ extern const btsdp_interface_t* btif_sdp_get_interface(); -/*Hearing Aid client*/ -extern HearingAidInterface* btif_hearing_aid_get_interface(); /* Hearing Access client */ extern HasClientInterface* btif_has_client_get_interface(); /* LeAudio testi client */ diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index c6e277c3c14..c5a723d09b0 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -39,6 +39,7 @@ #include +#include "btif/include/btif_api.h" #include "btif/include/btif_common.h" #include "btif/include/btif_config.h" #include "btif/include/btif_dm.h" @@ -64,9 +65,6 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using base::PlatformThread; using bluetooth::Uuid; using bluetooth::common::MessageLoopThread; diff --git a/system/btif/src/btif_hearing_aid.cc b/system/btif/src/btif_hearing_aid.cc index 6c8a689c49a..21b134ebd19 100644 --- a/system/btif/src/btif_hearing_aid.cc +++ b/system/btif/src/btif_hearing_aid.cc @@ -18,6 +18,8 @@ /* Hearing Aid Profile Interface */ +#include "btif_hearing_aid.h" + #include #include #include @@ -29,9 +31,6 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using base::Bind; using base::Unretained; using bluetooth::hearing_aid::ConnectionState; diff --git a/system/btif/src/btif_pan.cc b/system/btif/src/btif_pan.cc index 527c6ae6836..53c7cdb94cc 100644 --- a/system/btif/src/btif_pan.cc +++ b/system/btif/src/btif_pan.cc @@ -27,6 +27,8 @@ #define LOG_TAG "bt_btif_pan" +#include "btif/include/btif_pan.h" + #include #include #include @@ -73,9 +75,6 @@ #define MIN(x, y) (((x) < (y)) ? (x) : (y)) -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; btpan_cb_t btpan_cb; @@ -535,14 +534,6 @@ btpan_conn_t* btpan_new_conn(int handle, const RawAddress& addr, tBTA_PAN_ROLE l return nullptr; } -void btpan_close_handle(btpan_conn_t* p) { - log::verbose("btpan_close_handle : close handle {}", p->handle); - p->handle = -1; - p->local_role = -1; - p->remote_role = -1; - memset(&p->peer, 0, 6); -} - static inline bool should_forward(tETH_HDR* hdr) { uint16_t proto = ntohs(hdr->h_proto); if (proto == ETH_P_IP || proto == ETH_P_ARP || proto == ETH_P_IPV6) { diff --git a/system/include/hardware/bt_pan.h b/system/include/hardware/bt_pan.h index 0b6b16bef3e..4eca93720e3 100644 --- a/system/include/hardware/bt_pan.h +++ b/system/include/hardware/bt_pan.h @@ -19,6 +19,8 @@ #include #include +#include "hardware/bluetooth.h" + #define BTPAN_ROLE_NONE 0 #define BTPAN_ROLE_PANNAP 1 #define BTPAN_ROLE_PANU 2 -- GitLab From 406fc4344c9a57972a0e0cd86a723260be61d21b Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 7 Oct 2024 22:57:51 -0700 Subject: [PATCH 283/875] Fwk: Update lint-baseline with current failures Bug: 289445022 Test: m Bluetooth Flag: Exempt lint only Change-Id: I2c9f5ab97abb2a5db26419f9e78c08ebfcbc98e7 --- framework/lint-baseline.xml | 673 +++++++----------------------------- 1 file changed, 122 insertions(+), 551 deletions(-) diff --git a/framework/lint-baseline.xml b/framework/lint-baseline.xml index b87c402f980..ba89c54e54e 100644 --- a/framework/lint-baseline.xml +++ b/framework/lint-baseline.xml @@ -1,94 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -113,79 +25,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - + message="Field `AUDIO_LOCATION_INVALID` is a flagged API and should be inside an `if (Flags.leaudioMonoLocationErrata())` check (or annotate the surrounding method `getAudioLocation` with `@FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA) to transfer requirement to caller`)" + errorLine1=" return AUDIO_LOCATION_INVALID;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothLeAudio.java" + line="1208" + column="16"/> - - - - @@ -272,7 +107,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -283,7 +118,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -294,30 +129,41 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + + errorLine1=" builder.setChannelSoundingParams(" + errorLine2=" ^"> + line="210" + column="25"/> + message="Field `CREATOR` is a flagged API and should be inside an `if (Flags.channelSounding())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING) to transfer requirement to caller`)" + errorLine1=" ChannelSoundingParams.CREATOR.createFromParcel(in));" + errorLine2=" ~~~~~~~"> + line="211" + column="55"/> @@ -338,7 +184,7 @@ errorLine2=" ^"> @@ -349,7 +195,7 @@ errorLine2=" ^"> @@ -360,7 +206,18 @@ errorLine2=" ^"> + + + + @@ -371,7 +228,7 @@ errorLine2=" ^"> @@ -382,7 +239,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -409,410 +266,124 @@ - - - - - - - - + id="WrongConstant" + message="Must be one of: BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_TIMEOUT, BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE, BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD, BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP, BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CREATE_SERVER_SOCKET, BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET, BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE" + errorLine1=" return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothAdapter.java" + line="3267" + column="16"/> + id="WrongConstant" + message="Must be one of: BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_TIMEOUT, BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE, BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD, BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP, BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CREATE_SERVER_SOCKET, BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET, BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE" + errorLine1=" return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothAdapter.java" + line="3298" + column="16"/> + id="WrongConstant" + message="Must be one of: BluetoothCodecConfig.CODEC_PRIORITY_DISABLED, BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT, BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST" + errorLine1=" 0," + errorLine2=" ~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="WrongConstant" + message="Must be one of: BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE, BluetoothGattCharacteristic.WRITE_TYPE_SIGNED" + errorLine1=" characteristic.getWriteType())" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="WrongConstant" + message="Flag not allowed here" + errorLine1=" return (mCapability >> 1) & 1;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothHearingAid.java" + line="106" + column="20"/> + id="WrongConstant" + message="Flag not allowed here" + errorLine1=" return mCapability & 1;" + errorLine2=" ~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothHearingAid.java" + line="123" + column="20"/> + id="WrongConstant" + message="Must be one of: BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR, BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO, BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY, BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY, BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL" + errorLine1=" return mBqrCommon.getQualityReportId();" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothQualityReport.java" + line="300" + column="16"/> + id="WrongConstant" + message="Must be one of: BluetoothQualityReport.QUALITY_REPORT_ID_MONITOR, BluetoothQualityReport.QUALITY_REPORT_ID_APPROACH_LSTO, BluetoothQualityReport.QUALITY_REPORT_ID_A2DP_CHOPPY, BluetoothQualityReport.QUALITY_REPORT_ID_SCO_CHOPPY, BluetoothQualityReport.QUALITY_REPORT_ID_CONN_FAIL" + errorLine1=" + qualityReportIdToString(getQualityReportId())" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothQualityReport.java" + line="1103" + column="55"/> + id="WrongConstant" + message="Must be one of: OobData.LE_DEVICE_ROLE_PERIPHERAL_ONLY, OobData.LE_DEVICE_ROLE_CENTRAL_ONLY, OobData.LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL, OobData.LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL" + errorLine1=" mLeDeviceRole = -1; // Satisfy final" + errorLine2=" ~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/OobData.java" + line="784" + column="25"/> + id="WrongConstant" + message="Must be one of: ScanRecord.DATA_TYPE_FLAGS, ScanRecord.DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL, ScanRecord.DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE, ScanRecord.DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL, ScanRecord.DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE, ScanRecord.DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL, ScanRecord.DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE, ScanRecord.DATA_TYPE_LOCAL_NAME_SHORT, ScanRecord.DATA_TYPE_LOCAL_NAME_COMPLETE, ScanRecord.DATA_TYPE_TX_POWER_LEVEL, ScanRecord.DATA_TYPE_CLASS_OF_DEVICE, ScanRecord.DATA_TYPE_SIMPLE_PAIRING_HASH_C, ScanRecord.DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R, ScanRecord.DATA_TYPE_DEVICE_ID, ScanRecord.DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS, ScanRecord.DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE, ScanRecord.DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT, ScanRecord.DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT, ScanRecord.DATA_TYPE_SERVICE_DATA_16_BIT, ScanRecord.DATA_TYPE_PUBLIC_TARGET_ADDRESS, ScanRecord.DATA_TYPE_RANDOM_TARGET_ADDRESS, ScanRecord.DATA_TYPE_APPEARANCE, ScanRecord.DATA_TYPE_ADVERTISING_INTERVAL, ScanRecord.DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS, ScanRecord.DATA_TYPE_LE_ROLE, ScanRecord.DATA_TYPE_SIMPLE_PAIRING_HASH_C_256, ScanRecord.DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256, ScanRecord.DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT, ScanRecord.DATA_TYPE_SERVICE_DATA_32_BIT, ScanRecord.DATA_TYPE_SERVICE_DATA_128_BIT, ScanRecord.DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE, ScanRecord.DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE, ScanRecord.DATA_TYPE_URI, ScanRecord.DATA_TYPE_INDOOR_POSITIONING, ScanRecord.DATA_TYPE_TRANSPORT_DISCOVERY_DATA, ScanRecord.DATA_TYPE_LE_SUPPORTED_FEATURES, ScanRecord.DATA_TYPE_CHANNEL_MAP_UPDATE_INDICATION, ScanRecord.DATA_TYPE_PB_ADV, ScanRecord.DATA_TYPE_MESH_MESSAGE, ScanRecord.DATA_TYPE_MESH_BEACON, ScanRecord.DATA_TYPE_BIG_INFO, ScanRecord.DATA_TYPE_BROADCAST_CODE, ScanRecord.DATA_TYPE_RESOLVABLE_SET_IDENTIFIER, ScanRecord.DATA_TYPE_ADVERTISING_INTERVAL_LONG, ScanRecord.DATA_TYPE_3D_INFORMATION_DATA, ScanRecord.DATA_TYPE_MANUFACTURER_SPECIFIC_DATA" + errorLine1=" return mAdvertisingDataType;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/framework/java/android/bluetooth/le/ScanFilter.java" + line="423" + column="16"/> + id="SupportAnnotationUsage" + message="This annotation does not apply for type double; expected int" + errorLine1=" public @DistanceMeasurementMethodId double getId() {" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + line="97" + column="12"/> -- GitLab From 58a0fb33012d36bd736ba625ead74b1dd8dcd66e Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 7 Oct 2024 23:01:39 -0700 Subject: [PATCH 284/875] Fwk: Lint fix SupportAnnotationUsage Bug: 289445022 Test: m Bluetooth Flag: Exempt lint only Change-Id: Ia20228451ad854cdde58809a44937531f211e4bc --- framework/Android.bp | 3 +++ .../bluetooth/le/DistanceMeasurementMethod.java | 2 +- framework/lint-baseline.xml | 11 ----------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/framework/Android.bp b/framework/Android.bp index 6ae67d0bb92..4c484d40d0f 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -92,6 +92,9 @@ java_sdk_library { "error_prone_android_framework", ], lint: { + error_checks: [ + "SupportAnnotationUsage", + ], strict_updatability_linting: true, baseline_filename: "lint-baseline.xml", }, diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java b/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java index 26cfc191ec2..12b1a940f10 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java @@ -94,7 +94,7 @@ public final class DistanceMeasurementMethod implements Parcelable { @FlaggedApi(Flags.FLAG_CHANNEL_SOUNDING_25Q2_APIS) @Deprecated @SystemApi - public @DistanceMeasurementMethodId double getId() { + public double getId() { return mId; } diff --git a/framework/lint-baseline.xml b/framework/lint-baseline.xml index ba89c54e54e..500f3f6284b 100644 --- a/framework/lint-baseline.xml +++ b/framework/lint-baseline.xml @@ -375,15 +375,4 @@ column="16"/> - - - - -- GitLab From 5e364b45329468e5b243bab81a0e49e0694016c0 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 11 Oct 2024 14:18:39 -0700 Subject: [PATCH 285/875] Fwk: Address most of AndroidLint WrongConstant Bug: 289445022 Test: m Bluetooth Flag: Exempt lint only Change-Id: I7834577f5be76a501b6129e76fdcf905831dff97 --- .../android/bluetooth/BluetoothAdapter.java | 99 ++++--------------- .../bluetooth/BluetoothCodecConfig.java | 2 +- .../BluetoothGattCharacteristic.java | 11 +-- .../bluetooth/BluetoothHearingAid.java | 9 +- .../bluetooth/BluetoothQualityReport.java | 6 +- framework/java/android/bluetooth/OobData.java | 3 +- .../java/android/bluetooth/le/ScanFilter.java | 7 +- .../java/android/bluetooth/le/ScanRecord.java | 1 + framework/lint-baseline.xml | 82 ++------------- 9 files changed, 44 insertions(+), 176 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 4acad674dd3..22b6251e7f2 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -267,6 +267,7 @@ public final class BluetoothAdapter { value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_TIMEOUT, + BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE, BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD, BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP, @@ -1816,11 +1817,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean clearBluetooth() { mServiceLock.readLock().lock(); try { @@ -1848,11 +1845,7 @@ public final class BluetoothAdapter { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean factoryReset() { return clearBluetooth(); } @@ -1989,13 +1982,8 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothScanPermission - @RequiresPermission( - allOf = { - BLUETOOTH_SCAN, - BLUETOOTH_PRIVILEGED, - }) - @ScanModeStatusCode - public int setScanMode(@ScanMode int mode) { + @RequiresPermission(allOf = {BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED}) + public @ScanModeStatusCode int setScanMode(@ScanMode int mode) { if (getState() != STATE_ON) { return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; } @@ -2059,13 +2047,8 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothScanPermission - @RequiresPermission( - allOf = { - BLUETOOTH_SCAN, - BLUETOOTH_PRIVILEGED, - }) - @ScanModeStatusCode - public int setDiscoverableTimeout(@NonNull Duration timeout) { + @RequiresPermission(allOf = {BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED}) + public @ScanModeStatusCode int setDiscoverableTimeout(@NonNull Duration timeout) { if (getState() != STATE_ON) { return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; } @@ -2096,11 +2079,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis() { mServiceLock.readLock().lock(); try { @@ -2252,12 +2231,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - MODIFY_PHONE_STATE, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED, MODIFY_PHONE_STATE}) public boolean removeActiveDevice(@ActiveDeviceUse int profiles) { if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL @@ -2300,12 +2274,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - MODIFY_PHONE_STATE, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED, MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull BluetoothDevice device, @ActiveDeviceUse int profiles) { if (device == null) { Log.e(TAG, "setActiveDevice: Null device passed as parameter"); @@ -2844,11 +2813,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void requestControllerActivityEnergyInfo( @NonNull @CallbackExecutor Executor executor, @NonNull OnBluetoothActivityEnergyInfoCallback callback) { @@ -2882,11 +2847,7 @@ public final class BluetoothAdapter { @SystemApi @RequiresLegacyBluetoothAdminPermission @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull List getMostRecentlyConnectedDevices() { if (getState() != STATE_ON) { return Collections.emptyList(); @@ -2951,11 +2912,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull List getSupportedProfiles() { final ArrayList supportedProfiles = new ArrayList(); @@ -3246,8 +3203,7 @@ public final class BluetoothAdapter { @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) - @RfcommListenerResult - public int startRfcommServer( + public @RfcommListenerResult int startRfcommServer( @NonNull String name, @NonNull UUID uuid, @NonNull PendingIntent pendingIntent) { if (!pendingIntent.isImmutable()) { throw new IllegalArgumentException("The provided PendingIntent is not immutable"); @@ -3278,13 +3234,8 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) - @RfcommListenerResult - public int stopRfcommServer(@NonNull UUID uuid) { + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) + public @RfcommListenerResult int stopRfcommServer(@NonNull UUID uuid) { mServiceLock.readLock().lock(); try { if (mService != null) { @@ -3314,11 +3265,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull BluetoothSocket retrieveConnectedRfcommSocket(@NonNull UUID uuid) { IncomingRfcommSocketInfo socketInfo = null; @@ -4053,11 +4000,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void generateLocalOobData( @Transport int transport, @NonNull @CallbackExecutor Executor executor, @@ -5508,11 +5451,7 @@ public final class BluetoothAdapter { */ @SystemApi @RequiresBluetoothScanPermission - @RequiresPermission( - allOf = { - BLUETOOTH_SCAN, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED}) @GetOffloadedTransportDiscoveryDataScanSupportedReturnValues public int getOffloadedTransportDiscoveryDataScanSupported() { if (!getLeAccess()) { diff --git a/framework/java/android/bluetooth/BluetoothCodecConfig.java b/framework/java/android/bluetooth/BluetoothCodecConfig.java index 8e9ed78ef13..4e3a909b558 100644 --- a/framework/java/android/bluetooth/BluetoothCodecConfig.java +++ b/framework/java/android/bluetooth/BluetoothCodecConfig.java @@ -780,7 +780,7 @@ public final class BluetoothCodecConfig implements Parcelable { return sameAudioFeedingParameters( new BluetoothCodecConfig( mCodecType, /* priority */ - 0, + CODEC_PRIORITY_DEFAULT, sampleRate, bitsPerSample, channelMode, diff --git a/framework/java/android/bluetooth/BluetoothGattCharacteristic.java b/framework/java/android/bluetooth/BluetoothGattCharacteristic.java index 7810b966b65..a6b4b96c913 100644 --- a/framework/java/android/bluetooth/BluetoothGattCharacteristic.java +++ b/framework/java/android/bluetooth/BluetoothGattCharacteristic.java @@ -163,11 +163,11 @@ public class BluetoothGattCharacteristic implements Parcelable { protected int mKeySize = 16; /** - * Write type for this characteristic. See WRITE_TYPE_* constants. + * Write type for this characteristic. * * @hide */ - protected int mWriteType; + protected @WriteType int mWriteType; /** * Back-reference to the service this characteristic belongs to. @@ -392,7 +392,7 @@ public class BluetoothGattCharacteristic implements Parcelable { * * @return Write type for this characteristic */ - public int getWriteType() { + public @WriteType int getWriteType() { return mWriteType; } @@ -403,10 +403,9 @@ public class BluetoothGattCharacteristic implements Parcelable { * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} function write * this characteristic. * - * @param writeType The write type to for this characteristic. Can be one of: {@link - * #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}. + * @param writeType The write type to for this characteristic. */ - public void setWriteType(int writeType) { + public void setWriteType(@WriteType int writeType) { mWriteType = writeType; } diff --git a/framework/java/android/bluetooth/BluetoothHearingAid.java b/framework/java/android/bluetooth/BluetoothHearingAid.java index 476dc1e98d8..110e6f8caaf 100644 --- a/framework/java/android/bluetooth/BluetoothHearingAid.java +++ b/framework/java/android/bluetooth/BluetoothHearingAid.java @@ -100,8 +100,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { * @hide */ @SystemApi - @DeviceMode - public int getDeviceMode() { + public @DeviceMode int getDeviceMode() { if (VDBG) Log.v(TAG, "getDeviceMode()"); return (mCapability >> 1) & 1; } @@ -117,8 +116,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { * @hide */ @SystemApi - @DeviceSide - public int getDeviceSide() { + public @DeviceSide int getDeviceSide() { if (VDBG) Log.v(TAG, "getDeviceSide()"); return mCapability & 1; } @@ -693,8 +691,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(BLUETOOTH_CONNECT) - @DeviceSide - public int getDeviceSide(@NonNull BluetoothDevice device) { + public @DeviceSide int getDeviceSide(@NonNull BluetoothDevice device) { if (VDBG) Log.v(TAG, "getDeviceSide(" + device + ")"); verifyDeviceNotNull(device, "getDeviceSide"); final IBluetoothHearingAid service = getService(); diff --git a/framework/java/android/bluetooth/BluetoothQualityReport.java b/framework/java/android/bluetooth/BluetoothQualityReport.java index b6bc989c40b..c1b38de3304 100644 --- a/framework/java/android/bluetooth/BluetoothQualityReport.java +++ b/framework/java/android/bluetooth/BluetoothQualityReport.java @@ -295,8 +295,7 @@ public final class BluetoothQualityReport implements Parcelable { * @hide */ @SystemApi - @QualityReportId - public int getQualityReportId() { + public @QualityReportId int getQualityReportId() { return mBqrCommon.getQualityReportId(); } @@ -661,7 +660,7 @@ public final class BluetoothQualityReport implements Parcelable { private static final String TAG = BluetoothQualityReport.TAG + ".BqrCommon"; static final int BQR_COMMON_LEN = 55; - private int mQualityReportId; + private @QualityReportId int mQualityReportId; private int mPacketType; private int mConnectionHandle; private int mConnectionRole; @@ -749,6 +748,7 @@ public final class BluetoothQualityReport implements Parcelable { mCalFailedItemCount = in.readInt(); } + @QualityReportId int getQualityReportId() { return mQualityReportId; } diff --git a/framework/java/android/bluetooth/OobData.java b/framework/java/android/bluetooth/OobData.java index faf9407f16e..a90516d6164 100644 --- a/framework/java/android/bluetooth/OobData.java +++ b/framework/java/android/bluetooth/OobData.java @@ -768,8 +768,7 @@ public final class OobData implements Parcelable { */ @NonNull @SystemApi - @LeRole - public int getLeDeviceRole() { + public @LeRole int getLeDeviceRole() { return mLeDeviceRole; } diff --git a/framework/java/android/bluetooth/le/ScanFilter.java b/framework/java/android/bluetooth/le/ScanFilter.java index 8571b7e0f55..d78fa19823f 100644 --- a/framework/java/android/bluetooth/le/ScanFilter.java +++ b/framework/java/android/bluetooth/le/ScanFilter.java @@ -79,7 +79,7 @@ public final class ScanFilter implements Parcelable { @Nullable private final byte[] mManufacturerData; @Nullable private final byte[] mManufacturerDataMask; - private int mAdvertisingDataType = ScanRecord.DATA_TYPE_NONE; + private @AdvertisingDataType int mAdvertisingDataType = ScanRecord.DATA_TYPE_NONE; @Nullable private final byte[] mAdvertisingData; @Nullable private final byte[] mAdvertisingDataMask; @@ -103,7 +103,7 @@ public final class ScanFilter implements Parcelable { byte[] manufacturerDataMask, @AddressType int addressType, @Nullable byte[] irk, - int advertisingDataType, + @AdvertisingDataType int advertisingDataType, @Nullable byte[] advertisingData, @Nullable byte[] advertisingDataMask, @Nullable TransportBlockFilter transportBlockFilter) { @@ -418,8 +418,7 @@ public final class ScanFilter implements Parcelable { * if the type is not set. The values of advertising data type are defined in the Bluetooth * Generic Access Profile (https://www.bluetooth.com/specifications/assigned-numbers/) */ - @AdvertisingDataType - public int getAdvertisingDataType() { + public @AdvertisingDataType int getAdvertisingDataType() { return mAdvertisingDataType; } diff --git a/framework/java/android/bluetooth/le/ScanRecord.java b/framework/java/android/bluetooth/le/ScanRecord.java index 4cafc468ab1..57bd7445c7f 100644 --- a/framework/java/android/bluetooth/le/ScanRecord.java +++ b/framework/java/android/bluetooth/le/ScanRecord.java @@ -50,6 +50,7 @@ public final class ScanRecord { @IntDef( prefix = "DATA_TYPE_", value = { + DATA_TYPE_NONE, DATA_TYPE_FLAGS, DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL, DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE, diff --git a/framework/lint-baseline.xml b/framework/lint-baseline.xml index 500f3f6284b..e0cbba3180a 100644 --- a/framework/lint-baseline.xml +++ b/framework/lint-baseline.xml @@ -265,50 +265,6 @@ column="44"/> - - - - - - - - - - - - - - - - @@ -327,30 +283,19 @@ errorLine2=" ~~~~~~~~~~~~~~~"> - - - - + message="Flag not allowed here" + errorLine1=" mQualityReportId = bqrBuf.get() & 0xFF;" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> + line="694" + column="32"/> - - - - -- GitLab From 7f91529ea04be125885cbea165f591cc10f80609 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 11 Oct 2024 14:22:10 -0700 Subject: [PATCH 286/875] Fwk Lint: enforce as error Now that the baseline is up to date we can enforce some as error to prevent spreading the disease. Bug: 289445022 Test: m Bluetooth Flag: Exempt lint Change-Id: If552b9f17906de8a198bcfd0750d70157684c46d --- framework/Android.bp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/framework/Android.bp b/framework/Android.bp index 4c484d40d0f..9fa8d9a1608 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -93,7 +93,40 @@ java_sdk_library { ], lint: { error_checks: [ + "Autofill", + "DefaultLocale", + "DuplicateDefinition", + "ExtraText", + "ExtraTranslation", + "FlaggedApi", + "GestureBackNavigation", + "GuardedLogInvocation", + "HandlerLeak", + "InflateParams", + "LabelFor", + "MissingClass", + "MonochromeLauncherIcon", + "NewApi", + "ObsoleteSdkInt", + "Recycle", + "RtlHardcoded", + "RtlSymmetry", + "ScrollViewSize", + "SetTextI18n", + "SimpleDateFormat", + "StaticFieldLeak", + "StringFormatCount", + "StringFormatInvalid", "SupportAnnotationUsage", + "TextFields", + "TypographyEllipsis", + "UseSparseArrays", + "UseValueOf", + "VectorPath", + "VisibleForTests", + "Wakelock", + "WakelockTimeout", + "WrongConstant", ], strict_updatability_linting: true, baseline_filename: "lint-baseline.xml", -- GitLab From ca6865b07cb0fa9fc63a80b7ed7de5de810c9eb7 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 11 Oct 2024 21:34:47 +0000 Subject: [PATCH 287/875] system/btif: Enforce -Wmissing-prototypes Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor refactor Change-Id: Iaf191d9bdad6f25cef204d0671dc2530ac8231bd --- system/bta/include/bta_dm_api.h | 7 +++---- system/btif/include/btif_bqr.h | 11 +++-------- system/btif/include/btif_hd.h | 2 ++ system/btif/include/btif_hh.h | 7 +++++++ system/btif/src/bluetooth.cc | 6 ------ system/btif/src/btif_bqr.cc | 18 +++++++++++------- system/btif/src/btif_hd.cc | 8 ++------ system/btif/src/btif_hh.cc | 7 ++----- system/btif/test/btif_core_test.cc | 6 +----- system/btif/test/btif_hh_test.cc | 4 ---- 10 files changed, 31 insertions(+), 45 deletions(-) diff --git a/system/bta/include/bta_dm_api.h b/system/bta/include/bta_dm_api.h index 1ad4fd6ea65..2c911774824 100644 --- a/system/bta/include/bta_dm_api.h +++ b/system/bta/include/bta_dm_api.h @@ -21,12 +21,11 @@ * This is the interface file for device mananger functions. * ******************************************************************************/ -#ifndef BTA_DM_API_H -#define BTA_DM_API_H + +#pragma once #include "types/raw_address.h" // Brings connection to active mode void bta_dm_pm_active(const RawAddress& peer_addr); - -#endif /* BTA_DM_API_H */ +bool bta_dm_check_if_only_hd_connected(const RawAddress& peer_addr); diff --git a/system/btif/include/btif_bqr.h b/system/btif/include/btif_bqr.h index db575d17fab..71105ef9032 100644 --- a/system/btif/include/btif_bqr.h +++ b/system/btif/include/btif_bqr.h @@ -167,14 +167,6 @@ static constexpr const char* kpBtSchedulingTraceLastLogPath = // for sco choppy. Value format is a2dp_choppy_threshold,sco_choppy_threshold static constexpr const char* kpPropertyChoppyThreshold = "persist.bluetooth.bqr.choppy_threshold"; -// File Descriptor of LMP/LL message trace log -static int LmpLlMessageTraceLogFd = INVALID_FD; -// File Descriptor of Bluetooth Multi-profile/Coex scheduling trace log -static int BtSchedulingTraceLogFd = INVALID_FD; -// Counter of LMP/LL message trace -static uint16_t LmpLlMessageTraceCounter = 0; -// Counter of Bluetooth Multi-profile/Coex scheduling trace -static uint16_t BtSchedulingTraceCounter = 0; // The version supports ISO packets start from v1.01(257) static constexpr uint16_t kBqrIsoVersion = 0x101; // The version supports vendor quality and trace log starting v1.02(258) @@ -402,6 +394,9 @@ void DisableBtQualityReport(); // @param fd The file descriptor to use for dumping information. void DebugDump(int fd); +// Configure the file descriptor for the LMP/LL message trace log. +void SetLmpLlMessageTraceLogFd(int fd); + } // namespace bqr } // namespace bluetooth diff --git a/system/btif/include/btif_hd.h b/system/btif/include/btif_hd.h index 3eccd849bac..055811800c5 100644 --- a/system/btif/include/btif_hd.h +++ b/system/btif/include/btif_hd.h @@ -40,6 +40,8 @@ typedef struct { extern btif_hd_cb_t btif_hd_cb; +const bthd_interface_t* btif_hd_get_interface(); +bt_status_t btif_hd_execute_service(bool b_enable); void btif_hd_remove_device(RawAddress bd_addr); void btif_hd_service_registration(); diff --git a/system/btif/include/btif_hh.h b/system/btif/include/btif_hh.h index 2ff60d74da9..a0774c5376c 100644 --- a/system/btif/include/btif_hh.h +++ b/system/btif/include/btif_hh.h @@ -142,10 +142,13 @@ typedef struct { extern btif_hh_cb_t btif_hh_cb; +const bthh_interface_t* btif_hh_get_interface(); +bt_status_t btif_hh_execute_service(bool b_enable); btif_hh_device_t* btif_hh_find_connected_dev_by_handle(uint8_t handle); btif_hh_device_t* btif_hh_find_dev_by_handle(uint8_t handle); btif_hh_device_t* btif_hh_find_empty_dev(void); bt_status_t btif_hh_virtual_unplug(const tAclLinkSpec& link_spec); +bt_status_t btif_hh_connect(const tAclLinkSpec& link_spec); void btif_hh_remove_device(const tAclLinkSpec& link_spec); void btif_hh_setreport(btif_hh_uhid_t* p_uhid, bthh_report_type_t r_type, uint16_t size, uint8_t* report); @@ -166,6 +169,10 @@ void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev, const char* dev_name, uint void DumpsysHid(int fd); +namespace bluetooth::legacy::testing { +void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data); +} // namespace bluetooth::legacy::testing + namespace fmt { template <> struct formatter : enum_formatter {}; diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 815e29ff817..786c7e11ed5 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -165,10 +165,6 @@ bool is_local_device_atv = false; /*rfc l2cap*/ extern const btsock_interface_t* btif_sock_get_interface(); -/* hid host profile */ -extern const bthh_interface_t* btif_hh_get_interface(); -/* hid device profile */ -extern const bthd_interface_t* btif_hd_get_interface(); /* gatt */ extern const btgatt_interface_t* btif_gatt_get_interface(); /* avrc target */ @@ -189,8 +185,6 @@ extern CsisClientInterface* btif_csis_client_get_interface(); extern VolumeControlInterface* btif_volume_control_get_interface(); bt_status_t btif_av_sink_execute_service(bool b_enable); -bt_status_t btif_hh_execute_service(bool b_enable); -bt_status_t btif_hd_execute_service(bool b_enable); extern void gatt_tcb_dump(int fd); extern void bta_gatt_client_dump(int fd); diff --git a/system/btif/src/btif_bqr.cc b/system/btif/src/btif_bqr.cc index 5d65920f47e..765e7a73841 100644 --- a/system/btif/src/btif_bqr.cc +++ b/system/btif/src/btif_bqr.cc @@ -45,9 +45,6 @@ #include "stack/include/btm_client_interface.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace bluetooth { namespace bqr { @@ -59,6 +56,15 @@ static LeakyBondedQueue kpBqrEventQueue{kBqrEventQueueSize}; static uint16_t vendor_cap_supported_version; +// File Descriptor of LMP/LL message trace log +static int LmpLlMessageTraceLogFd = INVALID_FD; +// File Descriptor of Bluetooth Multi-profile/Coex scheduling trace log +static int BtSchedulingTraceLogFd = INVALID_FD; +// Counter of LMP/LL message trace +static uint16_t LmpLlMessageTraceCounter = 0; +// Counter of Bluetooth Multi-profile/Coex scheduling trace +static uint16_t BtSchedulingTraceCounter = 0; + class BluetoothQualityReportInterfaceImpl; std::unique_ptr bluetoothQualityReportInstance; @@ -508,7 +514,7 @@ static void BqrVscCompleteCallback(hci::CommandCompleteView complete) { ConfigureBqrCmpl(current_quality_event_mask); } -void ConfigBqrA2dpScoThreshold() { +static void ConfigBqrA2dpScoThreshold() { uint8_t sub_opcode = 0x16; uint16_t a2dp_choppy_threshold = 0; uint16_t sco_choppy_threshold = 0; @@ -926,9 +932,7 @@ void unregister_vse() { hci::VseSubeventCode::BQR_EVENT); } -namespace testing { -void set_lmp_trace_log_fd(int fd) { LmpLlMessageTraceLogFd = fd; } -} // namespace testing +void SetLmpLlMessageTraceLogFd(int fd) { LmpLlMessageTraceLogFd = fd; } } // namespace bqr } // namespace bluetooth diff --git a/system/btif/src/btif_hd.cc b/system/btif/src/btif_hd.cc index 1ddc10fc509..149b9aee2a2 100644 --- a/system/btif/src/btif_hd.cc +++ b/system/btif/src/btif_hd.cc @@ -33,11 +33,13 @@ #include +#include "bta/include/bta_dm_api.h" #include "bta/include/bta_hd_api.h" #include "bta/sys/bta_sys.h" #include "bta_sec_api.h" #include "btif/include/btif_common.h" #include "btif/include/btif_dm.h" +#include "btif/include/btif_hh.h" #include "btif/include/btif_profile_storage.h" #include "btif/include/btif_util.h" #include "include/hardware/bt_hd.h" @@ -56,14 +58,8 @@ #define COD_HID_COMBO 0x05C0 #define COD_HID_MAJOR 0x0500 -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; -bool bta_dm_check_if_only_hd_connected(const RawAddress& peer_addr); -void btif_hh_service_registration(bool enable); - /* HD request events */ typedef enum { BTIF_HD_DUMMY_REQ_EVT = 0 } btif_hd_req_evt_t; diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index 49d13d28d0e..629092bb3b8 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -68,9 +68,6 @@ #define LOGITECH_KB_MX5500_VENDOR_ID 0x046D #define LOGITECH_KB_MX5500_PRODUCT_ID 0xB30B -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; static int btif_hh_keylockstates = 0; // The current key state of each key @@ -301,7 +298,7 @@ static void sync_lockstate_on_connect(btif_hh_device_t* p_dev, tBTA_HH_DEV_DSCP_ * * Returns Added device entry ******************************************************************************/ -btif_hh_added_device_t* btif_hh_find_added_dev(const tAclLinkSpec& link_spec) { +static btif_hh_added_device_t* btif_hh_find_added_dev(const tAclLinkSpec& link_spec) { for (int i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) { btif_hh_added_device_t* added_dev = &btif_hh_cb.added_devices[i]; if (added_dev->link_spec == link_spec) { @@ -1123,7 +1120,7 @@ bt_status_t btif_hh_connect(const tAclLinkSpec& link_spec) { * Returns void * ******************************************************************************/ -void btif_hh_disconnect(const tAclLinkSpec& link_spec) { +static void btif_hh_disconnect(const tAclLinkSpec& link_spec) { btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_link_spec(link_spec); if (p_dev == nullptr) { log::warn("Unable to disconnect unknown HID device:{}", link_spec); diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc index bfd49059195..3f950d0bf93 100644 --- a/system/btif/test/btif_core_test.cc +++ b/system/btif/test/btif_core_test.cc @@ -888,10 +888,6 @@ TEST_F(BtifCoreVseWithSocketTest, debug_dump_empty) { EXPECT_EQ(std::future_status::ready, reading_done.wait_for(std::chrono::seconds(1))); } -namespace bluetooth::bqr::testing { -void set_lmp_trace_log_fd(int fd); -} - TEST_F(BtifCoreVseWithSocketTest, send_lmp_ll_msg) { auto payload = std::make_unique(); payload->AddOctets({'d', 'a', 't', 'a'}); @@ -904,7 +900,7 @@ TEST_F(BtifCoreVseWithSocketTest, send_lmp_ll_msg) { auto reading_done = reading_promise->get_future(); static int write_fd = write_fd_; - do_in_main_thread(BindOnce([]() { bluetooth::bqr::testing::set_lmp_trace_log_fd(write_fd); })); + do_in_main_thread(BindOnce([]() { bluetooth::bqr::SetLmpLlMessageTraceLogFd(write_fd); })); vse_callback_(view); do_in_main_thread(BindOnce( diff --git a/system/btif/test/btif_hh_test.cc b/system/btif/test/btif_hh_test.cc index a4306b6f103..80cbf8df1a3 100644 --- a/system/btif/test/btif_hh_test.cc +++ b/system/btif/test/btif_hh_test.cc @@ -45,10 +45,6 @@ module_t rust_module; const tBTA_AG_RES_DATA tBTA_AG_RES_DATA::kEmpty = {}; -const bthh_interface_t* btif_hh_get_interface(); -bt_status_t btif_hh_connect(const tAclLinkSpec& link_spec); -bt_status_t btif_hh_virtual_unplug(const tAclLinkSpec& link_spec); - namespace bluetooth { namespace legacy { namespace testing { -- GitLab From e4b3fa39ca9b236048c69701f778f598f44a66c9 Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Fri, 11 Oct 2024 22:18:29 +0000 Subject: [PATCH 288/875] asrc: Fix logging on negative deviation Bug: 312273987 Flag: EXEMPT, log fix Test: m com.android.btservices Change-Id: I7cd38679d0276fda26776f7c6ab742754385cfc8 --- system/audio/asrc/asrc_resampler.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/audio/asrc/asrc_resampler.cc b/system/audio/asrc/asrc_resampler.cc index fcb3a78027f..81d46f1121d 100644 --- a/system/audio/asrc/asrc_resampler.cc +++ b/system/audio/asrc/asrc_resampler.cc @@ -162,8 +162,8 @@ class SourceAudioHalAsrc::ClockRecovery : public bluetooth::hal::ReadClockHandle log::info( "Deviation: {:6} us ({:3.0f} ppm) | Output Fs: {:5.2f} Hz drift: {:2} " "us", - state.stream_time - state.local_time, state.butter_drift, output_stats.sample_rate, - output_stats.drift_us); + static_cast(state.stream_time - state.local_time), state.butter_drift, + output_stats.sample_rate, output_stats.drift_us); } public: -- GitLab From e49a1e988c6baf476e11a4ba205c31b9aa3e05c0 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 11 Oct 2024 17:41:57 +0000 Subject: [PATCH 289/875] Refactor - Use assigned config_id in CS commands Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 368617974 Test: m com.android.btservices Change-Id: Ic848ba7583f4671c71f82bdd6e684b03afde15ee --- system/gd/hci/distance_measurement_manager.cc | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index af17402bea4..1e7f75a55ee 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -68,6 +68,7 @@ static constexpr uint8_t kTxPwrDelta = 0x00; static constexpr uint8_t kProcedureDataBufferSize = 0x10; // Buffer size of Procedure data static constexpr uint16_t kMtuForRasData = 507; // 512 - 5 static constexpr uint16_t kRangingCounterMask = 0x0FFF; +static constexpr uint8_t kInvalidConfigId = 0xFF; struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { struct CsProcedureData { @@ -154,7 +155,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { CsSubModeType sub_mode_type; CsRttType rtt_type; bool remote_support_phase_based_ranging = false; - uint8_t config_id = 0; + uint8_t config_id = kInvalidConfigId; uint8_t selected_tx_power = 0; std::vector procedure_data_list; uint16_t interval_ms; @@ -313,6 +314,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { cs_trackers_[connection_handle].measurement_ongoing = true; cs_trackers_[connection_handle].waiting_for_start_callback = true; cs_trackers_[connection_handle].local_hci_role = local_hci_role; + cs_trackers_[connection_handle].config_id = kConfigId; } void start_distance_measurement_with_cs(const Address& cs_remote_address, @@ -337,7 +339,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (!cs_trackers_[connection_handle].config_set) { // TODO: compare the config set with the requested config. // The config may be override by reflector. consider to use different tracker for reflector - send_le_cs_create_config(connection_handle); + send_le_cs_create_config(connection_handle, cs_trackers_[connection_handle].config_id); return; } log::info("enable cs procedure regularly with interval: {} ms", @@ -573,14 +575,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handler_->BindOnceOn(this, &impl::on_cs_set_default_settings_complete)); } - void send_le_cs_create_config(uint16_t connection_handle) { + void send_le_cs_create_config(uint16_t connection_handle, uint8_t config_id) { auto channel_vector = common::FromHexString("1FFFFFFFFFFFFC7FFFFC"); // use all 72 Channel std::array channel_map; std::copy(channel_vector->begin(), channel_vector->end(), channel_map.begin()); std::reverse(channel_map.begin(), channel_map.end()); hci_layer_->EnqueueCommand( LeCsCreateConfigBuilder::Create( - connection_handle, kConfigId, CsCreateContext::BOTH_LOCAL_AND_REMOTE_CONTROLLER, + connection_handle, config_id, CsCreateContext::BOTH_LOCAL_AND_REMOTE_CONTROLLER, CsMainModeType::MODE_2, CsSubModeType::UNUSED, kMinMainModeSteps, kMaxMainModeSteps, kMainModeRepetition, kMode0Steps, CsRole::INITIATOR, CsConfigRttType::RTT_WITH_128_BIT_RANDOM_SEQUENCE, CsSyncPhy::LE_1M_PHY, @@ -589,11 +591,11 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); } - void send_le_cs_set_procedure_parameters(uint16_t connection_handle) { + void send_le_cs_set_procedure_parameters(uint16_t connection_handle, uint8_t config_id) { CsPreferredPeerAntenna preferred_peer_antenna; hci_layer_->EnqueueCommand( LeCsSetProcedureParametersBuilder::Create( - connection_handle, kConfigId, kMaxProcedureLen, kMinProcedureInterval, + connection_handle, config_id, kMaxProcedureLen, kMinProcedureInterval, kMaxProcedureInterval, kMaxProcedureCount, kMinSubeventLen, kMaxSubeventLen, kToneAntennaConfigSelection, CsPhy::LE_1M_PHY, kTxPwrDelta, preferred_peer_antenna, CsSnrControl::NOT_APPLIED, CsSnrControl::NOT_APPLIED), @@ -634,7 +636,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } hci_layer_->EnqueueCommand( - LeCsProcedureEnableBuilder::Create(connection_handle, kConfigId, enable), + LeCsProcedureEnableBuilder::Create(connection_handle, + cs_trackers_[connection_handle].config_id, enable), handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); } @@ -729,7 +732,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { cs_trackers_[connection_handle].setup_complete = true; log::info("Setup phase complete, connection_handle: {}, address: {}", connection_handle, cs_trackers_[connection_handle].address); - send_le_cs_create_config(connection_handle); + send_le_cs_create_config(connection_handle, cs_trackers_[connection_handle].config_id); } } @@ -760,7 +763,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (cs_trackers_[connection_handle].local_start) { cs_trackers_[connection_handle].config_set = true; - send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle()); + send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), + cs_trackers_[connection_handle].config_id); } } -- GitLab From 76b0f18ffe8e5af585d20c5455666337bd31d3b9 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Sat, 12 Oct 2024 00:42:29 +0000 Subject: [PATCH 290/875] system/bta/{ag,ar}: Enforce -Wmissing-prototypes Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor refactor Change-Id: Ie54164aef2956484240ccf8df19e2f48acd83b54 --- system/bta/ag/bta_ag_at.cc | 5 +--- system/bta/ag/bta_ag_rfc.cc | 57 ++++++++++++++++++------------------- system/bta/ar/bta_ar.cc | 4 +-- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/system/bta/ag/bta_ag_at.cc b/system/bta/ag/bta_ag_at.cc index 36d57a70f9b..2a7a24022d8 100644 --- a/system/bta/ag/bta_ag_at.cc +++ b/system/bta/ag/bta_ag_at.cc @@ -37,9 +37,6 @@ #include "os/log.h" #include "osi/include/allocator.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -90,7 +87,7 @@ void bta_ag_at_reinit(tBTA_AG_AT_CB* p_cb) { * Returns void * *****************************************************************************/ -void bta_ag_process_at(tBTA_AG_AT_CB* p_cb, char* p_end) { +static void bta_ag_process_at(tBTA_AG_AT_CB* p_cb, char* p_end) { uint16_t idx; uint8_t arg_type; char* p_arg; diff --git a/system/bta/ag/bta_ag_rfc.cc b/system/bta/ag/bta_ag_rfc.cc index 12ecc304c36..bdfbfbf5933 100644 --- a/system/bta/ag/bta_ag_rfc.cc +++ b/system/bta/ag/bta_ag_rfc.cc @@ -36,33 +36,30 @@ /* Event mask for RfCOMM port callback */ #define BTA_AG_PORT_EV_MASK PORT_EV_RXCHAR -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /* each scb has its own rfcomm callbacks */ -void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle); -void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle); -void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle); -void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle); -void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle); -void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle); -void bta_ag_mgmt_cback_1(const tPORT_RESULT code, uint16_t port_handle); -void bta_ag_mgmt_cback_2(const tPORT_RESULT code, uint16_t port_handle); -void bta_ag_mgmt_cback_3(const tPORT_RESULT code, uint16_t port_handle); -void bta_ag_mgmt_cback_4(const tPORT_RESULT code, uint16_t port_handle); -void bta_ag_mgmt_cback_5(const tPORT_RESULT code, uint16_t port_handle); -void bta_ag_mgmt_cback_6(const tPORT_RESULT code, uint16_t port_handle); +static void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle); +static void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle); +static void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle); +static void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle); +static void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle); +static void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle); +static void bta_ag_mgmt_cback_1(const tPORT_RESULT code, uint16_t port_handle); +static void bta_ag_mgmt_cback_2(const tPORT_RESULT code, uint16_t port_handle); +static void bta_ag_mgmt_cback_3(const tPORT_RESULT code, uint16_t port_handle); +static void bta_ag_mgmt_cback_4(const tPORT_RESULT code, uint16_t port_handle); +static void bta_ag_mgmt_cback_5(const tPORT_RESULT code, uint16_t port_handle); +static void bta_ag_mgmt_cback_6(const tPORT_RESULT code, uint16_t port_handle); /* rfcomm callback function tables */ typedef tPORT_CALLBACK* tBTA_AG_PORT_CBACK; -const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {bta_ag_port_cback_1, bta_ag_port_cback_2, +static const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3, bta_ag_port_cback_4, bta_ag_port_cback_5, bta_ag_port_cback_6}; typedef tPORT_MGMT_CALLBACK* tBTA_AG_PORT_MGMT_CBACK; -const tBTA_AG_PORT_MGMT_CBACK bta_ag_mgmt_cback_tbl[] = {bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, +static const tBTA_AG_PORT_MGMT_CBACK bta_ag_mgmt_cback_tbl[] = {bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, bta_ag_mgmt_cback_3, bta_ag_mgmt_cback_4, bta_ag_mgmt_cback_5, bta_ag_mgmt_cback_6}; @@ -165,40 +162,40 @@ static void bta_ag_mgmt_cback(const tPORT_RESULT code, uint16_t port_handle, uin * Returns void * ******************************************************************************/ -void bta_ag_mgmt_cback_1(const tPORT_RESULT code, uint16_t port_handle) { +static void bta_ag_mgmt_cback_1(const tPORT_RESULT code, uint16_t port_handle) { bta_ag_mgmt_cback(code, port_handle, 1); } -void bta_ag_mgmt_cback_2(const tPORT_RESULT code, uint16_t port_handle) { +static void bta_ag_mgmt_cback_2(const tPORT_RESULT code, uint16_t port_handle) { bta_ag_mgmt_cback(code, port_handle, 2); } -void bta_ag_mgmt_cback_3(const tPORT_RESULT code, uint16_t port_handle) { +static void bta_ag_mgmt_cback_3(const tPORT_RESULT code, uint16_t port_handle) { bta_ag_mgmt_cback(code, port_handle, 3); } -void bta_ag_mgmt_cback_4(const tPORT_RESULT code, uint16_t port_handle) { +static void bta_ag_mgmt_cback_4(const tPORT_RESULT code, uint16_t port_handle) { bta_ag_mgmt_cback(code, port_handle, 4); } -void bta_ag_mgmt_cback_5(const tPORT_RESULT code, uint16_t port_handle) { +static void bta_ag_mgmt_cback_5(const tPORT_RESULT code, uint16_t port_handle) { bta_ag_mgmt_cback(code, port_handle, 5); } -void bta_ag_mgmt_cback_6(const tPORT_RESULT code, uint16_t port_handle) { +static void bta_ag_mgmt_cback_6(const tPORT_RESULT code, uint16_t port_handle) { bta_ag_mgmt_cback(code, port_handle, 6); } -void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle) { +static void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle) { bta_ag_port_cback(code, port_handle, 1); } -void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle) { +static void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle) { bta_ag_port_cback(code, port_handle, 2); } -void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle) { +static void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle) { bta_ag_port_cback(code, port_handle, 3); } -void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle) { +static void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle) { bta_ag_port_cback(code, port_handle, 4); } -void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle) { +static void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle) { bta_ag_port_cback(code, port_handle, 5); } -void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle) { +static void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle) { bta_ag_port_cback(code, port_handle, 6); } @@ -212,7 +209,7 @@ void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle) { * Returns void * ******************************************************************************/ -void bta_ag_setup_port(tBTA_AG_SCB* p_scb, uint16_t handle) { +static void bta_ag_setup_port(tBTA_AG_SCB* p_scb, uint16_t handle) { int port_callback_index = bta_ag_scb_to_idx(p_scb) - 1; log::assert_that(port_callback_index >= 0, "invalid callback index, handle={}, bd_addr={}", handle, ADDRESS_TO_LOGGABLE_STR(p_scb->peer_addr)); diff --git a/system/bta/ar/bta_ar.cc b/system/bta/ar/bta_ar.cc index c3fade48b60..6ec0d7d8e65 100644 --- a/system/bta/ar/bta_ar.cc +++ b/system/bta/ar/bta_ar.cc @@ -27,6 +27,7 @@ #include +#include "bta/include/bta_ar_api.h" #include "bta/ar/bta_ar_int.h" #include "bta/sys/bta_sys.h" #include "profile/avrcp/avrcp_sdp_service.h" @@ -37,9 +38,6 @@ #include "stack/include/sdp_api.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth::avrcp; using namespace bluetooth; -- GitLab From bd66c8ea55ea1d69fbadf477604f22dbcea16f1c Mon Sep 17 00:00:00 2001 From: Jack He Date: Fri, 11 Oct 2024 17:27:38 -0700 Subject: [PATCH 291/875] RfcommTest: Fix server closure When removing item from a Python dictionary, we should use "del" instead of assigning it None Bug: 331415222 Test: atest BumbleBluetoothTests Flag: EXEMPT test Change-Id: I514f0d7d4e8443a1b57b6ce0f7faa9cf61087866 --- pandora/server/bumble_experimental/rfcomm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora/server/bumble_experimental/rfcomm.py b/pandora/server/bumble_experimental/rfcomm.py index bdc0ad59663..aa59566cf95 100644 --- a/pandora/server/bumble_experimental/rfcomm.py +++ b/pandora/server/bumble_experimental/rfcomm.py @@ -122,7 +122,7 @@ class RFCOMMService(RFCOMMServicer): async def StopServer(self, request: StopServerRequest, context: grpc.ServicerContext) -> StopServerResponse: logging.info(f"StopServer") assert self.server_ports[request.server.id] is not None - self.server_ports[request.server.id] = None + del self.server_ports[request.server.id] return StopServerResponse() -- GitLab From a0d13ee8ca89943fd54458d19f882c6761adeaee Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Sat, 12 Oct 2024 00:55:15 +0000 Subject: [PATCH 292/875] system/bta/pan: Enforce -Wmissing-prototype Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, minor refactor Change-Id: I533a5de5327bf9adabd73448ca97b289cbb86a88 --- system/bta/ag/bta_ag_rfc.cc | 12 +-- system/bta/ar/bta_ar.cc | 2 +- system/bta/include/bta_pan_ci.h | 64 ------------- system/bta/pan/bta_pan_act.cc | 1 - system/bta/pan/bta_pan_api.cc | 4 - system/bta/pan/bta_pan_ci.cc | 138 +--------------------------- system/bta/pan/bta_pan_main.cc | 11 +-- system/test/mock/mock_bta_pan_ci.cc | 46 ---------- 8 files changed, 13 insertions(+), 265 deletions(-) delete mode 100644 system/test/mock/mock_bta_pan_ci.cc diff --git a/system/bta/ag/bta_ag_rfc.cc b/system/bta/ag/bta_ag_rfc.cc index bdfbfbf5933..b3661aa4d3d 100644 --- a/system/bta/ag/bta_ag_rfc.cc +++ b/system/bta/ag/bta_ag_rfc.cc @@ -54,14 +54,14 @@ static void bta_ag_mgmt_cback_6(const tPORT_RESULT code, uint16_t port_handle); /* rfcomm callback function tables */ typedef tPORT_CALLBACK* tBTA_AG_PORT_CBACK; -static const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {bta_ag_port_cback_1, bta_ag_port_cback_2, - bta_ag_port_cback_3, bta_ag_port_cback_4, - bta_ag_port_cback_5, bta_ag_port_cback_6}; +static const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = { + bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3, + bta_ag_port_cback_4, bta_ag_port_cback_5, bta_ag_port_cback_6}; typedef tPORT_MGMT_CALLBACK* tBTA_AG_PORT_MGMT_CBACK; -static const tBTA_AG_PORT_MGMT_CBACK bta_ag_mgmt_cback_tbl[] = {bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, - bta_ag_mgmt_cback_3, bta_ag_mgmt_cback_4, - bta_ag_mgmt_cback_5, bta_ag_mgmt_cback_6}; +static const tBTA_AG_PORT_MGMT_CBACK bta_ag_mgmt_cback_tbl[] = { + bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, bta_ag_mgmt_cback_3, + bta_ag_mgmt_cback_4, bta_ag_mgmt_cback_5, bta_ag_mgmt_cback_6}; /******************************************************************************* * diff --git a/system/bta/ar/bta_ar.cc b/system/bta/ar/bta_ar.cc index 6ec0d7d8e65..bb365be9e1d 100644 --- a/system/bta/ar/bta_ar.cc +++ b/system/bta/ar/bta_ar.cc @@ -27,8 +27,8 @@ #include -#include "bta/include/bta_ar_api.h" #include "bta/ar/bta_ar_int.h" +#include "bta/include/bta_ar_api.h" #include "bta/sys/bta_sys.h" #include "profile/avrcp/avrcp_sdp_service.h" #include "stack/include/avct_api.h" diff --git a/system/bta/include/bta_pan_ci.h b/system/bta/include/bta_pan_ci.h index 6edc30f7f63..8508867eb6c 100644 --- a/system/bta/include/bta_pan_ci.h +++ b/system/bta/include/bta_pan_ci.h @@ -33,70 +33,6 @@ /***************************************************************************** * Function Declarations ****************************************************************************/ -/******************************************************************************* - * - * Function bta_pan_ci_tx_ready - * - * Description This function sends an event to PAN indicating the phone is - * ready for more data and PAN should call - * bta_pan_co_tx_path(). - * This function is used when the TX data path is configured - * to use a pull interface. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_tx_ready(uint16_t handle); - -/******************************************************************************* - * - * Function bta_pan_ci_rx_ready - * - * Description This function sends an event to PAN indicating the phone - * has data available to send to PAN and PAN should call - * bta_pan_co_rx_path(). This function is used when the RX - * data path is configured to use a pull interface. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_rx_ready(uint16_t handle); - -/******************************************************************************* - * - * Function bta_pan_ci_tx_flow - * - * Description This function is called to enable or disable data flow on - * the TX path. The phone should call this function to - * disable data flow when it is congested and cannot handle - * any more data sent by bta_pan_co_tx_write(). - * This function is used when the - * TX data path is configured to use a push interface. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_tx_flow(uint16_t handle, bool enable); - -/******************************************************************************* - * - * Function bta_pan_ci_rx_writebuf - * - * Description This function is called to send data to the phone when - * the RX path is configured to use a push interface with - * zero copy. The function sends an event to PAN containing - * the data buffer. The buffer will be freed by BTA; the - * phone must not free the buffer. - * - * - * Returns true if flow enabled - * - ******************************************************************************/ -void bta_pan_ci_rx_writebuf(uint16_t handle, const RawAddress& src, const RawAddress& dst, - uint16_t protocol, BT_HDR* p_buf, bool ext); /******************************************************************************* * diff --git a/system/bta/pan/bta_pan_act.cc b/system/bta/pan/bta_pan_act.cc index 223c9813bf8..fa24534bd93 100644 --- a/system/bta/pan/bta_pan_act.cc +++ b/system/bta/pan/bta_pan_act.cc @@ -41,7 +41,6 @@ using namespace bluetooth; #if (PAN_INCLUDED == TRUE) -void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event, tBTA_PAN_DATA* p_data); /* RX and TX data flow mask */ #define BTA_PAN_RX_MASK 0x0F diff --git a/system/bta/pan/bta_pan_api.cc b/system/bta/pan/bta_pan_api.cc index 506c9d547ef..5d75ac19efe 100644 --- a/system/bta/pan/bta_pan_api.cc +++ b/system/bta/pan/bta_pan_api.cc @@ -35,10 +35,6 @@ #include "types/raw_address.h" static const tBTA_SYS_REG bta_pan_reg = {bta_pan_hdl_event, BTA_PanDisable}; -void bta_pan_api_disable(tBTA_PAN_DATA* p_data); -void bta_pan_api_enable(tBTA_PAN_DATA* p_data); -void bta_pan_api_open(tBTA_PAN_DATA* p_data); -void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event, tBTA_PAN_DATA* p_data); std::string user_service_name; /* Service name for PANU role */ std::string gn_service_name; /* Service name for GN role */ diff --git a/system/bta/pan/bta_pan_ci.cc b/system/bta/pan/bta_pan_ci.cc index abd60b01450..a00ef5ba10f 100644 --- a/system/bta/pan/bta_pan_ci.cc +++ b/system/bta/pan/bta_pan_ci.cc @@ -22,148 +22,14 @@ * ******************************************************************************/ +#include "bta/include/bta_pan_ci.h" + #include "bta/pan/bta_pan_int.h" #include "internal_include/bt_target.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event, tBTA_PAN_DATA* p_data); - -/******************************************************************************* - * - * Function bta_pan_ci_tx_ready - * - * Description This function sends an event to PAN indicating the phone is - * ready for more data and PAN should call - * bta_pan_co_tx_path(). - * This function is used when the TX data path is configured - * to use a pull interface. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_tx_ready(uint16_t handle) { - BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR)); - - p_buf->layer_specific = handle; - p_buf->event = BTA_PAN_CI_TX_READY_EVT; - - bta_sys_sendmsg(p_buf); -} - -/******************************************************************************* - * - * Function bta_pan_ci_rx_ready - * - * Description This function sends an event to PAN indicating the phone - * has data available to send to PAN and PAN should call - * bta_pan_co_rx_path(). This function is used when the RX - * data path is configured to use a pull interface. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_rx_ready(uint16_t handle) { - BT_HDR_RIGID* p_buf = (BT_HDR_RIGID*)osi_malloc(sizeof(BT_HDR_RIGID)); - - p_buf->layer_specific = handle; - p_buf->event = BTA_PAN_CI_RX_READY_EVT; - - bta_sys_sendmsg(p_buf); -} - -/******************************************************************************* - * - * Function bta_pan_ci_tx_flow - * - * Description This function is called to enable or disable data flow on - * the TX path. The phone should call this function to - * disable data flow when it is congested and cannot handle - * any more data sent by bta_pan_co_tx_write(). - * This function is used when the - * TX data path is configured to use a push interface. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_tx_flow(uint16_t handle, bool enable) { - tBTA_PAN_CI_TX_FLOW* p_buf = (tBTA_PAN_CI_TX_FLOW*)osi_malloc(sizeof(tBTA_PAN_CI_TX_FLOW)); - - p_buf->hdr.layer_specific = handle; - p_buf->hdr.event = BTA_PAN_CI_TX_FLOW_EVT; - p_buf->enable = enable; - - bta_sys_sendmsg(p_buf); -} - -/******************************************************************************* - * - * Function bta_pan_ci_rx_write - * - * Description This function is called to send data to PAN when the RX path - * is configured to use a push interface. The function copies - * data to an event buffer and sends it to PAN. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_rx_write(uint16_t handle, const RawAddress& dst, const RawAddress& src, - uint16_t protocol, uint8_t* p_data, uint16_t len, bool ext) { - BT_HDR* p_buf = (BT_HDR*)osi_malloc(PAN_BUF_SIZE); - - p_buf->offset = PAN_MINIMUM_OFFSET; - - /* copy all other params before the data */ - ((tBTA_PAN_DATA_PARAMS*)p_buf)->src = src; - ((tBTA_PAN_DATA_PARAMS*)p_buf)->dst = dst; - ((tBTA_PAN_DATA_PARAMS*)p_buf)->protocol = protocol; - ((tBTA_PAN_DATA_PARAMS*)p_buf)->ext = ext; - p_buf->len = len; - - /* copy data */ - memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, len); - - p_buf->layer_specific = handle; - p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT; - - bta_sys_sendmsg(p_buf); -} - -/******************************************************************************* - * - * Function bta_pan_ci_rx_writebuf - * - * Description This function is called to send data to the phone when - * the RX path is configured to use a push interface with - * zero copy. The function sends an event to PAN containing - * the data buffer. The buffer will be freed by BTA; the - * phone must not free the buffer. - * - * - * Returns void - * - ******************************************************************************/ -void bta_pan_ci_rx_writebuf(uint16_t handle, const RawAddress& dst, const RawAddress& src, - uint16_t protocol, BT_HDR* p_buf, bool ext) { - /* copy all other params before the data */ - ((tBTA_PAN_DATA_PARAMS*)p_buf)->src = src; - ((tBTA_PAN_DATA_PARAMS*)p_buf)->dst = dst; - ((tBTA_PAN_DATA_PARAMS*)p_buf)->protocol = protocol; - ((tBTA_PAN_DATA_PARAMS*)p_buf)->ext = ext; - - p_buf->layer_specific = handle; - p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT; - bta_sys_sendmsg(p_buf); -} - /******************************************************************************* * * Function bta_pan_ci_readbuf diff --git a/system/bta/pan/bta_pan_main.cc b/system/bta/pan/bta_pan_main.cc index 1f2dc9d2e0b..91652e596ac 100644 --- a/system/bta/pan/bta_pan_main.cc +++ b/system/bta/pan/bta_pan_main.cc @@ -29,9 +29,6 @@ #include "internal_include/bt_target.h" #include "stack/include/bt_hdr.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -161,7 +158,7 @@ tBTA_PAN_SCB* bta_pan_scb_alloc(void) { * Returns void * ******************************************************************************/ -void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event, tBTA_PAN_DATA* p_data) { +static void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event, tBTA_PAN_DATA* p_data) { tBTA_PAN_ST_TBL state_table; uint8_t action; int i; @@ -197,7 +194,7 @@ void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event, tBTA_PAN_DATA* p_da * Returns void * ******************************************************************************/ -void bta_pan_api_enable(tBTA_PAN_DATA* p_data) { +static void bta_pan_api_enable(tBTA_PAN_DATA* p_data) { /* initialize control block */ memset(&bta_pan_cb, 0, sizeof(bta_pan_cb)); @@ -216,7 +213,7 @@ void bta_pan_api_enable(tBTA_PAN_DATA* p_data) { * Returns void * ******************************************************************************/ -void bta_pan_api_disable(tBTA_PAN_DATA* /* p_data */) { bta_pan_disable(); } +static void bta_pan_api_disable(tBTA_PAN_DATA* /* p_data */) { bta_pan_disable(); } /******************************************************************************* * @@ -228,7 +225,7 @@ void bta_pan_api_disable(tBTA_PAN_DATA* /* p_data */) { bta_pan_disable(); } * Returns void * ******************************************************************************/ -void bta_pan_api_open(tBTA_PAN_DATA* p_data) { +static void bta_pan_api_open(tBTA_PAN_DATA* p_data) { tBTA_PAN_SCB* p_scb; tBTA_PAN bta_pan; diff --git a/system/test/mock/mock_bta_pan_ci.cc b/system/test/mock/mock_bta_pan_ci.cc deleted file mode 100644 index ca15b4c33bb..00000000000 --- a/system/test/mock/mock_bta_pan_ci.cc +++ /dev/null @@ -1,46 +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:8 - */ - -#include "stack/include/bt_hdr.h" -#include "test/common/mock_functions.h" -#include "types/raw_address.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -BT_HDR* bta_pan_ci_readbuf(uint16_t /* handle */, RawAddress& /* src */, RawAddress& /* dst */, - uint16_t* /* p_protocol */, bool* /* p_ext */, bool* /* p_forward */) { - inc_func_call_count(__func__); - return nullptr; -} -void bta_pan_ci_rx_ready(uint16_t /* handle */) { inc_func_call_count(__func__); } -void bta_pan_ci_rx_write(uint16_t /* handle */, const RawAddress& /* dst */, - const RawAddress& /* src */, uint16_t /* protocol */, - uint8_t* /* p_data */, uint16_t /* len */, bool /* ext */) { - inc_func_call_count(__func__); -} -void bta_pan_ci_rx_writebuf(uint16_t /* handle */, const RawAddress& /* dst */, - const RawAddress& /* src */, uint16_t /* protocol */, - BT_HDR* /* p_buf */, bool /* ext */) { - inc_func_call_count(__func__); -} -void bta_pan_ci_tx_flow(uint16_t /* handle */, bool /* enable */) { inc_func_call_count(__func__); } -void bta_pan_ci_tx_ready(uint16_t /* handle */) { inc_func_call_count(__func__); } -- GitLab From c8db5d6bd1ccd652f02b88a252d26b668ecf464c Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 11 Oct 2024 17:55:46 +0000 Subject: [PATCH 293/875] handle the procedure enable command error 1. avoid sending 'enable' when the session is stopped. 2. work around the 'disable' error from controller. Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 368617974 Test: m com.android.btservices Change-Id: I7e86bebae8ed7fb51300bdb911f519d3b94afc1c --- system/gd/hci/distance_measurement_manager.cc | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 1e7f75a55ee..936676aac1a 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -635,10 +635,33 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } + if (!cs_trackers_[connection_handle].measurement_ongoing) { + log::error("safe guard, error state, no local measurement request."); + if (cs_trackers_[connection_handle].repeating_alarm) { + cs_trackers_[connection_handle].repeating_alarm->Cancel(); + } + return; + } + hci_layer_->EnqueueCommand( LeCsProcedureEnableBuilder::Create(connection_handle, cs_trackers_[connection_handle].config_id, enable), - handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); + handler_->BindOnceOn(this, &impl::on_cs_procedure_enable_command_status_cb, + connection_handle, enable)); + } + + void on_cs_procedure_enable_command_status_cb(uint16_t connection_handle, Enable enable, + CommandStatusView status_view) { + ErrorCode status = status_view.GetStatus(); + // controller may send error if the procedure instance has finished all scheduled procedures. + if (enable == Enable::DISABLED && status == ErrorCode::COMMAND_DISALLOWED) { + log::info("ignored the procedure disable command disallow error."); + if (cs_trackers_.find(connection_handle) != cs_trackers_.end()) { + reset_tracker_on_stopped(&cs_trackers_[connection_handle]); + } + } else { + on_cs_setup_command_status_cb(connection_handle, status_view); + } } void on_cs_setup_command_status_cb(uint16_t connection_handle, CommandStatusView status_view) { -- GitLab From 663489c837b912a482825b3257211727b5ba61ad Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Fri, 11 Oct 2024 22:08:24 +0200 Subject: [PATCH 294/875] acl_create_le_connection_with_id -> create_le_connection create_le_connection is adding device directly to AclManager, and relying on it's "direct connect" implementation. direct_connect_add method is doing multiplexing of apps request, and sending the request to AclManager, but it lacks some extra checks and lookups. Currently these methods are exclusive, if you try to use both you will get some bad behavior. These should be merged into one. This patch is moving both methods into same location, so it's easier to merge them into one under a flag. Test: mma -j32 Bug: 372202918 Flag: EXEMPT, just renaming/moving code Change-Id: I9166cca63dff9ada1ed4962ca805962c765f84d7 --- system/stack/Android.bp | 1 + system/stack/acl/btm_acl.cc | 44 ------------------- system/stack/fuzzers/l2cap_fuzzer.cc | 12 ++--- system/stack/gatt/connection_manager.cc | 42 ++++++++++++++++++ system/stack/gatt/connection_manager.h | 9 ++++ system/stack/gatt/gatt_api.cc | 2 +- system/stack/gatt/gatt_main.cc | 2 +- system/stack/include/l2cap_acl_interface.h | 2 - system/stack/l2cap/l2c_ble.cc | 3 +- .../test/gatt_connection_manager_test.cc | 3 ++ system/test/mock/mock_stack_acl.cc | 6 --- system/test/mock/mock_stack_acl.h | 13 ------ .../mock_stack_gatt_connection_manager.cc | 7 +++ 13 files changed, 73 insertions(+), 73 deletions(-) diff --git a/system/stack/Android.bp b/system/stack/Android.bp index a349e80a8ea..5fec9d2cee2 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -2067,6 +2067,7 @@ cc_test { ":TestMockMainShimEntry", ":TestMockStackAcl", ":TestMockStackBtm", + ":TestMockStackGatt", ":TestMockStackHcic", ":TestMockStackSdp", ":TestMockStackSmp", diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index fc4a4dcd6c5..612fd9dc63f 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -96,7 +96,6 @@ using bluetooth::legacy::hci::GetInterface; void BTM_update_version_info(const RawAddress& bd_addr, const remote_version_info& remote_version_info); -static void find_in_device_record(const RawAddress& bd_addr, tBLE_BD_ADDR* address_with_type); void l2c_link_hci_conn_comp(tHCI_STATUS status, uint16_t handle, const RawAddress& p_bda); void BTM_db_reset(void); @@ -2462,31 +2461,6 @@ void acl_write_automatic_flush_timeout(const RawAddress& bd_addr, uint16_t flush btsnd_hcic_write_auto_flush_tout(p_acl->hci_handle, flush_timeout_in_ticks); } -bool acl_create_le_connection_with_id(uint8_t /* id */, const RawAddress& bd_addr, - tBLE_ADDR_TYPE addr_type) { - tBLE_BD_ADDR address_with_type{ - .type = addr_type, - .bda = bd_addr, - }; - - find_in_device_record(bd_addr, &address_with_type); - - log::debug("Creating le direct connection to:{} type:{} (initial type: {})", address_with_type, - AddressTypeText(address_with_type.type), AddressTypeText(addr_type)); - - if (address_with_type.type == BLE_ADDR_ANONYMOUS) { - log::warn( - "Creating le direct connection to:{}, address type 'anonymous' is " - "invalid", - address_with_type); - return false; - } - - bluetooth::shim::ACL_AcceptLeConnectionFrom(address_with_type, - /* is_direct */ true); - return true; -} - void acl_rcv_acl_data(BT_HDR* p_msg) { acl_header_t acl_header{ .handle = HCI_INVALID_HANDLE, @@ -2583,24 +2557,6 @@ tACL_CONN* btm_acl_for_bda(const RawAddress& bd_addr, tBT_TRANSPORT transport) { return p_acl; } -void find_in_device_record(const RawAddress& bd_addr, tBLE_BD_ADDR* address_with_type) { - const tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr); - if (p_dev_rec == nullptr) { - return; - } - - if (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) { - if (p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) { - *address_with_type = {.type = p_dev_rec->ble.AddressType(), .bda = bd_addr}; - return; - } - *address_with_type = p_dev_rec->ble.identity_address_with_type; - return; - } - *address_with_type = {.type = BLE_ADDR_PUBLIC, .bda = bd_addr}; - return; -} - /******************************************************************************* * * Function btm_acl_flush diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc index d9793509b43..fd68f984864 100644 --- a/system/stack/fuzzers/l2cap_fuzzer.cc +++ b/system/stack/fuzzers/l2cap_fuzzer.cc @@ -95,15 +95,18 @@ void SnoopLogger::SetL2capChannelOpen(uint16_t, uint16_t, uint16_t, uint16_t, bo } // namespace hal } // namespace bluetooth +namespace connection_manager { +bool create_le_connection(uint8_t /* id */, const RawAddress& /* bd_addr */, + tBLE_ADDR_TYPE /* addr_type */) { + return true; +} +} // namespace connection_manager + namespace { class FakeBtStack { public: FakeBtStack() { - test::mock::stack_acl::acl_create_le_connection_with_id.body = - [](uint8_t /* id */, const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */) { - return true; - }; test::mock::stack_acl::acl_send_data_packet_br_edr.body = [](const RawAddress& /*bd_addr*/, BT_HDR* hdr) { ConsumeData((const uint8_t*)hdr, hdr->offset + hdr->len); @@ -132,7 +135,6 @@ public: } ~FakeBtStack() { - test::mock::stack_acl::acl_create_le_connection_with_id = {}; 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; diff --git a/system/stack/gatt/connection_manager.cc b/system/stack/gatt/connection_manager.cc index 45e19c91990..96278a91064 100644 --- a/system/stack/gatt/connection_manager.cc +++ b/system/stack/gatt/connection_manager.cc @@ -440,6 +440,48 @@ void wl_direct_connect_timeout_cb(uint8_t app_id, const RawAddress& address) { direct_connect_remove(app_id, address, true); } +static void find_in_device_record(const RawAddress& bd_addr, tBLE_BD_ADDR* address_with_type) { + const tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr); + if (p_dev_rec == nullptr) { + return; + } + + if (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) { + if (p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) { + *address_with_type = {.type = p_dev_rec->ble.AddressType(), .bda = bd_addr}; + return; + } + *address_with_type = p_dev_rec->ble.identity_address_with_type; + return; + } + *address_with_type = {.type = BLE_ADDR_PUBLIC, .bda = bd_addr}; + return; +} + +bool create_le_connection(uint8_t /* id */, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type) { + tBLE_BD_ADDR address_with_type{ + .type = addr_type, + .bda = bd_addr, + }; + + find_in_device_record(bd_addr, &address_with_type); + + log::debug("Creating le direct connection to:{} type:{} (initial type: {})", address_with_type, + AddressTypeText(address_with_type.type), AddressTypeText(addr_type)); + + if (address_with_type.type == BLE_ADDR_ANONYMOUS) { + log::warn( + "Creating le direct connection to:{}, address type 'anonymous' is " + "invalid", + address_with_type); + return false; + } + + bluetooth::shim::ACL_AcceptLeConnectionFrom(address_with_type, + /* is_direct */ true); + return true; +} + /** Add a device to the direct connection list. Returns true if device * added to the list, false otherwise */ bool direct_connect_add(uint8_t app_id, const RawAddress& address) { diff --git a/system/stack/gatt/connection_manager.h b/system/stack/gatt/connection_manager.h index fe564e9099c..a9a52562612 100644 --- a/system/stack/gatt/connection_manager.h +++ b/system/stack/gatt/connection_manager.h @@ -20,6 +20,7 @@ #include +#include "ble_address_with_type.h" #include "types/raw_address.h" /* connection_manager takes care of all the low-level details of LE connection @@ -49,6 +50,14 @@ void on_connection_complete(const RawAddress& address); std::set get_apps_connecting_to(const RawAddress& remote_bda); +/* create_le_connection is adding device directly to AclManager, and relying on it's "direct + * connect" implementation. + * direct_connect_add method is doing multiplexing of apps request, and + * sending the request to AclManager, but it lacks some extra checks and lookups. Currently these + * methods are exclusive, if you try to use both you will get some bad behavior. These should be + * merged into one. */ +bool create_le_connection(uint8_t /* id */, const RawAddress& bd_addr, + tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC); bool direct_connect_add(tAPP_ID app_id, const RawAddress& address); bool direct_connect_remove(tAPP_ID app_id, const RawAddress& address, bool connection_timeout = false); diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index cf723d1e1e1..af0dd7a9e22 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -1488,7 +1488,7 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE ad log::warn("{} already added to gatt_if {} direct conn list", bd_addr, gatt_if); } - ret = acl_create_le_connection_with_id(gatt_if, bd_addr, addr_type); + ret = connection_manager::create_le_connection(gatt_if, bd_addr, addr_type); } } else { diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index 7c8a2566100..a401c37f1d9 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -237,7 +237,7 @@ bool gatt_connect(const RawAddress& rem_bda, tBLE_ADDR_TYPE addr_type, tGATT_TCB } p_tcb->att_lcid = L2CAP_ATT_CID; - return acl_create_le_connection_with_id(gatt_if, rem_bda, addr_type); + return connection_manager::create_le_connection(gatt_if, rem_bda, addr_type); } bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBT_TRANSPORT transport, diff --git a/system/stack/include/l2cap_acl_interface.h b/system/stack/include/l2cap_acl_interface.h index 7e4a17dc466..811b5c12880 100644 --- a/system/stack/include/l2cap_acl_interface.h +++ b/system/stack/include/l2cap_acl_interface.h @@ -25,8 +25,6 @@ // This header contains functions for L2cap-ACL to invoke // -bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, - tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC); void acl_send_data_packet_br_edr(const RawAddress& bd_addr, BT_HDR* p_buf); void acl_send_data_packet_ble(const RawAddress& bd_addr, BT_HDR* p_buf); void acl_write_automatic_flush_timeout(const RawAddress& bd_addr, uint16_t flush_timeout); diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index 92753f8049b..8c6ff8af0bc 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -44,6 +44,7 @@ #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" #include "stack/btm/btm_sec_int_types.h" +#include "stack/gatt/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" @@ -926,7 +927,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { /** This function is to initate a direct connection. Returns true if connection * initiated, false otherwise. */ bool l2cble_create_conn(tL2C_LCB* p_lcb) { - if (!acl_create_le_connection_with_id(CONN_MGR_ID_L2CAP, p_lcb->remote_bd_addr)) { + if (!connection_manager::create_le_connection(CONN_MGR_ID_L2CAP, p_lcb->remote_bd_addr)) { return false; } diff --git a/system/stack/test/gatt_connection_manager_test.cc b/system/stack/test/gatt_connection_manager_test.cc index c1103b17009..afe3fcba4e8 100644 --- a/system/stack/test/gatt_connection_manager_test.cc +++ b/system/stack/test/gatt_connection_manager_test.cc @@ -9,6 +9,7 @@ #include "osi/include/alarm.h" #include "osi/test/alarm_mock.h" +#include "security_device_record.h" #include "stack/btm/neighbor_inquiry.h" #include "stack/gatt/connection_manager.h" @@ -53,6 +54,8 @@ const tBLE_BD_ADDR BTM_Sec_GetAddressWithType(const RawAddress& bd_addr) { return tBLE_BD_ADDR{.type = BLE_ADDR_PUBLIC, .bda = bd_addr}; } +tBTM_SEC_DEV_REC* btm_find_dev(const RawAddress& /* bd_addr */) { return nullptr; } + namespace bluetooth { namespace shim { diff --git a/system/test/mock/mock_stack_acl.cc b/system/test/mock/mock_stack_acl.cc index c5989b3bbd0..1e85c50ee33 100644 --- a/system/test/mock/mock_stack_acl.cc +++ b/system/test/mock/mock_stack_acl.cc @@ -48,7 +48,6 @@ struct BTM_IsAclConnectionUp BTM_IsAclConnectionUp; struct BTM_IsBleConnection BTM_IsBleConnection; struct BTM_ReadRemoteConnectionAddr BTM_ReadRemoteConnectionAddr; struct BTM_is_sniff_allowed_for BTM_is_sniff_allowed_for; -struct acl_create_le_connection_with_id acl_create_le_connection_with_id; struct acl_is_role_switch_allowed acl_is_role_switch_allowed; struct acl_is_switch_role_idle acl_is_switch_role_idle; struct acl_peer_supports_ble_2m_phy acl_peer_supports_ble_2m_phy; @@ -152,11 +151,6 @@ bool BTM_is_sniff_allowed_for(const RawAddress& peer_addr) { inc_func_call_count(__func__); return test::mock::stack_acl::BTM_is_sniff_allowed_for(peer_addr); } -bool acl_create_le_connection_with_id(uint8_t id, const RawAddress& bd_addr, - tBLE_ADDR_TYPE addr_type) { - inc_func_call_count(__func__); - return test::mock::stack_acl::acl_create_le_connection_with_id(id, bd_addr, addr_type); -} bool acl_is_role_switch_allowed() { inc_func_call_count(__func__); return test::mock::stack_acl::acl_is_role_switch_allowed(); diff --git a/system/test/mock/mock_stack_acl.h b/system/test/mock/mock_stack_acl.h index 2f4dc13ca1a..a454f7ff3db 100644 --- a/system/test/mock/mock_stack_acl.h +++ b/system/test/mock/mock_stack_acl.h @@ -97,19 +97,6 @@ struct acl_send_data_packet_br_edr { void operator()(const RawAddress& bd_addr, BT_HDR* p_buf) { return body(bd_addr, p_buf); } }; extern struct acl_send_data_packet_br_edr acl_send_data_packet_br_edr; -// Name: acl_create_le_connection_with_id -// Params: uint8_t id, const RawAddress& bd_addr -// Returns: bool -struct acl_create_le_connection_with_id { - std::function body{ - [](uint8_t /* id */, const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */) { - return false; - }}; - bool operator()(uint8_t id, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type) { - return body(id, bd_addr, addr_type); - } -}; -extern struct acl_create_le_connection_with_id acl_create_le_connection_with_id; // Name: acl_is_role_switch_allowed // Params: // Returns: bool diff --git a/system/test/mock/mock_stack_gatt_connection_manager.cc b/system/test/mock/mock_stack_gatt_connection_manager.cc index a27d7d2d6df..f0f33dddb5e 100644 --- a/system/test/mock/mock_stack_gatt_connection_manager.cc +++ b/system/test/mock/mock_stack_gatt_connection_manager.cc @@ -37,6 +37,13 @@ bool connection_manager::background_connect_remove(uint8_t /* app_id */, inc_func_call_count(__func__); return false; } + +bool connection_manager::create_le_connection(uint8_t /* id */, const RawAddress& /* bd_addr */, + tBLE_ADDR_TYPE /* addr_type */) { + inc_func_call_count(__func__); + return false; +} + bool connection_manager::direct_connect_add(uint8_t /* app_id */, const RawAddress& /* address */) { inc_func_call_count(__func__); return false; -- GitLab From 758a564ad098b911ea08134cd0d7108bd62b6541 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Fri, 11 Oct 2024 08:17:22 +0000 Subject: [PATCH 295/875] CS: Return confidence level Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 371187745 Test: m com.android.btservice Change-Id: I93630422b0805f3c0afeeb1621e12850c1164651 --- android/app/jni/com_android_bluetooth_gatt.cpp | 6 +++--- .../bluetooth/gatt/DistanceMeasurementManager.java | 14 ++++++++++---- .../gatt/DistanceMeasurementNativeInterface.java | 2 ++ .../gatt/DistanceMeasurementManagerTest.java | 2 ++ system/gd/hal/ranging_hal.h | 3 +++ system/gd/hal/ranging_hal_android.cc | 6 ++++-- system/gd/hci/distance_measurement_manager.cc | 5 +++-- system/gd/hci/distance_measurement_manager.h | 1 + system/gd/hci/distance_measurement_manager_mock.h | 3 ++- .../hardware/distance_measurement_interface.h | 2 +- system/main/shim/distance_measurement_manager.cc | 12 +++++++----- 11 files changed, 38 insertions(+), 18 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index 3e19920e224..15cab4f12b2 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -1235,7 +1235,7 @@ public: uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, int error_altitude_angle, long elapsedRealtimeNanos, - uint8_t method) { + int8_t confidence_level, uint8_t method) { std::shared_lock lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mDistanceMeasurementCallbacksObj) { @@ -1245,7 +1245,7 @@ public: sCallbackEnv->CallVoidMethod( mDistanceMeasurementCallbacksObj, method_onDistanceMeasurementResult, addr.get(), centimeter, error_centimeter, azimuth_angle, error_azimuth_angle, altitude_angle, - error_altitude_angle, elapsedRealtimeNanos, method); + error_altitude_angle, elapsedRealtimeNanos, confidence_level, method); } }; @@ -2979,7 +2979,7 @@ static int register_com_android_bluetooth_gatt_distance_measurement(JNIEnv* env) &method_onDistanceMeasurementStartFail}, {"onDistanceMeasurementStopped", "(Ljava/lang/String;II)V", &method_onDistanceMeasurementStopped}, - {"onDistanceMeasurementResult", "(Ljava/lang/String;IIIIIIJI)V", + {"onDistanceMeasurementResult", "(Ljava/lang/String;IIIIIIJII)V", &method_onDistanceMeasurementResult}, }; GET_JAVA_METHODS(env, "com/android/bluetooth/gatt/DistanceMeasurementNativeInterface", diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java index 95868961183..b4f27559bc8 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java @@ -469,16 +469,22 @@ public class DistanceMeasurementManager { int altitudeAngle, int errorAltitudeAngle, long elapsedRealtimeNanos, + int confidenceLevel, int method) { logd( "onDistanceMeasurementResult " + BluetoothUtils.toAnonymizedAddress(address) + ", centimeter " - + centimeter); - DistanceMeasurementResult result = + + centimeter + + ", confidenceLevel " + + confidenceLevel); + DistanceMeasurementResult.Builder builder = new DistanceMeasurementResult.Builder(centimeter / 100.0, errorCentimeter / 100.0) - .setMeasurementTimestampNanos(elapsedRealtimeNanos) - .build(); + .setMeasurementTimestampNanos(elapsedRealtimeNanos); + if (confidenceLevel != -1) { + builder.setConfidenceLevel(confidenceLevel / 100.0); + } + DistanceMeasurementResult result = builder.build(); switch (method) { case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: handleRssiResult(address, result); diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java index 223e36556fb..5d1b56b8db5 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java @@ -111,6 +111,7 @@ public class DistanceMeasurementNativeInterface { int altitudeAngle, int errorAltitudeAngle, long elapsedRealtimeNanos, + int confidenceLevel, int method) { mDistanceMeasurementManager.onDistanceMeasurementResult( address, @@ -121,6 +122,7 @@ public class DistanceMeasurementNativeInterface { altitudeAngle, errorAltitudeAngle, elapsedRealtimeNanos, + confidenceLevel, method); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java index ca85b26668f..b5aa597273c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java @@ -197,6 +197,7 @@ public class DistanceMeasurementManagerTest { -1, -1, 1000L, + -1, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); ArgumentCaptor result = ArgumentCaptor.forClass(DistanceMeasurementResult.class); @@ -235,6 +236,7 @@ public class DistanceMeasurementManagerTest { -1, -1, 1000L, + -1, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); DistanceMeasurementResult result = new DistanceMeasurementResult.Builder(1.00, 1.00).build(); diff --git a/system/gd/hal/ranging_hal.h b/system/gd/hal/ranging_hal.h index 2d1be5be6df..803f326c99e 100644 --- a/system/gd/hal/ranging_hal.h +++ b/system/gd/hal/ranging_hal.h @@ -39,6 +39,9 @@ struct ChannelSoundingRawData { struct RangingResult { double result_meters_; + // A normalized value from 0 (low confidence) to 100 (high confidence) representing the confidence + // of estimated distance. The value is -1 when unavailable. + int8_t confidence_level_; }; class RangingHalCallback { diff --git a/system/gd/hal/ranging_hal_android.cc b/system/gd/hal/ranging_hal_android.cc index 3c2696f669c..658b7d777b5 100644 --- a/system/gd/hal/ranging_hal_android.cc +++ b/system/gd/hal/ranging_hal_android.cc @@ -75,8 +75,10 @@ public: ::ndk::ScopedAStatus onResult( const ::aidl::android::hardware::bluetooth::ranging::RangingResult& in_result) { log::verbose("resultMeters {}", in_result.resultMeters); - hal::RangingResult ranging_result; - ranging_result.result_meters_ = in_result.resultMeters; + hal::RangingResult ranging_result = { + .result_meters_ = in_result.resultMeters, + .confidence_level_ = in_result.confidenceLevel, + }; ranging_hal_callback_->OnResult(connection_handle_, ranging_result); return ::ndk::ScopedAStatus::ok(); } diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index b8ce2f4263e..04410d07d55 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -219,7 +219,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { duration_cast(steady_clock::now().time_since_epoch()).count(); distance_measurement_callbacks_->OnDistanceMeasurementResult( cs_trackers_[connection_handle].address, ranging_result.result_meters_ * 100, 0.0, -1, - -1, -1, -1, elapsedRealtimeNanos, DistanceMeasurementMethod::METHOD_CS); + -1, -1, -1, elapsedRealtimeNanos, ranging_result.confidence_level_, + DistanceMeasurementMethod::METHOD_CS); } ~impl() {} @@ -1546,7 +1547,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { long elapsedRealtimeNanos = duration_cast(steady_clock::now().time_since_epoch()).count(); distance_measurement_callbacks_->OnDistanceMeasurementResult( - address, distance * 100, distance * 100, -1, -1, -1, -1, elapsedRealtimeNanos, + address, distance * 100, distance * 100, -1, -1, -1, -1, elapsedRealtimeNanos, -1, DistanceMeasurementMethod::METHOD_RSSI); } diff --git a/system/gd/hci/distance_measurement_manager.h b/system/gd/hci/distance_measurement_manager.h index bb9158c592c..03103200b89 100644 --- a/system/gd/hci/distance_measurement_manager.h +++ b/system/gd/hci/distance_measurement_manager.h @@ -61,6 +61,7 @@ public: uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, int error_altitude_angle, long elapsedRealtimeNanos, + int8_t confidence_level, DistanceMeasurementMethod method) = 0; virtual void OnRasFragmentReady(Address address, uint16_t procedure_counter, bool is_last, std::vector raw_data) = 0; diff --git a/system/gd/hci/distance_measurement_manager_mock.h b/system/gd/hci/distance_measurement_manager_mock.h index 6561c18d8cf..e062f1e3136 100644 --- a/system/gd/hci/distance_measurement_manager_mock.h +++ b/system/gd/hci/distance_measurement_manager_mock.h @@ -37,7 +37,8 @@ class MockDistanceMeasurementCallbacks : public DistanceMeasurementCallbacks { MOCK_METHOD(void, OnDistanceMeasurementStopped, (Address, DistanceMeasurementErrorCode, DistanceMeasurementMethod)); MOCK_METHOD(void, OnDistanceMeasurementResult, - (Address, uint32_t, uint32_t, int, int, int, int, long, DistanceMeasurementMethod)); + (Address, uint32_t, uint32_t, int, int, int, int, long, int8_t, + DistanceMeasurementMethod)); }; class MockDistanceMeasurementManager : public DistanceMeasurementManager { diff --git a/system/include/hardware/distance_measurement_interface.h b/system/include/hardware/distance_measurement_interface.h index ed382d32e09..01367a557db 100644 --- a/system/include/hardware/distance_measurement_interface.h +++ b/system/include/hardware/distance_measurement_interface.h @@ -34,7 +34,7 @@ public: uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, int error_altitude_angle, long elapsedRealtimeNanos, - uint8_t method) = 0; + int8_t confidence_level, uint8_t method) = 0; }; class DistanceMeasurementInterface { diff --git a/system/main/shim/distance_measurement_manager.cc b/system/main/shim/distance_measurement_manager.cc index 6e45e090e04..53bc0c02118 100644 --- a/system/main/shim/distance_measurement_manager.cc +++ b/system/main/shim/distance_measurement_manager.cc @@ -127,12 +127,14 @@ public: uint32_t error_centimeter, int azimuth_angle, int error_azimuth_angle, int altitude_angle, int error_altitude_angle, long elapsedRealtimeNanos, + int8_t confidence_level, DistanceMeasurementMethod method) override { - do_in_jni_thread(base::BindOnce( - &::DistanceMeasurementCallbacks::OnDistanceMeasurementResult, - base::Unretained(distance_measurement_callbacks_), bluetooth::ToRawAddress(address), - centimeter, error_centimeter, azimuth_angle, error_azimuth_angle, altitude_angle, - error_altitude_angle, elapsedRealtimeNanos, static_cast(method))); + do_in_jni_thread(base::BindOnce(&::DistanceMeasurementCallbacks::OnDistanceMeasurementResult, + base::Unretained(distance_measurement_callbacks_), + bluetooth::ToRawAddress(address), centimeter, error_centimeter, + azimuth_angle, error_azimuth_angle, altitude_angle, + error_altitude_angle, elapsedRealtimeNanos, confidence_level, + static_cast(method))); } void OnRasFragmentReady(bluetooth::hci::Address address, uint16_t procedure_counter, bool is_last, -- GitLab From ee26c37de3a5b1cd89c2606467f49e984bf85064 Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Mon, 14 Oct 2024 11:45:37 +0800 Subject: [PATCH 296/875] floss: GATT: Make sure OnConnectionUpdated is sent when ConnectionParameterUpdate When ConnectionParameterUpdate is called without an GATT connnection, LibBluetooth won't send out a callback. To provide a simpler API usage, this patch guarantees that a OnConnectionUpdated will always be sent after ConnectionParameterUpdate. Bug: 372547952 Tag: #floss Test: mmm packages/modules/Bluetooth Test: manual call ConnectionParameterUpdate w/o an active connection, the OnConnectionUpdated callback is called Flag: EXEMPT, Floss-only change Change-Id: Ib22b235ce2a6cb38d93ca9fa1e2d24a60b25223b --- .../gd/rust/linux/stack/src/bluetooth_gatt.rs | 53 ++++++++++++++++--- system/gd/rust/linux/stack/src/lib.rs | 2 +- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs index 6c56ce6d9d2..10368fbf49c 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs @@ -1306,6 +1306,10 @@ pub struct ScanFilter { } pub enum GattActions { + /// Used when we need to invoke an update in this layer e.g. when there's no active connection, + /// where LibBluetooth accepts the conn_parameter_update call but won't send out a callback. + /// Params: client_id, address, interval, latency, timeout, status + InvokeConnectionUpdated(i32, RawAddress, i32, i32, i32, GattStatus), /// This disconnects all server and client connections to the device. /// Params: remote_device Disconnect(BluetoothDevice), @@ -1335,6 +1339,7 @@ enum ControllerScanType { /// Implementation of the GATT API (IBluetoothGatt). pub struct BluetoothGatt { gatt: Arc>, + tx: Sender, context_map: ContextMap, server_context_map: ServerContextMap, @@ -1370,6 +1375,7 @@ impl BluetoothGatt { pub fn new(intf: Arc>, tx: Sender) -> BluetoothGatt { BluetoothGatt { gatt: Arc::new(Mutex::new(Gatt::new(&intf.lock().unwrap()))), + tx: tx.clone(), context_map: ContextMap::new(tx.clone()), server_context_map: ServerContextMap::new(tx.clone()), reliable_queue: HashSet::new(), @@ -1387,24 +1393,24 @@ impl BluetoothGatt { } } - pub fn init_profiles(&mut self, tx: Sender, api_tx: Sender) { + pub fn init_profiles(&mut self, api_tx: Sender) { let gatt_client_callbacks_dispatcher = GattClientCallbacksDispatcher { - dispatch: make_message_dispatcher(tx.clone(), Message::GattClient), + dispatch: make_message_dispatcher(self.tx.clone(), Message::GattClient), }; let gatt_server_callbacks_dispatcher = GattServerCallbacksDispatcher { - dispatch: make_message_dispatcher(tx.clone(), Message::GattServer), + dispatch: make_message_dispatcher(self.tx.clone(), Message::GattServer), }; let gatt_scanner_callbacks_dispatcher = GattScannerCallbacksDispatcher { - dispatch: make_message_dispatcher(tx.clone(), Message::LeScanner), + dispatch: make_message_dispatcher(self.tx.clone(), Message::LeScanner), }; let gatt_scanner_inband_callbacks_dispatcher = GattScannerInbandCallbacksDispatcher { - dispatch: make_message_dispatcher(tx.clone(), Message::LeScannerInband), + dispatch: make_message_dispatcher(self.tx.clone(), Message::LeScannerInband), }; let gatt_adv_inband_callbacks_dispatcher = GattAdvInbandCallbacksDispatcher { - dispatch: make_message_dispatcher(tx.clone(), Message::LeAdvInband), + dispatch: make_message_dispatcher(self.tx.clone(), Message::LeAdvInband), }; let gatt_adv_callbacks_dispatcher = GattAdvCallbacksDispatcher { - dispatch: make_message_dispatcher(tx.clone(), Message::LeAdv), + dispatch: make_message_dispatcher(self.tx.clone(), Message::LeAdv), }; self.gatt.lock().unwrap().initialize( @@ -1820,6 +1826,20 @@ impl BluetoothGatt { pub fn handle_action(&mut self, action: GattActions) { match action { + GattActions::InvokeConnectionUpdated( + client_id, + addr, + interval, + latency, + timeout, + status, + ) => { + if let Some(client) = self.context_map.get_by_client_id(client_id) { + if let Some(cb) = self.context_map.get_callback_from_callback_id(client.cbid) { + cb.on_connection_updated(addr, interval, latency, timeout, status); + } + } + } GattActions::Disconnect(device) => { for client_id in self.context_map.get_client_ids_from_address(&device.address) { if let Some(conn_id) = @@ -2474,7 +2494,7 @@ impl IBluetoothGatt for BluetoothGatt { fn connection_parameter_update( &self, - _client_id: i32, + client_id: i32, addr: RawAddress, min_interval: i32, max_interval: i32, @@ -2492,6 +2512,23 @@ impl IBluetoothGatt for BluetoothGatt { min_ce_len, max_ce_len, ); + // If there's no connection for this client, LibBluetooth would not propagate a callback. + // Thus make up a success callback here. + if self.context_map.get_conn_id_from_address(client_id, &addr).is_none() { + let tx = self.tx.clone(); + tokio::spawn(async move { + let _ = tx + .send(Message::GattActions(GattActions::InvokeConnectionUpdated( + client_id, + addr, + max_interval, + latency, + timeout, + GattStatus::Success, + ))) + .await; + }); + } } fn client_set_preferred_phy( diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs index 95cface1470..b13e66b523b 100644 --- a/system/gd/rust/linux/stack/src/lib.rs +++ b/system/gd/rust/linux/stack/src/lib.rs @@ -303,7 +303,7 @@ impl Stack { bluetooth_media.lock().unwrap().initialize(); bluetooth.lock().unwrap().set_media(bluetooth_media.clone()); // Init Gatt and pass it to Bluetooth. - bluetooth_gatt.lock().unwrap().init_profiles(tx.clone(), api_tx.clone()); + bluetooth_gatt.lock().unwrap().init_profiles(api_tx.clone()); bluetooth_gatt.lock().unwrap().enable(true); bluetooth.lock().unwrap().set_gatt_and_init_scanner(bluetooth_gatt.clone()); // Init AdvertiseManager. It selects the stack per is_le_ext_adv_supported -- GitLab From 06e4b602afd154211f74791ee0ae9d8c99953898 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Wed, 25 Sep 2024 19:51:28 +0800 Subject: [PATCH 297/875] hh: Forward the GET/SET REPORT failures to UHID Currently when GET/SET REPORT request from UHID fails for any reason, we just silently drop it and doesn't notify UHID. This is against the expectation and may cause UHID to be stuck. This CL forwards the GET/SET REPORT replies on the failure cases, including when the request fails even before it's sent to the peripheral device. Bug: 307923455 Bug: 369748430 Test: m -j Test: Pair with a Lenovo Thinkpad Trackpoint keyboard. Then plug in a security key and verify it's usable. Flag: com.android.bluetooth.flags.forward_get_set_report_failure_to_uhid Change-Id: I7ae8e07d900b3dc7131094d650e1afbb091083f3 --- system/bta/hh/bta_hh_le.cc | 144 +++++++++++++++++++++++++++--------- system/btif/co/bta_hh_co.cc | 11 ++- system/btif/src/btif_hh.cc | 3 + 3 files changed, 122 insertions(+), 36 deletions(-) diff --git a/system/bta/hh/bta_hh_le.cc b/system/bta/hh/bta_hh_le.cc index 92fffab8a68..d4f940c9f7f 100644 --- a/system/bta/hh/bta_hh_le.cc +++ b/system/bta/hh/bta_hh_le.cc @@ -1785,6 +1785,24 @@ void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB* p_cb) { bta_hh_le_remove_dev_bg_conn(p_cb); } +/******************************************************************************* + * + * Function send_read_report_reply + * + * Description send GET_REPORT_EVT to application with the report data + * + * Returns void + * + ******************************************************************************/ +static void send_read_report_reply(uint8_t hid_handle, tBTA_HH_STATUS status, BT_HDR* rpt_data) { + tBTA_HH_HSDATA hs_data = { + .status = status, + .handle = hid_handle, + .rsp_data.p_rpt_data = rpt_data, + }; + (*bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH*)&hs_data); +} + /******************************************************************************* * * Function read_report_cb @@ -1802,10 +1820,17 @@ 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; + } + 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); + } return; } @@ -1819,38 +1844,42 @@ 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); + } return; } - tBTA_HH_HSDATA hs_data = {}; - hs_data.status = BTA_HH_ERR; - hs_data.handle = p_dev_cb->hid_handle; - if (status == GATT_SUCCESS) { - tBTA_HH_LE_RPT* p_rpt; - const gatt::Service* p_svc = BTA_GATTC_GetOwningService(conn_id, p_char->value_handle); - - p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, char_uuid, p_char->value_handle); - if (p_rpt != nullptr && len) { - BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1); - /* pack data send to app */ - hs_data.status = BTA_HH_OK; - p_buf->len = len + 1; - p_buf->layer_specific = 0; - p_buf->offset = 0; - - uint8_t* pp = (uint8_t*)(p_buf + 1); - /* attach report ID as the first byte of the report before sending it to - * USB HID driver */ - UINT8_TO_STREAM(pp, p_rpt->rpt_id); - memcpy(pp, value, len); - - hs_data.rsp_data.p_rpt_data = p_buf; - } + 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; - (*bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH*)&hs_data); - osi_free(hs_data.rsp_data.p_rpt_data); + if (status != GATT_SUCCESS) { + send_read_report_reply(hid_handle, BTA_HH_ERR, nullptr); + return; + } + + const gatt::Service* p_svc = BTA_GATTC_GetOwningService(conn_id, p_char->value_handle); + const tBTA_HH_LE_RPT* p_rpt = + bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, char_uuid, p_char->value_handle); + if (p_rpt == nullptr || len == 0) { + send_read_report_reply(hid_handle, BTA_HH_ERR, nullptr); + return; + } + + BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1); + p_buf->len = len + 1; + p_buf->layer_specific = 0; + p_buf->offset = 0; + + uint8_t* pp = (uint8_t*)(p_buf + 1); + /* attach report ID as the first byte of the report before sending it to + * USB HID driver */ + UINT8_TO_STREAM(pp, p_rpt->rpt_id); + memcpy(pp, value, len); + + send_read_report_reply(hid_handle, BTA_HH_OK, p_buf); + osi_free(p_buf); } /******************************************************************************* @@ -1866,8 +1895,11 @@ static void bta_hh_le_get_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type, uin tBTA_HH_LE_RPT* 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) { + 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); + } return; } @@ -1875,9 +1907,34 @@ static void bta_hh_le_get_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type, uin BtaGattQueue::ReadCharacteristic(p_cb->conn_id, p_rpt->char_inst_id, read_report_cb, p_cb); } +/******************************************************************************* + * + * Function send_write_report_reply + * + * Description send SET_REPORT_EVT to application with the report data + * + * Returns void + * + ******************************************************************************/ +static void send_write_report_reply(uint8_t hid_handle, tBTA_HH_STATUS status, uint16_t event) { + tBTA_HH_CBDATA cback_data = { + .status = status, + .handle = hid_handle, + }; + (*bta_hh_cb.p_cback)(event, (tBTA_HH*)&cback_data); +} + +/******************************************************************************* + * + * Function write_report_cb + * + * Description Process the Write report complete. + * + * Returns void + * + ******************************************************************************/ static void write_report_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/, const uint8_t* /*value*/, void* data) { - tBTA_HH_CBDATA cback_data; tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; uint16_t cb_evt = p_dev_cb->w4_evt; if (cb_evt == BTA_HH_EMPTY_EVT) { @@ -1885,10 +1942,17 @@ 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; + } + 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); + } return; } @@ -1896,14 +1960,22 @@ 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); + } return; } /* Set Report finished */ - cback_data.handle = p_dev_cb->hid_handle; - cback_data.status = (status == GATT_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR; - p_dev_cb->w4_evt = BTA_HH_EMPTY_EVT; - (*bta_hh_cb.p_cback)(cb_evt, (tBTA_HH*)&cback_data); + 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 { + send_write_report_reply(hid_handle, BTA_HH_ERR, cb_evt); + } } /******************************************************************************* * @@ -1921,6 +1993,9 @@ 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); + } return; } @@ -1932,6 +2007,9 @@ 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); + } osi_free(p_buf); return; } diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index 086ad115513..f60a7016481 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -1115,7 +1115,8 @@ void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, const uint8_t* p_ return; } - if (len == 0 || len > UHID_DATA_MAX) { + // len of zero is allowed, it's possible on failure case. + if (len > UHID_DATA_MAX) { log::warn("Invalid report size = {}", len); return; } @@ -1126,7 +1127,9 @@ void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, const uint8_t* p_ to_uhid.uhid.type = UHID_GET_REPORT_REPLY; to_uhid.uhid.u.get_report_reply.err = status; to_uhid.uhid.u.get_report_reply.size = len; - memcpy(to_uhid.uhid.u.get_report_reply.data, p_rpt, len); + if (len > 0) { + memcpy(to_uhid.uhid.u.get_report_reply.data, p_rpt, len); + } to_uhid_thread(p_dev->internal_send_fd, &to_uhid, uhid_calc_msg_len(&to_uhid.uhid, len)); return; @@ -1162,7 +1165,9 @@ void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, const uint8_t* p_ }, }, }; - memcpy(ev.u.get_report_reply.data, p_rpt, len); + if (len > 0) { + memcpy(ev.u.get_report_reply.data, p_rpt, len); + } uhid_write(p_dev->uhid.fd, &ev, uhid_calc_msg_len(&ev, len)); osi_free(context); diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index 49d13d28d0e..70c8e44d91f 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -692,6 +692,9 @@ 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); + } } } -- GitLab From 52a3a5bdd20316483e1db2f57f770bfbaddfc541 Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Mon, 14 Oct 2024 17:09:54 +0900 Subject: [PATCH 298/875] Add flag gatt_clear_cache_on_factory_reset Bug: 373284699 Bug: 359583862 Bug: 315241296 Test: m -j; Change-Id: I30351194530ad6beff7d5eed2c5251c82bf011d8 --- flags/gap.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/gap.aconfig b/flags/gap.aconfig index 96749aaede3..396b5a496b0 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -244,3 +244,13 @@ flag { description: "Support MSFT HCI extension for LE Scanning. go/bt-msft-aosp-dd" bug: "365787977" } + +flag { + name: "gatt_clear_cache_on_factory_reset" + namespace: "bluetooth" + description: "Clear GATT cache/hash on factory reset" + bug: "373284699" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From ec8920ad43b7f25d3ae6c71ff9747d26218fa522 Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Mon, 14 Oct 2024 09:20:02 +0000 Subject: [PATCH 299/875] Modified testBondLe_Reconnect test case Introduced new RPC call to support run time HID and HOGP service configuration. by default no Hid/HOGP services hence added HOGP service on bumble for testBondLe_Reconnect() test case Bug: 368045103 Test: atest -v PairingTest Change-Id: Ib2e09f485d0e1555baa09e5946fd89ba9b291b0d --- .../bluetooth/pairing/PairingTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java index 7d5e3108a49..441f5529920 100644 --- a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java +++ b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java @@ -90,6 +90,9 @@ public class PairingTest { private static final ParcelUuid BATTERY_UUID = ParcelUuid.fromString("0000180F-0000-1000-8000-00805F9B34FB"); + private static final ParcelUuid HOGP_UUID = + ParcelUuid.fromString("00001812-0000-1000-8000-00805F9B34FB"); + private static final Context sTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); private static final BluetoothAdapter sAdapter = @@ -409,6 +412,14 @@ public class PairingTest { testStep_restartBt(); assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice); + mBumble.gattBlocking() + .registerService( + GattProto.RegisterServiceRequest.newBuilder() + .setService( + GattProto.GattServiceParams.newBuilder() + .setUuid(HOGP_UUID.toString()) + .build()) + .build()); mBumble.hostBlocking() .advertise( @@ -441,6 +452,14 @@ public class PairingTest { .setUuid(BATTERY_UUID.toString()) .build()) .build()); + mBumble.gattBlocking() + .registerService( + GattProto.RegisterServiceRequest.newBuilder() + .setService( + GattProto.GattServiceParams.newBuilder() + .setUuid(HOGP_UUID.toString()) + .build()) + .build()); mBumble.hostBlocking() .advertise( -- GitLab From 34e6e38281f2be91d4ed847156fc9c4385a64a2e Mon Sep 17 00:00:00 2001 From: Etienne Ruffieux Date: Thu, 10 Oct 2024 14:03:22 +0000 Subject: [PATCH 300/875] Make SetBrowsedPlayer return current path and correct item count. Until now, SetBrowsedPlayer was returning the root id and the number of items present in root folder. It should instead return the current browsing path as changed by down and up events, and contain the corresponding number of files of the current folder. Bug: 297843126 Flag: com.android.bluetooth.flags.browsing_refactor Test: atest BluetoothInstrumentationTests Change-Id: Id1ac7f53d24f8df776112b8a109c53e1f1cec921 --- .../com_android_bluetooth_avrcp_target.cpp | 28 ++++++++-------- .../bluetooth/audio_util/MediaPlayerList.java | 32 +++++++++++++------ .../bluetooth/avrcp/AvrcpNativeInterface.java | 17 +++++----- .../bluetooth/avrcp/AvrcpTargetService.java | 7 ++-- system/btif/avrcp/avrcp_service.cc | 5 +-- system/gd/rust/topshim/btav/btav_shim.cc | 1 + system/include/hardware/avrcp/avrcp.h | 5 +-- system/profile/avrcp/device.cc | 22 +++++++------ .../avrcp_device_fuzz/avrcp_device_fuzz.cc | 5 +-- .../profile/avrcp/tests/avrcp_device_test.cc | 8 ++--- .../profile/avrcp/tests/avrcp_test_helper.h | 3 +- 11 files changed, 78 insertions(+), 55 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_avrcp_target.cpp b/android/app/jni/com_android_bluetooth_avrcp_target.cpp index 22f11e43458..ad1664191ae 100644 --- a/android/app/jni/com_android_bluetooth_avrcp_target.cpp +++ b/android/app/jni/com_android_bluetooth_avrcp_target.cpp @@ -64,7 +64,7 @@ static std::vector getNowPlayingList(); static uint16_t getCurrentPlayerId(); static std::vector getMediaPlayerList(); using SetBrowsedPlayerCb = MediaInterface::SetBrowsedPlayerCallback; -static void setBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCb); +static void setBrowsedPlayer(uint16_t player_id, std::string current_path, SetBrowsedPlayerCb); static uint16_t setAddressedPlayer(uint16_t player_id); using GetFolderItemsCb = MediaInterface::FolderItemsCallback; static void getFolderItems(uint16_t player_id, std::string media_id, GetFolderItemsCb cb); @@ -155,8 +155,9 @@ public: cb.Run(current_player); } - void SetBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCallback browse_cb) override { - setBrowsedPlayer(player_id, browse_cb); + void SetBrowsedPlayer(uint16_t player_id, std::string current_path, + SetBrowsedPlayerCallback browse_cb) override { + setBrowsedPlayer(player_id, current_path, browse_cb); } void SetAddressedPlayer(uint16_t player_id, SetAddressedPlayerCallback addressed_cb) override { @@ -683,7 +684,7 @@ static std::vector getMediaPlayerList() { return ret_list; } -static void setBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCb cb) { +static void setBrowsedPlayer(uint16_t player_id, std::string current_path, SetBrowsedPlayerCb cb) { log::debug(""); std::shared_lock lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); @@ -692,21 +693,22 @@ static void setBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCb cb) { } set_browsed_player_cb = cb; - sCallbackEnv->CallVoidMethod(mJavaInterface, method_setBrowsedPlayer, player_id); + jstring j_current_path = sCallbackEnv->NewStringUTF(current_path.c_str()); + sCallbackEnv->CallVoidMethod(mJavaInterface, method_setBrowsedPlayer, player_id, j_current_path); } static void setBrowsedPlayerResponseNative(JNIEnv* env, jobject /* object */, jint /* player_id */, - jboolean success, jstring root_id, jint num_items) { + jboolean success, jstring current_path, jint num_items) { log::debug(""); - std::string root; - if (root_id != nullptr) { - const char* value = env->GetStringUTFChars(root_id, nullptr); - root = std::string(value); - env->ReleaseStringUTFChars(root_id, value); + std::string path; + if (current_path != nullptr) { + const char* value = env->GetStringUTFChars(current_path, nullptr); + path = std::string(value); + env->ReleaseStringUTFChars(current_path, value); } - set_browsed_player_cb.Run(success == JNI_TRUE, root, num_items); + set_browsed_player_cb.Run(success == JNI_TRUE, path, num_items); } static uint16_t setAddressedPlayer(uint16_t player_id) { @@ -1091,7 +1093,7 @@ int register_com_android_bluetooth_avrcp_target(JNIEnv* env) { {"getNowPlayingList", "()Ljava/util/List;", &method_getNowPlayingList}, {"getCurrentPlayerId", "()I", &method_getCurrentPlayerId}, {"getMediaPlayerList", "()Ljava/util/List;", &method_getMediaPlayerList}, - {"setBrowsedPlayer", "(I)V", &method_setBrowsedPlayer}, + {"setBrowsedPlayer", "(ILjava/lang/String;)V", &method_setBrowsedPlayer}, {"setAddressedPlayer", "(I)I", &method_setAddressedPlayer}, {"getFolderItemsRequest", "(ILjava/lang/String;)V", &method_getFolderItemsRequest}, {"playItem", "(IZLjava/lang/String;)V", &method_playItem}, diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java index 1cbde5ec5e1..019e7e508ae 100644 --- a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java +++ b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java @@ -117,7 +117,7 @@ public class MediaPlayerList { void run(boolean availablePlayers, boolean addressedPlayers, boolean uids); } - public interface GetPlayerRootCallback { + public interface SetBrowsedPlayerCallback { void run(int playerId, boolean success, String rootId, int numItems); } @@ -371,22 +371,34 @@ public class MediaPlayerList { mMediaSessionManager.dispatchMediaKeyEvent(event, false); } - public void getPlayerRoot(int playerId, GetPlayerRootCallback cb) { + /** Sets the {@link #mBrowsingPlayerId} and returns the number of items in current path */ + public void setBrowsedPlayer(int playerId, String currentPath, SetBrowsedPlayerCallback cb) { if (Flags.browsingRefactor()) { if (!haveMediaBrowser(playerId)) { cb.run(playerId, false, "", 0); return; } + mBrowsingPlayerId = playerId; MediaBrowserWrapper wrapper = mMediaBrowserWrappers.get(playerId); - wrapper.getRootId( - (rootId) -> { - wrapper.getFolderItems( - rootId, - (parentId, itemList) -> { - cb.run(playerId, true, rootId, itemList.size()); - }); - }); + + // If player is different than actual or if the given path is wrong, process rootId + if (playerId != mBrowsingPlayerId || currentPath.equals("")) { + wrapper.getRootId( + (rootId) -> { + wrapper.getFolderItems( + rootId, + (parentId, itemList) -> { + cb.run(playerId, true, rootId, itemList.size()); + }); + }); + } else { + wrapper.getFolderItems( + currentPath, + (parentId, itemList) -> { + cb.run(playerId, true, currentPath, itemList.size()); + }); + } } else { // Fix PTS AVRCP/TG/MCN/CB/BI-02-C if (Utils.isPtsTestMode()) { diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java index 4d366ac1306..1dd106be573 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java @@ -172,24 +172,23 @@ public class AvrcpNativeInterface { return mAvrcpService.getMediaPlayerList(); } - // TODO(apanicke): This shouldn't be named setBrowsedPlayer as it doesn't actually connect - // anything internally. It just returns the number of items in the root folder. - void setBrowsedPlayer(int playerId) { - d("setBrowsedPlayer: playerId=" + playerId); - mAvrcpService.getPlayerRoot(playerId, (a, b, c, d) -> setBrowsedPlayerResponse(a, b, c, d)); + void setBrowsedPlayer(int playerId, String currentPath) { + d("setBrowsedPlayer: playerId=" + playerId + ", currentPath= " + currentPath); + mAvrcpService.setBrowsedPlayer( + playerId, currentPath, (a, b, c, d) -> setBrowsedPlayerResponse(a, b, c, d)); } - void setBrowsedPlayerResponse(int playerId, boolean success, String rootId, int numItems) { + void setBrowsedPlayerResponse(int playerId, boolean success, String currentPath, int numItems) { d( "setBrowsedPlayerResponse: playerId=" + playerId + " success=" + success - + " rootId=" - + rootId + + " currentPath=" + + currentPath + " numItems=" + numItems); - setBrowsedPlayerResponseNative(playerId, success, rootId, numItems); + setBrowsedPlayerResponseNative(playerId, success, currentPath, numItems); } int setAddressedPlayer(int playerId) { diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java index 19f580cf678..17bf92f8ecc 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java @@ -481,9 +481,10 @@ public class AvrcpTargetService extends ProfileService { return mMediaPlayerList.getMediaPlayerList(); } - /** See {@link MediaPlayerList#getPlayerRoot}. */ - void getPlayerRoot(int playerId, MediaPlayerList.GetPlayerRootCallback cb) { - mMediaPlayerList.getPlayerRoot(playerId, cb); + /** See {@link MediaPlayerList#setBrowsedPlayer}. */ + void setBrowsedPlayer( + int playerId, String currentPath, MediaPlayerList.SetBrowsedPlayerCallback cb) { + mMediaPlayerList.setBrowsedPlayer(playerId, currentPath, cb); } /** See {@link MediaPlayerList#setAddressedPlayer}. */ diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc index c76c281c636..8d1979c8ffc 100644 --- a/system/btif/avrcp/avrcp_service.cc +++ b/system/btif/avrcp/avrcp_service.cc @@ -226,7 +226,8 @@ public: base::Bind(&MediaInterface::GetAddressedPlayer, base::Unretained(wrapped_), bound_cb)); } - void SetBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCallback browse_cb) override { + void SetBrowsedPlayer(uint16_t player_id, std::string current_path, + SetBrowsedPlayerCallback browse_cb) override { auto cb_lambda = [](SetBrowsedPlayerCallback cb, bool success, std::string root_id, uint32_t num_items) { do_in_main_thread(base::BindOnce(cb, success, root_id, num_items)); @@ -235,7 +236,7 @@ public: auto bound_cb = base::Bind(cb_lambda, browse_cb); do_in_jni_thread(base::Bind(&MediaInterface::SetBrowsedPlayer, base::Unretained(wrapped_), - player_id, bound_cb)); + player_id, current_path, bound_cb)); } void SetAddressedPlayer(uint16_t player_id, SetAddressedPlayerCallback addressed_cb) override { diff --git a/system/gd/rust/topshim/btav/btav_shim.cc b/system/gd/rust/topshim/btav/btav_shim.cc index ed4f6fe3b08..2723d530e9b 100644 --- a/system/gd/rust/topshim/btav/btav_shim.cc +++ b/system/gd/rust/topshim/btav/btav_shim.cc @@ -53,6 +53,7 @@ public: void GetAddressedPlayer(GetAddressedPlayerCallback cb) override { cb.Run(currentPlayer_); } void SetBrowsedPlayer([[maybe_unused]] uint16_t player_id, + [[maybe_unused]] std::string current_path, [[maybe_unused]] SetBrowsedPlayerCallback browse_cb) override {} void SetAddressedPlayer([[maybe_unused]] uint16_t player_id, diff --git a/system/include/hardware/avrcp/avrcp.h b/system/include/hardware/avrcp/avrcp.h index 2698cc9f9ab..5b9544729d8 100644 --- a/system/include/hardware/avrcp/avrcp.h +++ b/system/include/hardware/avrcp/avrcp.h @@ -133,8 +133,9 @@ public: virtual void GetAddressedPlayer(GetAddressedPlayerCallback addressed_player) = 0; using SetBrowsedPlayerCallback = - base::Callback; - virtual void SetBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCallback browse_cb) = 0; + base::Callback; + virtual void SetBrowsedPlayer(uint16_t player_id, std::string current_path, + SetBrowsedPlayerCallback browse_cb) = 0; using SetAddressedPlayerCallback = base::Callback; virtual void SetAddressedPlayer(uint16_t player_id, SetAddressedPlayerCallback new_player) = 0; diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index 1851e88d346..cb40bca070c 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -1499,14 +1499,14 @@ void Device::HandleSetBrowsedPlayer(uint8_t label, std::shared_ptrGetPlayerId()); - media_interface_->SetBrowsedPlayer(pkt->GetPlayerId(), + media_interface_->SetBrowsedPlayer(pkt->GetPlayerId(), CurrentFolder(), base::Bind(&Device::SetBrowsedPlayerResponse, weak_ptr_factory_.GetWeakPtr(), label, pkt)); } void Device::SetBrowsedPlayerResponse(uint8_t label, std::shared_ptr pkt, - bool success, std::string root_id, uint32_t num_items) { - log::verbose("success={} root_id=\"{}\" num_items={}", success, root_id, num_items); + bool success, std::string current_path, uint32_t num_items) { + log::verbose("success={} current_path=\"{}\" num_items={}", success, current_path, num_items); if (!success) { auto response = SetBrowsedPlayerResponseBuilder::MakeBuilder(Status::INVALID_PLAYER_ID, 0x0000, @@ -1523,14 +1523,18 @@ void Device::SetBrowsedPlayerResponse(uint8_t label, std::shared_ptrGetPlayerId(); - - // Clear the path and push the new root. - current_path_ = std::stack(); - current_path_.push(root_id); + // SetBrowsedPlayer can be called to retrieve the current path + // and to verify that the player is still present, so we need to + // keep current_path_ as is if the player is already the one browsed. + // Otherwise, the current_path in the callback will contain the root id. + if (pkt->GetPlayerId() != curr_browsed_player_id_) { + curr_browsed_player_id_ = pkt->GetPlayerId(); + current_path_ = std::stack(); + current_path_.push(current_path); + } auto response = SetBrowsedPlayerResponseBuilder::MakeBuilder(Status::NO_ERROR, 0x0000, num_items, - 0, root_id); + 0, current_path); send_message(label, true, std::move(response)); } diff --git a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc index 5f69a6ac59d..3bfce3f1fa1 100644 --- a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc +++ b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc @@ -144,8 +144,9 @@ public: addressed_player.Run(currentPlayer); } using SetBrowsedPlayerCallback = - base::Callback; - void SetBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCallback browse_cb) { + base::Callback; + void SetBrowsedPlayer(uint16_t player_id, std::string /* current_path */, + SetBrowsedPlayerCallback browse_cb) { std::string rootId = mFdp->ConsumeRandomLengthString(kMaxLen); uint32_t numItems = mFdp->ConsumeIntegral(); browse_cb.Run(player_id, rootId, numItems); diff --git a/system/profile/avrcp/tests/avrcp_device_test.cc b/system/profile/avrcp/tests/avrcp_device_test.cc index 24cf0ff87df..1e1de8646e2 100644 --- a/system/profile/avrcp/tests/avrcp_device_test.cc +++ b/system/profile/avrcp/tests/avrcp_device_test.cc @@ -1130,11 +1130,11 @@ TEST_F(AvrcpDeviceTest, setBrowsedPlayerTest) { test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr, nullptr); - EXPECT_CALL(interface, SetBrowsedPlayer(_, _)) + EXPECT_CALL(interface, SetBrowsedPlayer(_, "", _)) .Times(3) - .WillOnce(InvokeCb<1>(true, "", 0)) - .WillOnce(InvokeCb<1>(false, "", 0)) - .WillOnce(InvokeCb<1>(true, "", 2)); + .WillOnce(InvokeCb<2>(true, "", 0)) + .WillOnce(InvokeCb<2>(false, "", 0)) + .WillOnce(InvokeCb<2>(true, "", 2)); auto not_browsable_rsp = SetBrowsedPlayerResponseBuilder::MakeBuilder( Status::PLAYER_NOT_BROWSABLE, 0x0000, 0, 0, ""); diff --git a/system/profile/avrcp/tests/avrcp_test_helper.h b/system/profile/avrcp/tests/avrcp_test_helper.h index 7a2f63ab2a7..df254e3e18e 100644 --- a/system/profile/avrcp/tests/avrcp_test_helper.h +++ b/system/profile/avrcp/tests/avrcp_test_helper.h @@ -45,7 +45,8 @@ public: MOCK_METHOD1(GetMediaPlayerList, void(MediaInterface::MediaListCallback)); MOCK_METHOD1(GetAddressedPlayer, void(MediaInterface::GetAddressedPlayerCallback)); MOCK_METHOD3(GetFolderItems, void(uint16_t, std::string, MediaInterface::FolderItemsCallback)); - MOCK_METHOD2(SetBrowsedPlayer, void(uint16_t, MediaInterface::SetBrowsedPlayerCallback)); + MOCK_METHOD3(SetBrowsedPlayer, + void(uint16_t, std::string, MediaInterface::SetBrowsedPlayerCallback)); MOCK_METHOD2(SetAddressedPlayer, void(uint16_t, MediaInterface::SetAddressedPlayerCallback)); MOCK_METHOD3(PlayItem, void(uint16_t, bool, std::string)); MOCK_METHOD1(SetActiveDevice, void(const RawAddress&)); -- GitLab From 6ddf7c24cf78f18256677ff8bd853bd2882a1525 Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Wed, 9 Oct 2024 03:48:09 +0000 Subject: [PATCH 301/875] interop: extended truncated report map for specific device The HID specification allows report maps to exceed 512 bytes. However, the Bluetooth specification requires all GATT attributes to be 512 bytes or less. This creates an interoperability issue when a device manufacturer implements a HID report map as a single GATT characteristic. This change handles this edge case by extending the report map after receiving the initial 512 bytes. This ensures compatibility with both HID and Bluetooth standards. As this workaround is currently implemented for one specific device, the extra bytes of the report map exist as static const arrays; if more devices need such workarounds, it is suggested to store the report map in a separate file which can be loaded from the file system. Bug: 332761737 Tag: #floss Test: mmm packages/modules/Bluetooth Test: Manual test on Brya, Brydge keyboard working Flag: EXEMPT, interop change and apply only to one and currently non-functioning device Change-Id: If9eb2e5e2828d0dea17f486207421525ffcccffc --- system/bta/hh/bta_hh_le.cc | 33 ++++++++++++++++++++++++++++--- system/conf/interop_database.conf | 5 +++++ system/device/include/interop.h | 4 ++++ system/device/src/interop.cc | 1 + 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/system/bta/hh/bta_hh_le.cc b/system/bta/hh/bta_hh_le.cc index 92fffab8a68..54b6cc2739d 100644 --- a/system/bta/hh/bta_hh_le.cc +++ b/system/bta/hh/bta_hh_le.cc @@ -1258,16 +1258,43 @@ static void read_hid_info_cb(tCONN_ID /*conn_id*/, tGATT_STATUS status, uint16_t STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp); } +static void get_iop_device_rpt_map(tBTA_HH_LE_HID_SRVC* p_srvc, uint16_t* len, uint8_t* desc) { + static const uint8_t residual_report_map[] = { + 0x31, 0x81, 0x02, 0xC0, 0x05, 0x0D, 0x09, 0x54, 0x25, 0x05, 0x75, 0x07, 0x95, 0x01, + 0x81, 0x02, 0x05, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x01, 0x15, 0x00, 0x25, 0x01, + 0x75, 0x01, 0x95, 0x01, 0x81, 0x02, 0x05, 0x0D, 0x55, 0x0C, 0x66, 0x01, 0x10, 0x47, + 0xFF, 0xFF, 0x00, 0x00, 0x27, 0xFF, 0xFF, 0x00, 0x00, 0x75, 0x10, 0x95, 0x01, 0x09, + 0x56, 0x81, 0x02, 0x85, 0x12, 0x09, 0x55, 0x09, 0x59, 0x25, 0x0F, 0x75, 0x08, 0x95, + 0x01, 0xB1, 0x02, 0x06, 0x00, 0xFF, 0x85, 0x11, 0x09, 0xC5, 0x15, 0x00, 0x26, 0xFF, + 0x00, 0x75, 0x08, 0x96, 0x00, 0x01, 0xB1, 0x02, 0xC0}; + + p_srvc->rpt_map = (uint8_t*)osi_malloc(*len + sizeof(residual_report_map)); + STREAM_TO_ARRAY(p_srvc->rpt_map, desc, *len); + memcpy(&(p_srvc->rpt_map[*len]), residual_report_map, sizeof(residual_report_map)); + *len = *len + sizeof(residual_report_map); +} void bta_hh_le_save_report_map(tBTA_HH_DEV_CB* p_dev_cb, uint16_t len, uint8_t* desc) { tBTA_HH_LE_HID_SRVC* p_srvc = &p_dev_cb->hid_srvc; osi_free_and_reset((void**)&p_srvc->rpt_map); if (len > 0) { - p_srvc->rpt_map = (uint8_t*)osi_malloc(len); + // Workaround for HID report maps exceeding 512 bytes. The HID spec allows for large report + // maps, but Bluetooth GATT attributes have a maximum size of 512 bytes. This interop workaround + // extended a received truncated report map with stored values. + // TODO: The workaround is specific to one device, if more devices need the similar interop + // workaround in the future, the “cached” report mapped should be stored in a separate file. + if (len == GATT_MAX_ATTR_LEN && + interop_match_vendor_product_ids(INTEROP_HOGP_LONG_REPORT, p_dev_cb->dscp_info.vendor_id, + p_dev_cb->dscp_info.product_id)) { + get_iop_device_rpt_map(p_srvc, &len, desc); + } else { + p_srvc->rpt_map = (uint8_t*)osi_malloc(len); + + uint8_t* pp = desc; + STREAM_TO_ARRAY(p_srvc->rpt_map, pp, len); + } - uint8_t* pp = desc; - STREAM_TO_ARRAY(p_srvc->rpt_map, pp, len); p_srvc->descriptor.dl_len = len; p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc.rpt_map; } diff --git a/system/conf/interop_database.conf b/system/conf/interop_database.conf index c7827c41af4..155fc228694 100644 --- a/system/conf/interop_database.conf +++ b/system/conf/interop_database.conf @@ -867,3 +867,8 @@ BSK10 = Name_Based # Peer can request proper latency based on its power state later. [INTEROP_HID_PREF_CONN_ZERO_LATENCY] 00:15:9E = Address_Based + +# Some HOGP devices have the report map longer than the maximum GATT attribute value length (512 +# bytes). +[INTEROP_HOGP_LONG_REPORT] +0x03f6-0xa001 = Vndr_Prdt_Based diff --git a/system/device/include/interop.h b/system/device/include/interop.h index 25967aafa30..6a05e5ff0a6 100644 --- a/system/device/include/interop.h +++ b/system/device/include/interop.h @@ -356,6 +356,10 @@ 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). + INTEROP_HOGP_LONG_REPORT, + END_OF_INTEROP_LIST } interop_feature_t; diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc index bcb491f33f1..eea1a62fc30 100644 --- a/system/device/src/interop.cc +++ b/system/device/src/interop.cc @@ -393,6 +393,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { CASE_RETURN_STR(INTEROP_MULTIPLE_HOGP_SERVICE_CHOOSE_THIRD); CASE_RETURN_STR(INTEROP_A2DP_SKIP_SDP_DURING_RECONNECTION); CASE_RETURN_STR(INTEROP_HID_PREF_CONN_ZERO_LATENCY); + CASE_RETURN_STR(INTEROP_HOGP_LONG_REPORT); } return UNKNOWN_INTEROP_FEATURE; } -- GitLab From d5f1667ee72cd2c7820d15eb3bebdf7312e0efb7 Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Wed, 9 Oct 2024 05:24:44 +0000 Subject: [PATCH 302/875] interop: force a MTU exchange for certain keyboards Some HOGP keyboards expect a MTU exchange flow as part of the initialization to function properly. Trigger a MTU exchange for a device in the interop list. Bug: 332761737 Tag: #floss Test: mmm packages/modules/Bluetooth Test: Manual test on Brya, Brydge keyboard working Flag: EXEMPT, interop change and apply only to one and currently non-functioning device Change-Id: I2efb78cae6072fb8fdd74a87628fb71804869164 --- system/bta/hh/bta_hh_le.cc | 7 +++++++ system/conf/interop_database.conf | 4 ++++ system/device/include/interop.h | 3 +++ system/device/src/interop.cc | 1 + 4 files changed, 15 insertions(+) diff --git a/system/bta/hh/bta_hh_le.cc b/system/bta/hh/bta_hh_le.cc index 54b6cc2739d..8b8ff3088ff 100644 --- a/system/bta/hh/bta_hh_le.cc +++ b/system/bta/hh/bta_hh_le.cc @@ -619,6 +619,13 @@ static void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB* p_cb) { bta_hh_le_register_input_notif(p_cb, p_cb->mode, true); bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL); + // Some HOGP devices requires MTU exchange be part of the initial setup to function. The size of + // the requested MTU does not matter as long as the procedure is triggered. + if (interop_match_vendor_product_ids(INTEROP_HOGP_FORCE_MTU_EXCHANGE, p_cb->dscp_info.vendor_id, + p_cb->dscp_info.product_id)) { + BTA_GATTC_ConfigureMTU(p_cb->conn_id, GATT_MAX_MTU_SIZE); + } + if (!com::android::bluetooth::flags::prevent_hogp_reconnect_when_connected()) { if (kBTA_HH_LE_RECONN && p_cb->status == BTA_HH_OK) { bta_hh_le_add_dev_bg_conn(p_cb); diff --git a/system/conf/interop_database.conf b/system/conf/interop_database.conf index 155fc228694..588d567a053 100644 --- a/system/conf/interop_database.conf +++ b/system/conf/interop_database.conf @@ -872,3 +872,7 @@ BSK10 = Name_Based # bytes). [INTEROP_HOGP_LONG_REPORT] 0x03f6-0xa001 = Vndr_Prdt_Based + +# Some HOGP devices requires MTU exchange be part of the initial setup to function. +[INTEROP_HOGP_FORCE_MTU_EXCHANGE] +0x03f6-0xa001 = Vndr_Prdt_Based diff --git a/system/device/include/interop.h b/system/device/include/interop.h index 6a05e5ff0a6..1d520b0c08b 100644 --- a/system/device/include/interop.h +++ b/system/device/include/interop.h @@ -360,6 +360,9 @@ typedef enum { // bytes). INTEROP_HOGP_LONG_REPORT, + // Some HOGP devices requires MTU exchange be part of the initial setup to function. + INTEROP_HOGP_FORCE_MTU_EXCHANGE, + END_OF_INTEROP_LIST } interop_feature_t; diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc index eea1a62fc30..78b1b70b348 100644 --- a/system/device/src/interop.cc +++ b/system/device/src/interop.cc @@ -394,6 +394,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { CASE_RETURN_STR(INTEROP_A2DP_SKIP_SDP_DURING_RECONNECTION); CASE_RETURN_STR(INTEROP_HID_PREF_CONN_ZERO_LATENCY); CASE_RETURN_STR(INTEROP_HOGP_LONG_REPORT); + CASE_RETURN_STR(INTEROP_HOGP_FORCE_MTU_EXCHANGE); } return UNKNOWN_INTEROP_FEATURE; } -- GitLab From 9ada0f5e1be5296474c6a69e178afd41cfc6f1b1 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 14 Oct 2024 13:37:00 -0700 Subject: [PATCH 303/875] PbapVcard: Apply pattern matching str.split(regex, n) is the same as Pattern.compile(regex).split(str, n). Except that the second can be compiled once why the first need to be recompile everytime it is invoked Bug: 371471052 Flag: Exempt refactor Test: atest BluetoothInstrumentationTests Change-Id: I0363ef188571db5e1c3a8745a377fde06d8894ff --- .../pbap/BluetoothPbapVcardManager.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java index fba3b07bb46..f3a08ec365f 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java @@ -53,10 +53,11 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.regex.Pattern; // Next tag value for ContentProfileErrorReportUtils.report(): 22 public class BluetoothPbapVcardManager { - private static final String TAG = "BluetoothPbapVcardManager"; + private static final String TAG = BluetoothPbapVcardManager.class.getSimpleName(); private ContentResolver mResolver; @@ -87,6 +88,11 @@ public class BluetoothPbapVcardManager { private static final int NEED_SEND_BODY = -1; + private static final String SEPARATOR = System.getProperty("line.separator"); + private static final Pattern SEPARATOR_PATTERN = Pattern.compile(SEPARATOR); + private static final Pattern PROPERTY_PATTERN = Pattern.compile("[;:]"); + private static final Pattern ATTRIBUTE_PATTERN = Pattern.compile(":"); + public BluetoothPbapVcardManager(final Context context) { mContext = context; mResolver = mContext.getContentResolver(); @@ -1100,7 +1106,7 @@ public class BluetoothPbapVcardManager { byte[] filter, byte[] selector, String vcardselectorop, - boolean vCardSelct) { + boolean vCardSelect) { long timestamp = System.currentTimeMillis(); HandlerForStringBuffer buffer = null; @@ -1121,7 +1127,7 @@ public class BluetoothPbapVcardManager { break; } String vcard = composer.createOneEntry(vcardType21); - if (vCardSelct) { + if (vCardSelect) { if (!vcardselector.checkVCardSelector(vcard, vcardselectorop)) { Log.e(TAG, "Checking vcard selector for call log"); ContentProfileErrorReportUtils.report( @@ -1176,7 +1182,7 @@ public class BluetoothPbapVcardManager { buffer.writeVCard(vcard); } } - if (needSendBody != NEED_SEND_BODY && vCardSelct) { + if (needSendBody != NEED_SEND_BODY && vCardSelect) { return pbSize; } } finally { @@ -1194,12 +1200,11 @@ public class BluetoothPbapVcardManager { } public String stripTelephoneNumber(String vCard) { - String separator = System.getProperty("line.separator"); - String[] attr = vCard.split(separator); + String[] attr = SEPARATOR_PATTERN.split(vCard); String stripedVCard = ""; for (int i = 0; i < attr.length; i++) { if (attr[i].startsWith("TEL")) { - String[] vTagAndTel = attr[i].split(":", 2); + String[] vTagAndTel = ATTRIBUTE_PATTERN.split(attr[i], 2); int telLenBefore = vTagAndTel[1].length(); // Remove '-', '(', ')' or ' ' from TEL number vTagAndTel[1] = @@ -1217,7 +1222,7 @@ public class BluetoothPbapVcardManager { for (int i = 0; i < attr.length; i++) { if (!attr[i].isEmpty()) { - stripedVCard = stripedVCard.concat(attr[i] + separator); + stripedVCard = stripedVCard.concat(attr[i] + SEPARATOR); } } Log.v(TAG, "vCard with stripped telephone no.: " + stripedVCard); @@ -1253,7 +1258,6 @@ public class BluetoothPbapVcardManager { } } - private static final String SEPARATOR = System.getProperty("line.separator"); private final byte[] mFilter; // This function returns true if the attributes needs to be included in the filtered vcard. @@ -1284,7 +1288,7 @@ public class BluetoothPbapVcardManager { if (mFilter == null) { return vCard; } - String[] lines = vCard.split(SEPARATOR); + String[] lines = SEPARATOR_PATTERN.split(vCard); StringBuilder filteredVCard = new StringBuilder(); boolean filteredIn = false; @@ -1292,7 +1296,7 @@ public class BluetoothPbapVcardManager { // Check whether the current property is changing (ignoring multi-line properties) // and determine if the current property is filtered in. if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) { - String currentProp = line.split("[;:]")[0]; + String currentProp = PROPERTY_PATTERN.split(line, 2)[0]; filteredIn = true; for (FilterBit bit : FilterBit.values()) { @@ -1352,7 +1356,6 @@ public class BluetoothPbapVcardManager { } } - private static final String SEPARATOR = System.getProperty("line.separator"); private final byte[] mSelector; PropertySelector(byte[] selector) { @@ -1463,7 +1466,7 @@ public class BluetoothPbapVcardManager { @VisibleForTesting static String getNameFromVCard(String vCard) { - String[] lines = vCard.split(PropertySelector.SEPARATOR); + String[] lines = SEPARATOR_PATTERN.split(vCard); String name = ""; for (String line : lines) { if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) { @@ -1477,10 +1480,10 @@ public class BluetoothPbapVcardManager { } private static boolean doesVCardHaveProperty(String vCard, String property) { - String[] lines = vCard.split(PropertySelector.SEPARATOR); + String[] lines = SEPARATOR_PATTERN.split(vCard); for (String line : lines) { if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) { - String currentProperty = line.split("[;:]")[0]; + String currentProperty = PROPERTY_PATTERN.split(line)[0]; if (property.equals(currentProperty)) { return true; } -- GitLab From 1cb695c659fe54720c6a79cbc5a320c625000b60 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 14 Oct 2024 14:01:14 -0700 Subject: [PATCH 304/875] MapbMessage: Apply pattern matching str.split(regex, n) is the same as Pattern.compile(regex).split(str, n). Except that the second can be compiled once why the first need to be recompile everytime it is invoked Bug: 371471052 Flag: Exempt refactor Test: atest BluetoothInstrumentationTests Change-Id: Iccfad5430d292ff5082b3701ac48383aab7ed5e2 --- .../bluetooth/map/BluetoothMapbMessage.java | 46 ++++++++++--------- .../map/BluetoothMapbMessageMime.java | 28 ++++++----- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java index 5af521c49cb..7b7d879d0a2 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java @@ -32,11 +32,15 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; // Next tag value for ContentProfileErrorReportUtils.report(): 10 public abstract class BluetoothMapbMessage { - protected static final String TAG = "BluetoothMapbMessage"; + protected static final String TAG = BluetoothMapbMessage.class.getSimpleName(); + + private static final Pattern UNESCAPE_COLON = Pattern.compile("[^\\\\]:"); + protected static final Pattern COLON = Pattern.compile(":"); private String mVersionString = "VERSION:1.0"; @@ -263,34 +267,34 @@ public abstract class BluetoothMapbMessage { while (!line.contains("END:VCARD")) { line = line.trim(); if (line.startsWith("N:")) { - parts = line.split("[^\\\\]:"); // Split on "un-escaped" ':' + parts = UNESCAPE_COLON.split(line); if (parts.length == 2) { name = parts[1]; } else { name = ""; } } else if (line.startsWith("FN:")) { - parts = line.split("[^\\\\]:"); // Split on "un-escaped" ':' + parts = UNESCAPE_COLON.split(line); if (parts.length == 2) { formattedName = parts[1]; } else { formattedName = ""; } } else if (line.startsWith("TEL:")) { - parts = line.split("[^\\\\]:"); // Split on "un-escaped" ':' + parts = UNESCAPE_COLON.split(line); if (parts.length == 2) { - String[] subParts = parts[1].split("[^\\\\];"); + String[] subParts = UNESCAPE_COLON.split(parts[1]); if (phoneNumbers == null) { - phoneNumbers = new ArrayList(1); + phoneNumbers = new ArrayList<>(1); } // only keep actual phone number phoneNumbers.add(subParts[subParts.length - 1]); } // Empty phone number - ignore } else if (line.startsWith("EMAIL:")) { - parts = line.split("[^\\\\]:"); // Split on "un-escaped" : + parts = UNESCAPE_COLON.split(line); if (parts.length == 2) { - String[] subParts = parts[1].split("[^\\\\];"); + String[] subParts = UNESCAPE_COLON.split(parts[1]); if (emailAddresses == null) { emailAddresses = new ArrayList(1); } @@ -299,9 +303,9 @@ public abstract class BluetoothMapbMessage { } // Empty email address entry - ignore } else if (line.startsWith("X-BT-UCI:")) { - parts = line.split("[^\\\\]:"); // Split on "un-escaped" : + parts = UNESCAPE_COLON.split(line); if (parts.length == 2) { - String[] subParts = parts[1].split("[^\\\\];"); + String[] subParts = UNESCAPE_COLON.split(parts[1]); if (btUcis == null) { btUcis = new ArrayList(1); } @@ -309,9 +313,9 @@ public abstract class BluetoothMapbMessage { } // Empty UCIentry - ignore } else if (line.startsWith("X-BT-UID:")) { - parts = line.split("[^\\\\]:"); // Split on "un-escaped" : + parts = UNESCAPE_COLON.split(line); if (parts.length == 2) { - String[] subParts = parts[1].split("[^\\\\];"); + String[] subParts = UNESCAPE_COLON.split(parts[1]); if (btUids == null) { btUids = new ArrayList(1); } @@ -514,7 +518,7 @@ public abstract class BluetoothMapbMessage { // Parse the properties - which end with either a VCARD or a BENV while (!line.contains("BEGIN:VCARD") && !line.contains("BEGIN:BENV")) { if (line.contains("STATUS")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { if (arg[1].trim().equals("READ")) { status = true; @@ -528,7 +532,7 @@ public abstract class BluetoothMapbMessage { } } if (line.contains("EXTENDEDDATA")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { String value = arg[1].trim(); // FIXME what should we do with this @@ -536,7 +540,7 @@ public abstract class BluetoothMapbMessage { } } if (line.contains("TYPE")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { String value = arg[1].trim(); /* Will throw IllegalArgumentException if value is wrong */ @@ -569,7 +573,7 @@ public abstract class BluetoothMapbMessage { } } if (line.contains("FOLDER")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { folder = arg[1].trim(); } @@ -652,7 +656,7 @@ public abstract class BluetoothMapbMessage { parseMsgInit(); while (!line.contains("END:")) { if (line.contains("PARTID:")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { try { Long unusedId = Long.parseLong(arg[1].trim()); @@ -669,7 +673,7 @@ public abstract class BluetoothMapbMessage { throw new IllegalArgumentException("Missing value for 'PARTID': " + line); } } else if (line.contains("ENCODING:")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { mEncoding = arg[1].trim(); // If needed validation will be done when the value is used @@ -677,7 +681,7 @@ public abstract class BluetoothMapbMessage { throw new IllegalArgumentException("Missing value for 'ENCODING': " + line); } } else if (line.contains("CHARSET:")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { mCharset = arg[1].trim(); // If needed validation will be done when the value is used @@ -685,7 +689,7 @@ public abstract class BluetoothMapbMessage { throw new IllegalArgumentException("Missing value for 'CHARSET': " + line); } } else if (line.contains("LANGUAGE:")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { String unusedLanguage = arg[1].trim(); // If needed validation will be done when the value is used @@ -693,7 +697,7 @@ public abstract class BluetoothMapbMessage { throw new IllegalArgumentException("Missing value for 'LANGUAGE': " + line); } } else if (line.contains("LENGTH:")) { - String[] arg = line.split(":"); + String[] arg = COLON.split(line); if (arg != null && arg.length == 2) { try { mBMsgLength = Integer.parseInt(arg[1].trim()); diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java index 546fcb8fc72..6e5204576a9 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java @@ -37,9 +37,15 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.UUID; +import java.util.regex.Pattern; // Next tag value for ContentProfileErrorReportUtils.report(): 8 public class BluetoothMapbMessageMime extends BluetoothMapbMessage { + private static final Pattern NEW_LINE = Pattern.compile("\r\n"); + private static final Pattern TWO_NEW_LINE = Pattern.compile("\r\n\r\n"); + private static final Pattern SEMI_COLON = Pattern.compile(";"); + private static final Pattern BOUNDARY_PATTERN = Pattern.compile("boundary[\\s]*="); + private static final Pattern CHARSET_PATTERN = Pattern.compile("charset[\\s]*="); public static class MimePart { public long mId = INVALID_VALUE; /* The _id from the content provider, can be used to @@ -559,7 +565,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { * headers were found. */ private String parseMimeHeaders(String hdrPart) { - String[] headers = hdrPart.split("\r\n"); + String[] headers = NEW_LINE.split(hdrPart); Log.d(TAG, "Header count=" + headers.length); String header; @@ -574,7 +580,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { if (header.trim().isEmpty()) { continue; } - String[] headerParts = header.split(":", 2); + String[] headerParts = COLON.split(header, 2); if (headerParts.length != 2) { // We treat the remaining content as plain text. StringBuilder remaining = new StringBuilder(); @@ -622,12 +628,12 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { } else if (headerType.contains("MIME-VERSION")) { /* The mime version is not needed */ } else if (headerType.contains("CONTENT-TYPE")) { - String[] contentTypeParts = headerValue.split(";"); + String[] contentTypeParts = SEMI_COLON.split(headerValue); mContentType = contentTypeParts[0]; // Extract the boundary if it exists for (int j = 1, n = contentTypeParts.length; j < n; j++) { if (contentTypeParts[j].contains("boundary")) { - mBoundary = contentTypeParts[j].split("boundary[\\s]*=", 2)[1].trim(); + mBoundary = BOUNDARY_PATTERN.split(contentTypeParts[j], 2)[1].trim(); // removing quotes from boundary string if ((mBoundary.charAt(0) == '\"') && (mBoundary.charAt(mBoundary.length() - 1) == '\"')) { @@ -635,7 +641,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { } Log.d(TAG, "Boundary tag=" + mBoundary); } else if (contentTypeParts[j].contains("charset")) { - mCharset = contentTypeParts[j].split("charset[\\s]*=", 2)[1].trim(); + mCharset = CHARSET_PATTERN.split(contentTypeParts[j], 2)[1].trim(); } } } else if (headerType.contains("CONTENT-TRANSFER-ENCODING")) { @@ -653,12 +659,12 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { } private void parseMimePart(String partStr) { - String[] parts = partStr.split("\r\n\r\n", 2); // Split the header from the body + String[] parts = TWO_NEW_LINE.split(partStr, 2); // Split the header from the body MimePart newPart = addMimePart(); String partEncoding = mMyEncoding; /* Use the overall encoding as default */ String body; - String[] headers = parts[0].split("\r\n"); + String[] headers = NEW_LINE.split(parts[0]); Log.d(TAG, "parseMimePart: headers count=" + headers.length); if (parts.length != 2) { @@ -672,7 +678,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { continue; } - String[] headerParts = header.split(":", 2); + String[] headerParts = COLON.split(header, 2); if (headerParts.length != 2) { Log.w(TAG, "part-Header not formatted correctly: "); ContentProfileErrorReportUtils.report( @@ -687,13 +693,13 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { String headerType = Ascii.toUpperCase(headerParts[0]); String headerValue = headerParts[1].trim(); if (headerType.contains("CONTENT-TYPE")) { - String[] contentTypeParts = headerValue.split(";"); + String[] contentTypeParts = SEMI_COLON.split(headerValue); newPart.mContentType = contentTypeParts[0]; // Extract the boundary if it exists for (int j = 1, n = contentTypeParts.length; j < n; j++) { String value = Ascii.toLowerCase(contentTypeParts[j]); if (value.contains("charset")) { - newPart.mCharsetName = value.split("charset[\\s]*=", 2)[1].trim(); + newPart.mCharsetName = CHARSET_PATTERN.split(value, 2)[1].trim(); } } } else if (headerType.contains("CONTENT-LOCATION")) { @@ -772,7 +778,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { String messageBody = null; message = message.replaceAll("\\r\\n[ \\\t]+", ""); // Unfold - messageParts = message.split("\r\n\r\n", 2); // Split the header from the body + messageParts = TWO_NEW_LINE.split(message, 2); // Split the header from the body if (messageParts.length != 2) { // Handle entire message as plain text messageBody = message; -- GitLab From 04410c9d3756716f6e7eca0cec2a509d68f5c5c1 Mon Sep 17 00:00:00 2001 From: Sarvesh Kalwit Date: Fri, 27 Sep 2024 23:07:40 +0000 Subject: [PATCH 305/875] Implement a APCF->MSFT converter utility Bug: 360391998 Bug: 365787977 Flag: EXEMPT, Floss change Test: m -j Change-Id: I3d0ee366c42f5aa5d50a1ca36ca6142b402d8fbb --- .../bluetooth/le_scan/MsftAdvMonitor.java | 77 +++++++++++++++++++ .../bluetooth/le_scan/MsftAdvMonitorTest.java | 72 +++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 android/app/tests/unit/src/com/android/bluetooth/le_scan/MsftAdvMonitorTest.java diff --git a/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java b/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java index 8d67f2a8348..acf80cfd76e 100644 --- a/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java +++ b/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java @@ -16,7 +16,28 @@ package com.android.bluetooth.le_scan; +import android.bluetooth.le.ScanFilter; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.UUID; + +/** Helper class used to manage MSFT Advertisement Monitors. */ class MsftAdvMonitor { + /* Only pattern filtering is supported currently */ + // private static final int MSFT_CONDITION_TYPE_ALL = 0x00; + private static final int MSFT_CONDITION_TYPE_PATTERNS = 0x01; + // private static final int MSFT_CONDITION_TYPE_UUID = 0x02; + // private static final int MSFT_CONDITION_TYPE_IRK = 0x03; + // private static final int MSFT_CONDITION_TYPE_ADDRESS = 0x04; + + // Hardcoded values taken from CrOS defaults + private static final byte RSSI_THRESHOLD_HIGH = (byte) 0xBF; // 191 + private static final byte RSSI_THRESHOLD_LOW = (byte) 0xB0; // 176 + private static final byte RSSI_THRESHOLD_LOW_TIME_INTERVAL = (byte) 0x28; // 40s + private static final byte RSSI_SAMPLING_PERIOD = (byte) 0x05; // 500ms + private static final int FILTER_PATTERN_START_POSITION = (byte) 0x00; + static class Monitor { public byte rssi_threshold_high; public byte rssi_threshold_low; @@ -35,4 +56,60 @@ class MsftAdvMonitor { byte addr_type; String bd_addr; } + + private final Monitor mMonitor = new Monitor(); + private final ArrayList mPatterns = new ArrayList<>(); + private final Address mAddress = new Address(); + + // Constructor that converts an APCF-friendly filter to an MSFT-friendly format + public MsftAdvMonitor(ScanFilter filter) { + // Hardcoded values taken from CrOS defaults + mMonitor.rssi_threshold_high = RSSI_THRESHOLD_HIGH; + mMonitor.rssi_threshold_low = RSSI_THRESHOLD_LOW; + mMonitor.rssi_threshold_low_time_interval = RSSI_THRESHOLD_LOW_TIME_INTERVAL; + mMonitor.rssi_sampling_period = RSSI_SAMPLING_PERIOD; + mMonitor.condition_type = MSFT_CONDITION_TYPE_PATTERNS; + + if (filter.getServiceDataUuid() != null && filter.getServiceDataMask() == null) { + Pattern pattern = new Pattern(); + pattern.ad_type = (byte) 0x16; // Bluetooth Core Spec Part A, Section 1 + pattern.start_byte = FILTER_PATTERN_START_POSITION; + + // Extract the 16-bit UUID (third and fourth bytes) from the 128-bit + // UUID in reverse endianness + UUID uuid = filter.getServiceDataUuid().getUuid(); + ByteBuffer bb = ByteBuffer.allocate(16); // 16 byte (128 bit) UUID + bb.putLong(uuid.getMostSignificantBits()); + bb.putLong(uuid.getLeastSignificantBits()); + pattern.pattern = new byte[] {bb.get(3), bb.get(2)}; + + mPatterns.add(pattern); + } else if (filter.getAdvertisingData() != null + && filter.getAdvertisingData().length != 0 + && (filter.getAdvertisingDataMask() == null + || filter.getAdvertisingDataMask().length == 0)) { + Pattern pattern = new Pattern(); + pattern.ad_type = (byte) filter.getAdvertisingDataType(); + pattern.start_byte = FILTER_PATTERN_START_POSITION; + pattern.pattern = filter.getAdvertisingData(); + mPatterns.add(pattern); + } + + if (filter.getDeviceAddress() != null) { + mAddress.addr_type = (byte) filter.getAddressType(); + mAddress.bd_addr = filter.getDeviceAddress(); + } + } + + Monitor getMonitor() { + return mMonitor; + } + + Pattern[] getPatterns() { + return mPatterns.toArray(new Pattern[mPatterns.size()]); + } + + Address getAddress() { + return mAddress; + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/MsftAdvMonitorTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/MsftAdvMonitorTest.java new file mode 100644 index 00000000000..68d37a8e9ca --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/MsftAdvMonitorTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 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. + */ + +package com.android.bluetooth.le_scan; + +import static com.google.common.truth.Truth.assertThat; + +import android.bluetooth.le.ScanFilter; +import android.os.ParcelUuid; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class MsftAdvMonitorTest { + private static final String TAG = MsftAdvMonitorTest.class.getSimpleName(); + // Hardcoded values taken from CrOS defaults + private static final byte RSSI_THRESHOLD_HIGH = (byte) 0xBF; // 191 + private static final byte RSSI_THRESHOLD_LOW = (byte) 0xB0; // 176 + private static final byte RSSI_THRESHOLD_LOW_TIME_INTERVAL = (byte) 0x28; // 40s + private static final byte RSSI_SAMPLING_PERIOD = (byte) 0x05; // 500ms + private static final byte CONDITION_TYPE = (byte) 0x01; // MSFT condition type - patterns + private static final byte FILTER_PATTERN_START_POSITION = (byte) 0x00; + + // Retrieved from real Fastpair filter data + private static final String FAST_PAIR_UUID = "0000fe2c-0000-1000-8000-00805f9b34fb"; + private static final ParcelUuid FAST_PAIR_SERVICE_DATA_UUID = + ParcelUuid.fromString(FAST_PAIR_UUID); + private static final byte[] FAST_PAIR_SERVICE_DATA = + new byte[] {(byte) 0xfc, (byte) 0x12, (byte) 0x8e}; + + private void assertMonitorConstants(MsftAdvMonitor monitor) { + MsftAdvMonitor.Monitor mMonitor = monitor.getMonitor(); + assertThat(mMonitor.rssi_threshold_high).isEqualTo(RSSI_THRESHOLD_HIGH); + assertThat(mMonitor.rssi_threshold_low).isEqualTo(RSSI_THRESHOLD_LOW); + assertThat(mMonitor.rssi_threshold_low_time_interval) + .isEqualTo(RSSI_THRESHOLD_LOW_TIME_INTERVAL); + assertThat(mMonitor.rssi_sampling_period).isEqualTo(RSSI_SAMPLING_PERIOD); + assertThat(mMonitor.condition_type).isEqualTo(CONDITION_TYPE); + } + + @Test + public void testFastPairScanFilter() { + ScanFilter filter = + new ScanFilter.Builder() + .setServiceData(FAST_PAIR_SERVICE_DATA_UUID, FAST_PAIR_SERVICE_DATA) + .build(); + MsftAdvMonitor monitor = new MsftAdvMonitor(filter); + + assertMonitorConstants(monitor); + assertThat(monitor.getPatterns()).hasLength(1); + MsftAdvMonitor.Pattern mPattern = monitor.getPatterns()[0]; + assertThat(mPattern.ad_type) + .isEqualTo((byte) 0x16); // Bluetooth Core Spec Part A, Section 1 + assertThat(mPattern.start_byte).isEqualTo(FILTER_PATTERN_START_POSITION); + assertThat(mPattern.pattern).isEqualTo(new byte[] {(byte) 0x2c, (byte) 0xfe}); + } +} -- GitLab From eb3ad027cdef5863680205472d763a4ade7eb7f8 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 10 Oct 2024 18:24:40 -0700 Subject: [PATCH 306/875] Flag: add adapter_properties_looper Bug: 372777933 Bug: 315241296 Flag: com.android.bluetooth.flags.adapter_properties_looper Test: m Bluetooth Change-Id: I4f7ab5c9cbcaebe12916319d6597a311f1dc9ea2 --- flags/adapter.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/adapter.aconfig b/flags/adapter.aconfig index 6fb5963a0cb..f355113fe0e 100644 --- a/flags/adapter.aconfig +++ b/flags/adapter.aconfig @@ -1,6 +1,16 @@ package: "com.android.bluetooth.flags" container: "com.android.btservices" +flag { + name: "adapter_properties_looper" + namespace: "bluetooth" + description: "Manage AdapterProperties threading to not conflict with main looper and handle callback from native properly" + metadata { + purpose: PURPOSE_BUGFIX + } + bug: "372777933" +} + flag { name: "adapter_suspend_mgmt" namespace: "bluetooth" -- GitLab From 483729b98165d681db4c2c93e2c02fc9c0a85fc0 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 11 Oct 2024 14:49:16 -0700 Subject: [PATCH 307/875] AdapterProperties use correct looper Bug: 372777933 Bug: 372775662 Flag: com.android.bluetooth.flags.adapter_properties_looper Test: m Bluetooth Change-Id: I4dd286ee2028e481efd9f0b67ec4a7c5798db3b5 --- .../btservice/AdapterProperties.java | 32 +++++++++++++------ .../bluetooth/btservice/AdapterService.java | 20 ++++++++---- .../bluetooth/btservice/JniCallbacks.java | 7 ++-- .../btservice/AdapterPropertiesTest.java | 5 +-- .../btservice/BondStateMachineTest.java | 5 +-- 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index 728bad66cf3..f5bbe79c583 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -34,6 +34,7 @@ import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothHidDevice; import android.bluetooth.BluetoothHidHost; import android.bluetooth.BluetoothLeAudio; +import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothMapClient; import android.bluetooth.BluetoothPan; @@ -48,6 +49,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.os.ParcelUuid; import android.os.SystemProperties; import android.os.UserHandle; @@ -72,7 +75,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; class AdapterProperties { - private static final String TAG = "AdapterProperties"; + private static final String TAG = AdapterProperties.class.getSimpleName(); private static final String MAX_CONNECTED_AUDIO_DEVICES_PROPERTY = "persist.bluetooth.maxconnectedaudiodevices"; @@ -95,8 +98,7 @@ class AdapterProperties { private volatile int mDiscoverableTimeout; private volatile ParcelUuid[] mUuids; - private CopyOnWriteArrayList mBondedDevices = - new CopyOnWriteArrayList(); + private CopyOnWriteArrayList mBondedDevices = new CopyOnWriteArrayList<>(); private int mProfilesConnecting, mProfilesConnected, mProfilesDisconnecting; private final HashMap> mProfileConnectionState = @@ -111,10 +113,12 @@ class AdapterProperties { private boolean mA2dpOffloadEnabled = false; private final AdapterService mService; + private final BluetoothAdapter mAdapter; + private final RemoteDevices mRemoteDevices; + private final Handler mHandler; + private boolean mDiscovering; private long mDiscoveryEndMs; // < Time (ms since epoch) that discovery ended or will end. - private RemoteDevices mRemoteDevices; - private BluetoothAdapter mAdapter; // TODO - all hw capabilities to be exposed as a class private int mNumOfAdvertisementInstancesSupported; private boolean mRpaOffloadSupported; @@ -212,15 +216,16 @@ class AdapterProperties { // can be added here. private final Object mObject = new Object(); - AdapterProperties(AdapterService service) { + AdapterProperties(AdapterService service, RemoteDevices remoteDevices, Looper looper) { + mAdapter = ((Context) service).getSystemService(BluetoothManager.class).getAdapter(); + mRemoteDevices = remoteDevices; mService = service; - mAdapter = BluetoothAdapter.getDefaultAdapter(); + mHandler = new Handler(looper); invalidateBluetoothCaches(); } - public void init(RemoteDevices remoteDevices) { + public void init() { mProfileConnectionState.clear(); - mRemoteDevices = remoteDevices; // Get default max connected audio devices from config.xml int configDefaultMaxConnectedAudioDevices = @@ -275,7 +280,6 @@ class AdapterProperties { } public void cleanup() { - mRemoteDevices = null; mProfileConnectionState.clear(); if (mReceiverRegistered) { @@ -959,6 +963,14 @@ class AdapterProperties { } void adapterPropertyChangedCallback(int[] types, byte[][] values) { + if (Flags.adapterPropertiesLooper()) { + mHandler.post(() -> adapterPropertyChangedCallbackInternal(types, values)); + } else { + adapterPropertyChangedCallbackInternal(types, values); + } + } + + private void adapterPropertyChangedCallbackInternal(int[] types, byte[][] values) { Intent intent; int type; byte[] val; diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 17ce026d796..facf3cb7469 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -631,7 +631,7 @@ public class AdapterService extends Service { } // OnCreate must perform the minimum of infaillible and mandatory initialization mRemoteDevices = new RemoteDevices(this, mLooper); - mAdapterProperties = new AdapterProperties(this); + mAdapterProperties = new AdapterProperties(this, mRemoteDevices, mLooper); mAdapterStateMachine = new AdapterState(this, mLooper); mBinder = new AdapterServiceBinder(this); mUserManager = getNonNullSystemService(UserManager.class); @@ -666,7 +666,7 @@ public class AdapterService extends Service { mAdapter = BluetoothAdapter.getDefaultAdapter(); if (!Flags.fastBindToApp()) { // Moved to OnCreate - mAdapterProperties = new AdapterProperties(this); + mAdapterProperties = new AdapterProperties(this, mRemoteDevices, mLooper); mAdapterStateMachine = new AdapterState(this, mLooper); } boolean isCommonCriteriaMode = @@ -1001,7 +1001,7 @@ public class AdapterService extends Service { // calling cleanup but this may not be necessary at all // We should figure out why this is needed later mRemoteDevices.reset(); - mAdapterProperties.init(mRemoteDevices); + mAdapterProperties.init(); Log.d(TAG, "bleOnProcessStart() - Make Bond State Machine"); mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); @@ -1200,8 +1200,11 @@ public class AdapterService extends Service { } void updateAdapterName(String name) { - // TODO: b/372775662 - remove post once caller is on correct thread - mHandler.post(() -> updateAdapterNameInternal(name)); + if (Flags.adapterPropertiesLooper()) { + updateAdapterNameInternal(name); + } else { + mHandler.post(() -> updateAdapterNameInternal(name)); + } } private void updateAdapterNameInternal(String name) { @@ -1218,8 +1221,11 @@ public class AdapterService extends Service { } void updateAdapterAddress(String address) { - // TODO: b/372775662 - remove post once caller is on correct thread - mHandler.post(() -> updateAdapterAddressInternal(address)); + if (Flags.adapterPropertiesLooper()) { + updateAdapterAddressInternal(address); + } else { + mHandler.post(() -> updateAdapterAddressInternal(address)); + } } private void updateAdapterAddressInternal(String address) { diff --git a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java index a8e5492a351..d79239746f4 100644 --- a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +++ b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java @@ -21,9 +21,10 @@ import android.bluetooth.UidTraffic; class JniCallbacks { + private final AdapterProperties mAdapterProperties; + private final AdapterService mAdapterService; + private RemoteDevices mRemoteDevices; - private AdapterProperties mAdapterProperties; - private AdapterService mAdapterService; private BondStateMachine mBondStateMachine; JniCallbacks(AdapterService adapterService, AdapterProperties adapterProperties) { @@ -38,8 +39,6 @@ class JniCallbacks { void cleanup() { mRemoteDevices = null; - mAdapterProperties = null; - mAdapterService = null; mBondStateMachine = null; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java index 0ada5156b34..152edb06dc8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java @@ -93,8 +93,9 @@ public class AdapterPropertiesTest { .thenReturn(InstrumentationRegistry.getTargetContext().getResources()); // Must be called to initialize services - mAdapterProperties = new AdapterProperties(mAdapterService); - mAdapterProperties.init(mRemoteDevices); + mAdapterProperties = + new AdapterProperties(mAdapterService, mRemoteDevices, mHandlerThread.getLooper()); + mAdapterProperties.init(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java index e3a2f9d91af..a8be93af782 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java @@ -99,8 +99,9 @@ public class BondStateMachineTest { mRemoteDevices = new RemoteDevices(mAdapterService, mHandlerThread.getLooper()); mRemoteDevices.reset(); when(mAdapterService.getResources()).thenReturn(mTargetContext.getResources()); - mAdapterProperties = new AdapterProperties(mAdapterService); - mAdapterProperties.init(mRemoteDevices); + mAdapterProperties = + new AdapterProperties(mAdapterService, mRemoteDevices, mHandlerThread.getLooper()); + mAdapterProperties.init(); mBondStateMachine = BondStateMachine.make(mAdapterService, mAdapterProperties, mRemoteDevices); } -- GitLab From 918489e2ee34d2c0f068e3ba86404766072305f0 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 11 Oct 2024 15:24:02 -0700 Subject: [PATCH 308/875] MetricsLogger: listen to connection change AdapterProperties was listening to intent in order to log, this is exactly the role of the MetricsLogger to listen on event and generates appropriate logs. The AdapterProperties has nothing to do with that. So I am moving the code there Test: atest BluetoothInstrumentationTests Bug: 311772251 Flag: Exempt refactor moving code without op change Change-Id: I3ca86dcf0084ebdb39b9be9aefe3466f6f9f5457 --- .../btservice/AdapterProperties.java | 126 ---------------- .../bluetooth/btservice/AdapterService.java | 27 +--- .../bluetooth/btservice/MetricsLogger.java | 141 +++++++++++++++++- .../BassClientStateMachineTest.java | 12 +- .../btservice/AdapterServiceTest.java | 6 +- .../btservice/MetricsLoggerTest.java | 13 +- .../bluetooth/gatt/AppAdvertiseStatsTest.java | 24 ++- .../le_audio/LeAudioBroadcastServiceTest.java | 7 +- .../bluetooth/le_scan/ScanManagerTest.java | 43 +++--- 9 files changed, 182 insertions(+), 217 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index f5bbe79c583..42191c742ce 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -23,31 +23,17 @@ import static android.Manifest.permission.BLUETOOTH_SCAN; import android.annotation.NonNull; import android.app.BroadcastOptions; import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothA2dpSink; import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothAvrcpController; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothHeadset; -import android.bluetooth.BluetoothHeadsetClient; -import android.bluetooth.BluetoothHearingAid; -import android.bluetooth.BluetoothHidDevice; -import android.bluetooth.BluetoothHidHost; -import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothMap; -import android.bluetooth.BluetoothMapClient; -import android.bluetooth.BluetoothPan; -import android.bluetooth.BluetoothPbap; -import android.bluetooth.BluetoothPbapClient; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSap; import android.bluetooth.BufferConstraint; import android.bluetooth.BufferConstraints; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -147,70 +133,6 @@ class AdapterProperties { private boolean mIsLeIsochronousBroadcasterSupported; private boolean mIsLeChannelSoundingSupported; - private boolean mReceiverRegistered; - - private final BroadcastReceiver mReceiver = - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action == null) { - Log.w(TAG, "Received intent with null action"); - return; - } - switch (action) { - case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.HEADSET, intent); - break; - case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.A2DP, intent); - break; - case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.HEADSET_CLIENT, intent); - break; - case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.HEARING_AID, intent); - break; - case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.A2DP_SINK, intent); - break; - case BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.HID_DEVICE, intent); - break; - case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.HID_HOST, intent); - break; - case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.AVRCP_CONTROLLER, intent); - break; - case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.PAN, intent); - break; - case BluetoothMap.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.MAP, intent); - break; - case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.MAP_CLIENT, intent); - break; - case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.SAP, intent); - break; - case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.PBAP_CLIENT, intent); - break; - case BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.PBAP, intent); - break; - case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.LE_AUDIO, intent); - break; - default: - Log.w(TAG, "Received unknown intent " + intent); - break; - } - } - }; - // Lock for all getters and setters. // If finer grained locking is needer, more locks // can be added here. @@ -258,34 +180,12 @@ class AdapterProperties { SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false) && !SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); - mService.registerReceiver(mReceiver, filter); - mReceiverRegistered = true; invalidateBluetoothCaches(); } public void cleanup() { mProfileConnectionState.clear(); - if (mReceiverRegistered) { - mService.unregisterReceiver(mReceiver); - mReceiverRegistered = false; - } mBondedDevices.clear(); invalidateBluetoothCaches(); } @@ -709,32 +609,6 @@ class AdapterProperties { return mDiscovering; } - private void logConnectionStateChanges(int profile, Intent connIntent) { - BluetoothDevice device = connIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - int state = connIntent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); - int metricId = mService.getMetricId(device); - byte[] remoteDeviceInfoBytes = MetricsLogger.getInstance().getRemoteDeviceInfoProto(device); - if (state == BluetoothProfile.STATE_CONNECTING) { - String deviceName = mRemoteDevices.getName(device); - BluetoothStatsLog.write( - BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED, metricId, deviceName); - BluetoothStatsLog.write( - BluetoothStatsLog.REMOTE_DEVICE_INFORMATION_WITH_METRIC_ID, - metricId, - remoteDeviceInfoBytes); - - MetricsLogger.getInstance().logAllowlistedDeviceNameHash(metricId, deviceName, true); - } - BluetoothStatsLog.write( - BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, - state, - 0 /* deprecated */, - profile, - mService.obfuscateAddress(device), - metricId, - 0, - -1); - } void updateOnProfileConnectionChanged( BluetoothDevice device, int profile, int newState, int prevState) { diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index facf3cb7469..2a72dae9c67 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -335,8 +335,6 @@ public class AdapterService extends Service { private volatile boolean mTestModeEnabled = false; - private MetricsLogger mMetricsLogger; - /** Handlers for incoming service calls */ private AdapterServiceBinder mBinder; @@ -646,7 +644,6 @@ public class AdapterService extends Service { private void init() { Log.d(TAG, "init()"); Config.init(this); - initMetricsLogger(); mDeviceConfigListener.start(); if (!Flags.fastBindToApp()) { @@ -658,6 +655,7 @@ public class AdapterService extends Service { mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class); mRemoteDevices = new RemoteDevices(this, mLooper); } + MetricsLogger.getInstance().init(this, mRemoteDevices); clearDiscoveringPackages(); if (!Flags.fastBindToApp()) { @@ -822,23 +820,6 @@ public class AdapterService extends Service { return mSilenceDeviceManager; } - private boolean initMetricsLogger() { - if (mMetricsLogger != null) { - return false; - } - mMetricsLogger = MetricsLogger.getInstance(); - return mMetricsLogger.init(this); - } - - private boolean closeMetricsLogger() { - if (mMetricsLogger == null) { - return false; - } - boolean result = mMetricsLogger.close(); - mMetricsLogger = null; - return result; - } - /** * Log L2CAP CoC Server Connection Metrics * @@ -891,10 +872,6 @@ public class AdapterService extends Service { socketAcceptanceLatencyMillis); } - public void setMetricsLogger(MetricsLogger metricsLogger) { - mMetricsLogger = metricsLogger; - } - /** * Log L2CAP CoC Client Connection Metrics * @@ -1457,7 +1434,7 @@ public class AdapterService extends Service { return; } - closeMetricsLogger(); + MetricsLogger.getInstance().close(); clearAdapterService(this); diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java index e0dd770f83c..10c92eab85b 100644 --- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java @@ -18,9 +18,28 @@ package com.android.bluetooth.btservice; import static com.android.bluetooth.BtRestrictedStatsLog.RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED; import android.app.AlarmManager; +import android.bluetooth.BluetoothA2dp; +import android.bluetooth.BluetoothA2dpSink; +import android.bluetooth.BluetoothAvrcpController; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothHeadsetClient; +import android.bluetooth.BluetoothHearingAid; +import android.bluetooth.BluetoothHidDevice; +import android.bluetooth.BluetoothHidHost; +import android.bluetooth.BluetoothLeAudio; +import android.bluetooth.BluetoothMap; +import android.bluetooth.BluetoothMapClient; +import android.bluetooth.BluetoothPan; +import android.bluetooth.BluetoothPbap; +import android.bluetooth.BluetoothPbapClient; +import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; +import android.bluetooth.BluetoothSap; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.os.Build; import android.os.SystemClock; import android.util.Log; @@ -71,6 +90,7 @@ public class MetricsLogger { HashMap mCounters = new HashMap<>(); private static volatile MetricsLogger sInstance = null; private AdapterService mAdapterService = null; + private RemoteDevices mRemoteDevices = null; private AlarmManager mAlarmManager = null; private boolean mInitialized = false; private static final Object sLock = new Object(); @@ -111,7 +131,8 @@ public class MetricsLogger { } } - public boolean isInitialized() { + @VisibleForTesting + boolean isInitialized() { return mInitialized; } @@ -151,12 +172,13 @@ public class MetricsLogger { mBloomFilter = bloomfilter; } - public boolean init(AdapterService adapterService) { + void init(AdapterService adapterService, RemoteDevices remoteDevices) { if (mInitialized) { - return false; + return; } mInitialized = true; mAdapterService = adapterService; + mRemoteDevices = remoteDevices; scheduleDrains(); if (!initBloomFilter(BLOOMFILTER_FULL_PATH)) { Log.w(TAG, "MetricsLogger can't initialize the bloomfilter"); @@ -164,7 +186,112 @@ public class MetricsLogger { // We still want to use this class even if the bloomfilter isn't initialized // so still return true here. } - return true; + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); + mAdapterService.registerReceiver(mReceiver, filter); + } + + private final BroadcastReceiver mReceiver = + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action == null) { + Log.w(TAG, "Received intent with null action"); + return; + } + switch (action) { + case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.HEADSET, intent); + break; + case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.A2DP, intent); + break; + case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.HEADSET_CLIENT, intent); + break; + case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.HEARING_AID, intent); + break; + case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.A2DP_SINK, intent); + break; + case BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.HID_DEVICE, intent); + break; + case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.HID_HOST, intent); + break; + case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.AVRCP_CONTROLLER, intent); + break; + case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.PAN, intent); + break; + case BluetoothMap.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.MAP, intent); + break; + case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.MAP_CLIENT, intent); + break; + case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.SAP, intent); + break; + case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.PBAP_CLIENT, intent); + break; + case BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.PBAP, intent); + break; + case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.LE_AUDIO, intent); + break; + default: + Log.w(TAG, "Received unknown intent " + intent); + break; + } + } + }; + + private void logConnectionStateChanges(int profile, Intent connIntent) { + BluetoothDevice device = connIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + int state = connIntent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); + int metricId = mAdapterService.getMetricId(device); + byte[] remoteDeviceInfoBytes = getRemoteDeviceInfoProto(device); + if (state == BluetoothProfile.STATE_CONNECTING) { + String deviceName = mRemoteDevices.getName(device); + BluetoothStatsLog.write( + BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED, metricId, deviceName); + BluetoothStatsLog.write( + BluetoothStatsLog.REMOTE_DEVICE_INFORMATION_WITH_METRIC_ID, + metricId, + remoteDeviceInfoBytes); + + logAllowlistedDeviceNameHash(metricId, deviceName, true); + } + BluetoothStatsLog.write( + BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, + state, + 0 /* deprecated */, + profile, + mAdapterService.obfuscateAddress(device), + metricId, + 0, + -1); } public boolean cacheCount(int key, long count) { @@ -260,18 +387,18 @@ public class MetricsLogger { } } - public boolean close() { + void close() { if (!mInitialized) { - return false; + return; } Log.d(TAG, "close()"); + mAdapterService.unregisterReceiver(mReceiver); cancelPendingDrain(); drainBufferedCounters(); mAlarmManager = null; mAdapterService = null; mInitialized = false; mBloomFilterInitialized = false; - return true; } protected void cancelPendingDrain() { diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index 70b50063dd8..ec6fcfe4b57 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -62,7 +62,6 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -174,7 +173,6 @@ public class BassClientStateMachineTest { doNothing() .when(mMethodProxy) .periodicAdvertisingManagerTransferSync(any(), any(), anyInt(), anyInt()); - MetricsLogger.getInstance(); MetricsLogger.setInstanceForTesting(mMetricsLogger); // Get a device for testing @@ -2496,7 +2494,7 @@ public class BassClientStateMachineTest { BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_CODE_REQUIRED, 0x0L); // Verify broadcast audio session is logged when pa no past - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSync( eq(mTestDevice), eq(TEST_BROADCAST_ID), @@ -2519,7 +2517,7 @@ public class BassClientStateMachineTest { BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_BAD_CODE, 0x0L); // Verify broadcast audio session is logged when big encryption failed - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSync( eq(mTestDevice), eq(TEST_BROADCAST_ID), @@ -2542,7 +2540,7 @@ public class BassClientStateMachineTest { BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING, BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG); // Verify broadcast audio session is logged when bis sync failed - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSync( eq(mTestDevice), eq(TEST_BROADCAST_ID), @@ -2579,7 +2577,7 @@ public class BassClientStateMachineTest { 0x0L); // Verify broadcast audio session is logged when source removed - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSync( eq(mTestDevice), eq(TEST_BROADCAST_ID), @@ -2608,7 +2606,7 @@ public class BassClientStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); // Verify broadcast audio session is logged when source removed - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSync( eq(mTestDevice), eq(TEST_BROADCAST_ID), 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 df83babd3ea..e10b3ccf0b4 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 @@ -322,13 +322,10 @@ public class AdapterServiceTest { when(mMockService.getName()).thenReturn("Service1"); when(mMockService2.getName()).thenReturn("Service2"); - when(mMockMetricsLogger.init(any())).thenReturn(true); - when(mMockMetricsLogger.close()).thenReturn(true); - configureEnabledProfiles(); Config.init(mMockContext); - mAdapterService.setMetricsLogger(mMockMetricsLogger); + MetricsLogger.setInstanceForTesting(mMockMetricsLogger); // Attach a context to the service for permission checks. mAdapterService.attach(mMockContext, null, null, null, mApplication, null); @@ -358,6 +355,7 @@ public class AdapterServiceTest { GattNativeInterface.setInstance(null); PeriodicScanNativeInterface.setInstance(null); ScanNativeInterface.setInstance(null); + MetricsLogger.setInstanceForTesting(null); } private void syncHandler(int... what) { 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 46b170ce409..3f0331f2b8b 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 @@ -15,8 +15,6 @@ */ package com.android.bluetooth.btservice; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doReturn; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -87,7 +85,8 @@ public class MetricsLoggerTest { private TestableMetricsLogger mTestableMetricsLogger; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock private AdapterService mMockAdapterService; + @Mock private AdapterService mAdapterService; + @Mock private RemoteDevices mRemoteDevices; private static class TestableMetricsLogger extends MetricsLogger { public HashMap mTestableCounters = new HashMap<>(); @@ -113,11 +112,9 @@ public class MetricsLoggerTest { @Before public void setUp() { - // Dump metrics to clean up internal states MetricsLogger.dumpProto(BluetoothLog.newBuilder()); mTestableMetricsLogger = new TestableMetricsLogger(); - mTestableMetricsLogger.init(mMockAdapterService); - doReturn(null).when(mMockAdapterService).registerReceiver(any(), any()); + mTestableMetricsLogger.init(mAdapterService, mRemoteDevices); } @After @@ -231,13 +228,13 @@ public class MetricsLoggerTest { Assert.assertFalse(mTestableMetricsLogger.cacheCount(1, 1)); mTestableMetricsLogger.drainBufferedCounters(); Assert.assertFalse(mTestableMetricsLogger.mTestableCounters.containsKey(1)); - Assert.assertFalse(mTestableMetricsLogger.close()); } @Test public void testAddAndSendCountersDoubleInit() { Assert.assertTrue(mTestableMetricsLogger.isInitialized()); - Assert.assertFalse(mTestableMetricsLogger.init(mMockAdapterService)); + // sending a null adapterService will crash in case the double init no longer works + mTestableMetricsLogger.init(null, mRemoteDevices); } @Test 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 28cb4074ef5..cb3aa0dc888 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 @@ -19,7 +19,6 @@ package com.android.bluetooth.gatt; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothProtoEnums; @@ -84,7 +83,6 @@ public class AppAdvertiseStatsTest { @After public void tearDown() throws Exception { MetricsLogger.setInstanceForTesting(null); - MetricsLogger.getInstance(); } private void testSleep(long millis) { @@ -335,13 +333,13 @@ public class AppAdvertiseStatsTest { duration, maxExtAdvEvents, instanceCount); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_ADV_COUNT_ENABLE), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_ADV_COUNT_CONNECTABLE_ENABLE), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_ADV_COUNT_PERIODIC_ENABLE), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logAdvStateChanged( new int[] {appUid}, new String[] {name}, @@ -360,21 +358,21 @@ public class AppAdvertiseStatsTest { testSleep(advTestDuration); appAdvertiseStats.recordAdvertiseStop(instanceCount); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_ADV_COUNT_DISABLE), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_ADV_COUNT_CONNECTABLE_DISABLE), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_ADV_COUNT_PERIODIC_DISABLE), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_ADV_DURATION_COUNT_TOTAL_1M), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount( eq(BluetoothProtoEnums.LE_ADV_DURATION_COUNT_CONNECTABLE_1M), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount( eq(BluetoothProtoEnums.LE_ADV_DURATION_COUNT_PERIODIC_1M), eq((long) 1)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logAdvStateChanged( eq(new int[] {appUid}), eq(new String[] {name}), diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 613fe815fe8..16fe2d79896 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -216,7 +216,6 @@ public class LeAudioBroadcastServiceTest { doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); mAdapter = BluetoothAdapter.getDefaultAdapter(); - MetricsLogger.getInstance(); MetricsLogger.setInstanceForTesting(mMetricsLogger); LeAudioBroadcasterNativeInterface.setInstance(mLeAudioBroadcasterNativeInterface); @@ -353,7 +352,7 @@ public class LeAudioBroadcastServiceTest { TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); // Verify broadcast audio session is logged when session stopped - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSession( eq(broadcastId), eq(new int[] {0x2}), // STATS_SESSION_AUDIO_QUALITY_HIGH @@ -444,7 +443,7 @@ public class LeAudioBroadcastServiceTest { TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); // Verify broadcast audio session is logged when session failed to create - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSession( eq(INVALID_BROADCAST_ID), eq(new int[] {0x2}), // STATS_SESSION_AUDIO_QUALITY_HIGH @@ -522,7 +521,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(state_event); // Verify broadcast audio session is logged when session failed to stream - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logLeAudioBroadcastAudioSession( eq(broadcastId), eq(new int[] {0x2}), // STATS_SESSION_AUDIO_QUALITY_HIGH 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 c54552ca839..ca9c0f87832 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 @@ -46,7 +46,6 @@ import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -1418,7 +1417,7 @@ public class ScanManagerTest { // Create scan client for the app, which also records scan start ScanClient client = createScanClient(i, isFiltered, scanMode, UID, appScanStats); // Verify that the app scan start is logged - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logAppScanStateChanged( new int[] {UID}, new String[] {PACKAGE_NAME}, @@ -1441,7 +1440,7 @@ public class ScanManagerTest { // Record scan stop client.stats.recordScanStop(i); // Verify that the app scan stop is logged - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logAppScanStateChanged( eq(new int[] {UID}), eq(new String[] {PACKAGE_NAME}), @@ -1509,7 +1508,7 @@ public class ScanManagerTest { mHandler.sendMessage(createStartStopScanMessage(true, client2)); mTestLooper.dispatchAll(); // Verify radio scan stop is logged with the first app - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logRadioScanStopped( eq(new int[] {UID_1}), eq(new String[] {PACKAGE_NAME_1}), @@ -1544,7 +1543,7 @@ public class ScanManagerTest { mHandler.sendMessage(createStartStopScanMessage(true, client3)); mTestLooper.dispatchAll(); // Verify radio scan stop is logged with the second app - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logRadioScanStopped( eq(new int[] {UID_2}), eq(new String[] {PACKAGE_NAME_2}), @@ -1602,7 +1601,7 @@ public class ScanManagerTest { mHandler.sendMessage(createScreenOnOffMessage(false)); mTestLooper.dispatchAll(); // Verify radio scan stop is logged with the third app when screen turns off - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logRadioScanStopped( eq(new int[] {UID_3}), eq(new String[] {PACKAGE_NAME_3}), @@ -1638,7 +1637,7 @@ public class ScanManagerTest { mHandler.sendMessage(createImportanceMessage(true, UID_4)); mTestLooper.dispatchAll(); // Verify radio scan stop is logged with the third app when screen turns on - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logRadioScanStopped( eq(new int[] {mostAggressiveClient.appUid}), eq(new String[] {TEST_PACKAGE_NAME + mostAggressiveClient.appUid}), @@ -1679,7 +1678,7 @@ public class ScanManagerTest { mHandler.sendMessage(createStartStopScanMessage(false, client3)); mTestLooper.dispatchAll(); // Verify radio scan stop is logged with the third app - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logRadioScanStopped( eq(new int[] {UID_3}), eq(new String[] {PACKAGE_NAME_3}), @@ -1703,7 +1702,7 @@ public class ScanManagerTest { mHandler.sendMessage(createStartStopScanMessage(false, client2)); mTestLooper.dispatchAll(); // Verify radio scan stop is logged with the second app - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logRadioScanStopped( eq(new int[] {UID_2}), eq(new String[] {PACKAGE_NAME_2}), @@ -1727,7 +1726,7 @@ public class ScanManagerTest { mHandler.sendMessage(createStartStopScanMessage(false, client1)); mTestLooper.dispatchAll(); // Verify radio scan stop is logged with the first app - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .logRadioScanStopped( eq(new int[] {UID_1}), eq(new String[] {PACKAGE_NAME_1}), @@ -1771,9 +1770,9 @@ public class ScanManagerTest { testSleep(50); // Stop scan sendMessageWaitForProcessed(createStartStopScanMessage(false, client)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount( eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), anyLong()); @@ -1837,9 +1836,9 @@ public class ScanManagerTest { testSleep(50); // Stop scan sendMessageWaitForProcessed(createStartStopScanMessage(false, client)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount( eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), anyLong()); @@ -1876,9 +1875,9 @@ public class ScanManagerTest { testSleep(50); // Start scan with higher duty cycle sendMessageWaitForProcessed(createStartStopScanMessage(true, client2)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount( eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), anyLong()); @@ -1894,9 +1893,9 @@ public class ScanManagerTest { Mockito.clearInvocations(mMetricsLogger); // Stop scan with higher duty cycle sendMessageWaitForProcessed(createStartStopScanMessage(false, client2)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount(eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), anyLong()); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount( eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR_SCREEN_ON), anyLong()); @@ -1943,7 +1942,7 @@ public class ScanManagerTest { testSleep(scanTestDuration); // Stop scan sendMessageWaitForProcessed(createStartStopScanMessage(false, client)); - verify(mMetricsLogger, times(1)) + verify(mMetricsLogger) .cacheCount( eq(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR), mScanDurationCaptor.capture()); @@ -1964,15 +1963,13 @@ public class ScanManagerTest { sendMessageWaitForProcessed(createScreenOnOffMessage(true)); verify(mMetricsLogger, never()) .cacheCount(eq(BluetoothProtoEnums.SCREEN_OFF_EVENT), anyLong()); - verify(mMetricsLogger, times(1)) - .cacheCount(eq(BluetoothProtoEnums.SCREEN_ON_EVENT), anyLong()); + verify(mMetricsLogger).cacheCount(eq(BluetoothProtoEnums.SCREEN_ON_EVENT), anyLong()); Mockito.clearInvocations(mMetricsLogger); // Turn off screen sendMessageWaitForProcessed(createScreenOnOffMessage(false)); verify(mMetricsLogger, never()) .cacheCount(eq(BluetoothProtoEnums.SCREEN_ON_EVENT), anyLong()); - verify(mMetricsLogger, times(1)) - .cacheCount(eq(BluetoothProtoEnums.SCREEN_OFF_EVENT), anyLong()); + verify(mMetricsLogger).cacheCount(eq(BluetoothProtoEnums.SCREEN_OFF_EVENT), anyLong()); Mockito.clearInvocations(mMetricsLogger); } -- GitLab From cd5641a199e2f4f1676193773168fc5377b2f866 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 11 Oct 2024 15:41:49 -0700 Subject: [PATCH 309/875] Uniformize times(1) mockito usage 1 is the default, we don't need to specify it Bug: 311772251 Test: atest BluetoothInstrumentationTests Flag: TEST_ONLY Change-Id: Id18d97842023c2b3c9b8336150d4021656d16d50 --- .../bluetooth/a2dp/A2dpCodecConfigTest.java | 6 +- .../bluetooth/a2dp/A2dpStateMachineTest.java | 4 +- .../a2dpsink/A2dpSinkStreamHandlerTest.java | 22 +-- .../audio_util/BrowserPlayerWrapperTest.java | 20 +-- .../audio_util/MediaPlayerWrapperTest.java | 16 +-- .../avrcp/AvrcpBipObexServerTest.java | 7 +- .../AvrcpControllerServiceTest.java | 2 +- .../AvrcpControllerStateMachineTest.java | 28 ++-- .../bass_client/BassClientServiceTest.java | 14 +- .../BassClientStateMachineTest.java | 2 +- .../btservice/AdapterPropertiesTest.java | 5 +- .../btservice/BondStateMachineTest.java | 12 +- .../bluetooth/btservice/PhonePolicyTest.java | 24 ++-- .../btservice/RemoteDevicesTest.java | 4 +- .../csip/CsipSetCoordinatorServiceTest.java | 18 +-- .../gatt/DistanceMeasurementManagerTest.java | 3 +- .../HeadsetServiceAndStateMachineTest.java | 6 +- .../hfp/HeadsetStateMachineTest.java | 6 +- .../le_audio/LeAudioBroadcastServiceTest.java | 113 ++++++++------- .../le_audio/LeAudioServiceTest.java | 136 +++++++++--------- .../le_audio/LeAudioTmapGattServerTest.java | 7 +- .../mapclient/MapClientStateMachineTest.java | 24 ++-- .../mcp/MediaControlGattServiceTest.java | 14 +- .../BluetoothTetheringNetworkFactoryTest.java | 5 +- .../PbapClientConnectionHandlerTest.java | 3 +- .../android/bluetooth/tbs/TbsGattTest.java | 20 +-- .../vc/VolumeControlServiceTest.java | 81 ++++++----- 27 files changed, 296 insertions(+), 306 deletions(-) diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java index 7857a6c25f9..04527233f00 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java @@ -755,8 +755,7 @@ public class A2dpCodecConfigTest { getDefaultCodecConfigByType( BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT)); - verify(mA2dpNativeInterface, times(1)) - .setCodecConfigPreference(mTestDevice, codecConfigsArray); + verify(mA2dpNativeInterface).setCodecConfigPreference(mTestDevice, codecConfigsArray); // shouldn't invoke to native when current codec is already an optional for (int codecType : sOptionalCodecTypes) { @@ -764,8 +763,7 @@ public class A2dpCodecConfigTest { mTestDevice, getDefaultCodecConfigByType( codecType, BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT)); - verify(mA2dpNativeInterface, times(1)) - .setCodecConfigPreference(mTestDevice, codecConfigsArray); + verify(mA2dpNativeInterface).setCodecConfigPreference(mTestDevice, codecConfigsArray); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java index a21f86c07e9..5f1c1e9ecd8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java @@ -365,7 +365,7 @@ public class A2dpStateMachineTest { // Selected codec = SBC, selectable codec = SBC mA2dpStateMachine.processCodecConfigEvent(codecStatusSbcAndSbc); verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusSbcAndSbc, false); - verify(mA2dpService, times(1)).updateLowLatencyAudioSupport(mTestDevice); + verify(mA2dpService).updateLowLatencyAudioSupport(mTestDevice); // Inject an event to change state machine to connected state A2dpStackEvent connStCh = @@ -382,7 +382,7 @@ public class A2dpStateMachineTest { .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); // Verify that state machine update optional codec when enter connected state - verify(mA2dpService, times(1)).updateOptionalCodecsSupport(mTestDevice); + verify(mA2dpService).updateOptionalCodecsSupport(mTestDevice); verify(mA2dpService, times(2)).updateLowLatencyAudioSupport(mTestDevice); // Change codec status when device connected. diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java index c74fd3ef35f..f1dabf24470 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java @@ -145,7 +145,7 @@ public class A2dpSinkStreamHandlerTest { public void testSnkPlay() { // Play was pressed locally, expect streaming to start soon. mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SNK_PLAY)); - verify(mMockAudioManager, times(1)).requestAudioFocus(any()); + verify(mMockAudioManager).requestAudioFocus(any()); assertThat(mStreamHandler.isPlaying()).isFalse(); assertThat(BluetoothMediaBrowserService.isActive()).isFalse(); } @@ -189,7 +189,7 @@ public class A2dpSinkStreamHandlerTest { // Play was pressed remotely for an iot device, expect streaming to start. when(mMockPackageManager.hasSystemFeature(any())).thenReturn(true); mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY)); - verify(mMockAudioManager, times(1)).requestAudioFocus(any()); + verify(mMockAudioManager).requestAudioFocus(any()); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); assertThat(mStreamHandler.isPlaying()).isTrue(); } @@ -211,9 +211,9 @@ public class A2dpSinkStreamHandlerTest { mStreamHandler.handleMessage( mStreamHandler.obtainMessage( A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE, AudioManager.AUDIOFOCUS_GAIN)); - verify(mMockAudioManager, times(1)).requestAudioFocus(any()); - verify(mMockNativeInterface, times(1)).informAudioFocusState(1); - verify(mMockNativeInterface, times(1)).informAudioTrackGain(1.0f); + verify(mMockAudioManager).requestAudioFocus(any()); + verify(mMockNativeInterface).informAudioFocusState(1); + verify(mMockNativeInterface).informAudioTrackGain(1.0f); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); assertThat(mStreamHandler.getFocusState()).isEqualTo(AudioManager.AUDIOFOCUS_GAIN); @@ -228,7 +228,7 @@ public class A2dpSinkStreamHandlerTest { mStreamHandler.obtainMessage( A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE, AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)); - verify(mMockNativeInterface, times(1)).informAudioTrackGain(DUCK_PERCENT / 100.0f); + verify(mMockNativeInterface).informAudioTrackGain(DUCK_PERCENT / 100.0f); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); assertThat(mStreamHandler.getFocusState()) @@ -246,7 +246,7 @@ public class A2dpSinkStreamHandlerTest { AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)); verify(mMockAudioManager, times(0)).abandonAudioFocus(any()); verify(mMockNativeInterface, times(0)).informAudioFocusState(0); - verify(mMockNativeInterface, times(1)).informAudioTrackGain(0); + verify(mMockNativeInterface).informAudioTrackGain(0); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); assertThat(mStreamHandler.getFocusState()) @@ -264,7 +264,7 @@ public class A2dpSinkStreamHandlerTest { AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)); verify(mMockAudioManager, times(0)).abandonAudioFocus(any()); verify(mMockNativeInterface, times(0)).informAudioFocusState(0); - verify(mMockNativeInterface, times(1)).informAudioTrackGain(0); + verify(mMockNativeInterface).informAudioTrackGain(0); mStreamHandler.handleMessage( mStreamHandler.obtainMessage(A2dpSinkStreamHandler.REQUEST_FOCUS, true)); verify(mMockAudioManager, times(2)).requestAudioFocus(any()); @@ -281,7 +281,7 @@ public class A2dpSinkStreamHandlerTest { mStreamHandler.obtainMessage( A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE, AudioManager.AUDIOFOCUS_GAIN)); verify(mMockAudioManager, times(0)).abandonAudioFocus(any()); - verify(mMockNativeInterface, times(1)).informAudioTrackGain(1.0f); + verify(mMockNativeInterface).informAudioTrackGain(1.0f); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); assertThat(BluetoothMediaBrowserService.isActive()).isTrue(); @@ -295,8 +295,8 @@ public class A2dpSinkStreamHandlerTest { mStreamHandler.handleMessage( mStreamHandler.obtainMessage( A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE, AudioManager.AUDIOFOCUS_LOSS)); - verify(mMockAudioManager, times(1)).abandonAudioFocus(any()); - verify(mMockNativeInterface, times(1)).informAudioFocusState(0); + verify(mMockAudioManager).abandonAudioFocus(any()); + verify(mMockNativeInterface).informAudioFocusState(0); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); assertThat(BluetoothMediaBrowserService.isActive()).isFalse(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java index 4e21e9e215c..e2edf0903a7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java @@ -197,10 +197,10 @@ public class BrowserPlayerWrapperTest { verify(mMockBrowser).testInit(any(), any(), mBrowserConnCb.capture(), any()); MediaBrowser.ConnectionCallback browserConnCb = mBrowserConnCb.getValue(); - verify(mMockBrowser, times(1)).connect(); + verify(mMockBrowser).connect(); browserConnCb.onConnected(); verify(mConnCb).run(eq(BrowsedPlayerWrapper.STATUS_SUCCESS), eq(wrapper)); - verify(mMockBrowser, times(1)).disconnect(); + verify(mMockBrowser).disconnect(); } @Test @@ -211,7 +211,7 @@ public class BrowserPlayerWrapperTest { verify(mMockBrowser).testInit(any(), any(), mBrowserConnCb.capture(), any()); MediaBrowser.ConnectionCallback browserConnCb = mBrowserConnCb.getValue(); - verify(mMockBrowser, times(1)).connect(); + verify(mMockBrowser).connect(); browserConnCb.onConnectionSuspended(); verify(mConnCb).run(eq(BrowsedPlayerWrapper.STATUS_CONN_ERROR), eq(wrapper)); // Twice because our mConnCb is wrapped when using the plain connect() call and disconnect @@ -228,10 +228,10 @@ public class BrowserPlayerWrapperTest { verify(mMockBrowser).testInit(any(), any(), mBrowserConnCb.capture(), any()); MediaBrowser.ConnectionCallback browserConnCb = mBrowserConnCb.getValue(); - verify(mMockBrowser, times(1)).connect(); + verify(mMockBrowser).connect(); browserConnCb.onConnectionFailed(); verify(mConnCb).run(eq(BrowsedPlayerWrapper.STATUS_CONN_ERROR), eq(wrapper)); - verify(mMockBrowser, times(1)).disconnect(); + verify(mMockBrowser).disconnect(); } @Test @@ -245,11 +245,11 @@ public class BrowserPlayerWrapperTest { verify(mMockBrowser).testInit(any(), any(), mBrowserConnCb.capture(), any()); MediaBrowser.ConnectionCallback browserConnCb = mBrowserConnCb.getValue(); - verify(mMockBrowser, times(1)).connect(); + verify(mMockBrowser).connect(); browserConnCb.onConnected(); verify(mConnCb).run(eq(BrowsedPlayerWrapper.STATUS_CONN_ERROR), eq(wrapper)); - verify(mMockBrowser, times(1)).disconnect(); + verify(mMockBrowser).disconnect(); } @Test @@ -284,7 +284,7 @@ public class BrowserPlayerWrapperTest { MediaBrowser.ConnectionCallback browserConnCb = mBrowserConnCb.getValue(); wrapper.playItem("test_item"); - verify(mMockBrowser, times(1)).connect(); + verify(mMockBrowser).connect(); MediaController mockController = mock(MediaController.class); MediaController.TransportControls mockTransport = @@ -310,7 +310,7 @@ public class BrowserPlayerWrapperTest { // Once we're told we're playing, make sure we disconnect builder.setState(PlaybackState.STATE_PLAYING, 0, 1); controllerCb.onPlaybackStateChanged(builder.build()); - verify(mMockBrowser, times(1)).disconnect(); + verify(mMockBrowser).disconnect(); } @Test @@ -321,7 +321,7 @@ public class BrowserPlayerWrapperTest { MediaBrowser.ConnectionCallback browserConnCb = mBrowserConnCb.getValue(); wrapper.playItem("test_item"); - verify(mMockBrowser, times(1)).connect(); + verify(mMockBrowser).connect(); MediaController mockController = mock(MediaController.class); MediaController.TransportControls mockTransport = diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java index 79316b4e43d..f1e78940c65 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java @@ -265,7 +265,7 @@ public class MediaPlayerWrapperTest { controllerCallbacks.onMetadataChanged(mTestMetadata.build()); // Assert that the metadata was updated and playback state wasn't - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals( "Returned Metadata isn't equal to given Metadata", @@ -332,7 +332,7 @@ public class MediaPlayerWrapperTest { controllerCallbacks.onPlaybackStateChanged(mTestState.build()); // Assert that both metadata and playback state are there. - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals( "Returned PlaybackState isn't equal to given PlaybackState", @@ -371,7 +371,7 @@ public class MediaPlayerWrapperTest { controllerCallbacks.onMetadataChanged(null); // Assert that the metadata returned by getMetadata() is used instead of null - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals( "Returned metadata is incorrect", @@ -402,7 +402,7 @@ public class MediaPlayerWrapperTest { // Assert that the metadata returned by getPlaybackState() is used instead of null - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals( "Returned PlaybackState is incorrect", @@ -428,7 +428,7 @@ public class MediaPlayerWrapperTest { controllerCallbacks.onQueueChanged(null); // Assert that both metadata and playback state are there. - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals("Returned Queue isn't null", data.queue.size(), 0); } @@ -509,7 +509,7 @@ public class MediaPlayerWrapperTest { controllerCallbacks.onPlaybackStateChanged(mTestState.build()); // Assert that both metadata and only the first playback state is there. - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals( "Returned PlaybackState isn't equal to given PlaybackState", @@ -625,7 +625,7 @@ public class MediaPlayerWrapperTest { controllerCallbacks.onQueueChanged(getQueueFromDescriptions(mTestQueue)); // Assert that the callback was called with the updated data - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); verify(mFailHandler, never()).onTerribleFailure(any(), any(), anyBoolean()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals( @@ -676,7 +676,7 @@ public class MediaPlayerWrapperTest { verify(mFailHandler).onTerribleFailure(any(), any(), anyBoolean()); // Assert that the callback was called with the mismatch data - verify(mTestCbs, times(1)).mediaUpdatedCallback(mMediaUpdateData.capture()); + verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); Assert.assertEquals( "Returned Metadata isn't equal to given Metadata", diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java index 26d732b28e5..cfd283648e1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -182,7 +181,7 @@ public class AvrcpBipObexServerTest { public void testConnectWithValidUuidHeader() throws Exception { mRequest.setHeader(HeaderSet.TARGET, BLUETOOTH_UUID_AVRCP_COVER_ART); int responseCode = mAvrcpBipObexServer.onConnect(mRequest, mReply); - verify(mCallback, times(1)).onConnected(); + verify(mCallback).onConnected(); assertThat(responseCode).isEqualTo(ResponseCodes.OBEX_HTTP_OK); } @@ -199,14 +198,14 @@ public class AvrcpBipObexServerTest { @Test public void testDisonnect() { mAvrcpBipObexServer.onDisconnect(mRequest, mReply); - verify(mCallback, times(1)).onDisconnected(); + verify(mCallback).onDisconnected(); } /** Make sure onClose notifies the callbacks in the proper way */ @Test public void testOnClose() { mAvrcpBipObexServer.onClose(); - verify(mCallback, times(1)).onClose(); + verify(mCallback).onClose(); } /** Make sure onGet handles null headers gracefully */ diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java index 3b0dfce27a8..deabdbe1087 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java @@ -262,7 +262,7 @@ public class AvrcpControllerServiceTest { BrowseResult result = mService.getContents(parentMediaId); - verify(mStateMachine, times(1)).requestContents(eq(node)); + verify(mStateMachine).requestContents(eq(node)); assertThat(result.getStatus()).isEqualTo(BrowseResult.DOWNLOAD_PENDING); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java index 62254b0ed25..70fac79ca16 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java @@ -1519,12 +1519,12 @@ public class AvrcpControllerStateMachineTest { sendAudioFocusUpdate(AudioManager.AUDIOFOCUS_LOSS_TRANSIENT); TestUtils.waitForLooperToBeIdle(mAvrcpStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .sendPassThroughCommand( eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE), eq(KEY_DOWN)); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .sendPassThroughCommand( eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE), @@ -1564,12 +1564,12 @@ public class AvrcpControllerStateMachineTest { sendAudioFocusUpdate(AudioManager.AUDIOFOCUS_LOSS); TestUtils.waitForLooperToBeIdle(mAvrcpStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .sendPassThroughCommand( eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE), eq(KEY_DOWN)); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .sendPassThroughCommand( eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE), @@ -1610,12 +1610,12 @@ public class AvrcpControllerStateMachineTest { sendAudioFocusUpdate(AudioManager.AUDIOFOCUS_GAIN); TestUtils.waitForLooperToBeIdle(mAvrcpStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .sendPassThroughCommand( eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PLAY), eq(KEY_DOWN)); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .sendPassThroughCommand( eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PLAY), @@ -1754,12 +1754,12 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Verify download attempt and send some elements over, verify next set is requested - verify(mNativeInterface, times(1)).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); + verify(mNativeInterface).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); mAvrcpStateMachine.sendMessage( AvrcpControllerStateMachine.MESSAGE_PROCESS_GET_FOLDER_ITEMS, new ArrayList(nowPlayingList.subList(0, 20))); TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)).getNowPlayingList(eq(mTestAddress), eq(20), eq(39)); + verify(mNativeInterface).getNowPlayingList(eq(mTestAddress), eq(20), eq(39)); // Force a now playing content invalidation and verify attempted download mAvrcpStateMachine.nowPlayingContentChanged(); @@ -1821,7 +1821,7 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Verify download attempt and send some elements over, verify next set is requested - verify(mNativeInterface, times(1)).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); + verify(mNativeInterface).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); mAvrcpStateMachine.nowPlayingContentChanged(); mAvrcpStateMachine.sendMessage( @@ -1881,12 +1881,12 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Verify download attempt and send some elements over, verify next set is requested - verify(mNativeInterface, times(1)).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); + verify(mNativeInterface).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); mAvrcpStateMachine.sendMessage( AvrcpControllerStateMachine.MESSAGE_PROCESS_GET_FOLDER_ITEMS, new ArrayList(nowPlayingList.subList(0, 20))); TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)).getNowPlayingList(eq(mTestAddress), eq(20), eq(39)); + verify(mNativeInterface).getNowPlayingList(eq(mTestAddress), eq(20), eq(39)); // Force a now playing content invalidation due to addressed player change mAvrcpStateMachine.sendMessage( @@ -1949,7 +1949,7 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Verify download attempt and send some elements over, verify next set is requested - verify(mNativeInterface, times(1)).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); + verify(mNativeInterface).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); // Force a now playing content invalidation due to addressed player change, happening // before we've received any items from the remote device. @@ -2007,7 +2007,7 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Request for new contents should be sent - verify(mNativeInterface, times(1)).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); + verify(mNativeInterface).getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); Assert.assertFalse(nowPlaying.isCached()); // Send timeout on our own instead of waiting 10 seconds @@ -2075,7 +2075,7 @@ public class AvrcpControllerStateMachineTest { // issues a player list fetch mAvrcpStateMachine.connect(StackEvent.connectionStateChanged(true, true)); TestUtils.waitForLooperToBeIdle(mAvrcpStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)).getPlayerList(eq(mTestAddress), eq(0), eq(19)); + verify(mNativeInterface).getPlayerList(eq(mTestAddress), eq(0), eq(19)); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 246677b6ed1..b32e1aae5b9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -2139,7 +2139,7 @@ public class BassClientServiceTest { verify(sm, never()).sendMessage(any()); } else if (sm.getDevice().equals(mCurrentDevice1)) { ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(sm, times(1)).sendMessage(messageCaptor.capture()); + verify(sm).sendMessage(messageCaptor.capture()); List msgs = messageCaptor.getAllValues().stream() .filter( @@ -4380,7 +4380,7 @@ public class BassClientServiceTest { mBassClientService.handleDeviceDisconnection(mCurrentDevice, true); mBassClientService.handleDeviceDisconnection(mCurrentDevice1, true); - verify(mLeAudioService, times(1)).stopBroadcast(eq(TEST_BROADCAST_ID)); + verify(mLeAudioService).stopBroadcast(eq(TEST_BROADCAST_ID)); } @Test @@ -4396,7 +4396,7 @@ public class BassClientServiceTest { mBassClientService.handleDeviceDisconnection(mCurrentDevice, true); mBassClientService.handleDeviceDisconnection(mCurrentDevice1, true); - verify(mLeAudioService, times(1)).stopBroadcast(eq(TEST_BROADCAST_ID)); + verify(mLeAudioService).stopBroadcast(eq(TEST_BROADCAST_ID)); } @Test @@ -4444,7 +4444,7 @@ public class BassClientServiceTest { mBassClientService.handleDeviceDisconnection(mCurrentDevice1, true); /* After second device disconnection and de-synchronization expect stopping broadcast */ - verify(mLeAudioService, times(1)).stopBroadcast(eq(TEST_BROADCAST_ID)); + verify(mLeAudioService).stopBroadcast(eq(TEST_BROADCAST_ID)); } @Test @@ -4473,7 +4473,7 @@ public class BassClientServiceTest { mBassClientService.handleDeviceDisconnection(mCurrentDevice1, false); /* After second device disconnection and de-synchronization expect stopping broadcast */ - verify(mLeAudioService, times(1)).stopBroadcast(eq(TEST_BROADCAST_ID)); + verify(mLeAudioService).stopBroadcast(eq(TEST_BROADCAST_ID)); } @Test @@ -4491,7 +4491,7 @@ public class BassClientServiceTest { mBassClientService.handleDeviceDisconnection(mCurrentDevice, true); /* After first device disconnection and de-synchronization expect stopping broadcast */ - verify(mLeAudioService, times(1)).stopBroadcast(eq(TEST_BROADCAST_ID)); + verify(mLeAudioService).stopBroadcast(eq(TEST_BROADCAST_ID)); /* Imitate first device being in disconnected state */ doReturn(BluetoothProfile.STATE_DISCONNECTED) @@ -4502,7 +4502,7 @@ public class BassClientServiceTest { mBassClientService.handleDeviceDisconnection(mCurrentDevice1, true); /* After second device disconnection and de-synchronization expect not stopping broadcast */ - verify(mLeAudioService, times(1)).stopBroadcast(eq(TEST_BROADCAST_ID)); + verify(mLeAudioService).stopBroadcast(eq(TEST_BROADCAST_ID)); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index ec6fcfe4b57..bd3874ff1eb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -2702,7 +2702,7 @@ public class BassClientStateMachineTest { @SafeVarargs private void verifyIntentSent(int timeout_ms, Matcher... matchers) { - verify(mBassClientService, timeout(timeout_ms).times(1)) + verify(mBassClientService, timeout(timeout_ms)) .sendBroadcast( MockitoHamcrest.argThat(AllOf.allOf(matchers)), eq(BLUETOOTH_CONNECT), diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java index 152edb06dc8..dc3494e5cb5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -83,8 +82,8 @@ public class AdapterPropertiesTest { when(mNativeInterface.removeBond(any(byte[].class))).thenReturn(true); mRemoteDevices = new RemoteDevices(mAdapterService, mHandlerThread.getLooper()); - verify(mAdapterService, times(1)).getSystemService(Context.BLUETOOTH_SERVICE); - verify(mAdapterService, times(1)).getSystemService(BluetoothManager.class); + verify(mAdapterService).getSystemService(Context.BLUETOOTH_SERVICE); + verify(mAdapterService).getSystemService(BluetoothManager.class); mRemoteDevices.reset(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java index a8be93af782..e1dc5a07ce8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java @@ -140,8 +140,8 @@ public class BondStateMachineTest { mBondStateMachine.sendMessage(removeBondMsg2); TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)).removeBond(eq(TEST_BT_ADDR_BYTES)); - verify(mNativeInterface, times(1)).removeBond(eq(TEST_BT_ADDR_BYTES_2)); + verify(mNativeInterface).removeBond(eq(TEST_BT_ADDR_BYTES)); + verify(mNativeInterface).removeBond(eq(TEST_BT_ADDR_BYTES_2)); mBondStateMachine.bondStateChangeCallback( AbstractionLayer.BT_STATUS_SUCCESS, TEST_BT_ADDR_BYTES, BOND_NONE, 0); @@ -159,10 +159,10 @@ public class BondStateMachineTest { mBondStateMachine.sendMessage(createBondMsg2); TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .createBond( eq(TEST_BT_ADDR_BYTES), eq(BluetoothDevice.ADDRESS_TYPE_PUBLIC), anyInt()); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .createBond( eq(TEST_BT_ADDR_BYTES_2), eq(BluetoothDevice.ADDRESS_TYPE_PUBLIC), @@ -194,10 +194,10 @@ public class BondStateMachineTest { mBondStateMachine.sendMessage(createBondMsg2); TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .createBond( eq(TEST_BT_ADDR_BYTES), eq(BluetoothDevice.ADDRESS_TYPE_PUBLIC), anyInt()); - verify(mNativeInterface, times(1)) + verify(mNativeInterface) .createBond( eq(TEST_BT_ADDR_BYTES_2), eq(BluetoothDevice.ADDRESS_TYPE_RANDOM), diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java index fc41eec21c5..1d4778d1fd3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java @@ -279,7 +279,7 @@ public class PhonePolicyTest { // Single device, no CSIP processInitProfilePriorities_LeAudioOnlyHelper( BluetoothCsipSetCoordinator.GROUP_ID_INVALID, 1, false, false); - verify(mLeAudioService, times(1)) + verify(mLeAudioService) .setConnectionPolicy( any(BluetoothDevice.class), eq(BluetoothProfile.CONNECTION_POLICY_ALLOWED)); } @@ -573,17 +573,17 @@ public class PhonePolicyTest { waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); // Verify connection policy is set properly - verify(mLeAudioService, times(1)) + verify(mLeAudioService) .setConnectionPolicy( eq(firstDevice), eq(BluetoothProfile.CONNECTION_POLICY_ALLOWED)); mPhonePolicy.profileActiveDeviceChanged(BluetoothProfile.LE_AUDIO, firstDevice); waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - verify(mA2dpService, times(1)) + verify(mA2dpService) .setConnectionPolicy( eq(firstDevice), eq(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)); - verify(mHeadsetService, times(1)) + verify(mHeadsetService) .setConnectionPolicy( eq(firstDevice), eq(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)); @@ -606,17 +606,17 @@ public class PhonePolicyTest { waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); // Verify connection policy is set properly - verify(mLeAudioService, times(1)) + verify(mLeAudioService) .setConnectionPolicy( eq(secondDevice), eq(BluetoothProfile.CONNECTION_POLICY_ALLOWED)); mPhonePolicy.profileActiveDeviceChanged(BluetoothProfile.LE_AUDIO, secondDevice); waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - verify(mA2dpService, times(1)) + verify(mA2dpService) .setConnectionPolicy( eq(secondDevice), eq(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)); - verify(mHeadsetService, times(1)) + verify(mHeadsetService) .setConnectionPolicy( eq(secondDevice), eq(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)); } @@ -692,14 +692,14 @@ public class PhonePolicyTest { waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); // Verify connection policy is set properly - verify(mLeAudioService, times(1)) + verify(mLeAudioService) .setConnectionPolicy( eq(firstDevice), eq(BluetoothProfile.CONNECTION_POLICY_ALLOWED)); mPhonePolicy.profileActiveDeviceChanged(BluetoothProfile.LE_AUDIO, firstDevice); waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - verify(mHearingAidService, times(1)) + verify(mHearingAidService) .setConnectionPolicy( eq(firstDevice), eq(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)); @@ -722,14 +722,14 @@ public class PhonePolicyTest { waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); // Verify connection policy is set properly - verify(mLeAudioService, times(1)) + verify(mLeAudioService) .setConnectionPolicy( eq(secondDevice), eq(BluetoothProfile.CONNECTION_POLICY_ALLOWED)); mPhonePolicy.profileActiveDeviceChanged(BluetoothProfile.LE_AUDIO, secondDevice); waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - verify(mHearingAidService, times(1)) + verify(mHearingAidService) .setConnectionPolicy( eq(secondDevice), eq(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)); } @@ -864,7 +864,7 @@ public class PhonePolicyTest { // Verify we didn't have any unexpected calls to setConnection or deleteConnection verify(mDatabaseManager, times(2)).setConnection(any(BluetoothDevice.class), anyInt()); - verify(mDatabaseManager, times(1)) + verify(mDatabaseManager) .setDisconnection(eq(connectionOrder.get(1)), eq(BluetoothProfile.HEADSET)); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java index 40b570dccd7..6129d254978 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java @@ -78,8 +78,8 @@ public class RemoteDevicesTest { .thenReturn(Context.BLUETOOTH_SERVICE); mRemoteDevices = new RemoteDevices(mAdapterService, mHandlerThread.getLooper()); - verify(mAdapterService, times(1)).getSystemService(Context.BLUETOOTH_SERVICE); - verify(mAdapterService, times(1)).getSystemService(BluetoothManager.class); + verify(mAdapterService).getSystemService(Context.BLUETOOTH_SERVICE); + verify(mAdapterService).getSystemService(BluetoothManager.class); } @After 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 1487108d1cf..77bb8b522c3 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 @@ -307,7 +307,7 @@ public class CsipSetCoordinatorServiceTest { UUID lock_uuid = mService.lockGroup(group_id, mCsipSetCoordinatorLockCallback); Assert.assertNotNull(lock_uuid); - verify(mCsipSetCoordinatorNativeInterface, times(1)).groupLockSet(eq(group_id), eq(true)); + verify(mCsipSetCoordinatorNativeInterface).groupLockSet(eq(group_id), eq(true)); Assert.assertTrue(mService.isGroupLocked(group_id)); doCallRealMethod() @@ -317,21 +317,21 @@ public class CsipSetCoordinatorServiceTest { group_id, true, IBluetoothCsipSetCoordinator.CSIS_GROUP_LOCK_SUCCESS); try { - verify(mCsipSetCoordinatorLockCallback, times(1)) + verify(mCsipSetCoordinatorLockCallback) .onGroupLockSet(group_id, BluetoothStatusCodes.SUCCESS, true); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mService.unlockGroup(lock_uuid); - verify(mCsipSetCoordinatorNativeInterface, times(1)).groupLockSet(eq(group_id), eq(false)); + verify(mCsipSetCoordinatorNativeInterface).groupLockSet(eq(group_id), eq(false)); mCsipSetCoordinatorNativeInterface.onGroupLockChanged( group_id, false, IBluetoothCsipSetCoordinator.CSIS_GROUP_LOCK_SUCCESS); Assert.assertFalse(mService.isGroupLocked(group_id)); try { - verify(mCsipSetCoordinatorLockCallback, times(1)) + verify(mCsipSetCoordinatorLockCallback) .onGroupLockSet(group_id, BluetoothStatusCodes.SUCCESS, false); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -355,19 +355,19 @@ public class CsipSetCoordinatorServiceTest { Assert.assertFalse(mService.isGroupLocked(group_id)); UUID lock_uuid = mService.lockGroup(group_id, mCsipSetCoordinatorLockCallback); - verify(mCsipSetCoordinatorNativeInterface, times(1)).groupLockSet(eq(group_id), eq(true)); + verify(mCsipSetCoordinatorNativeInterface).groupLockSet(eq(group_id), eq(true)); Assert.assertNotNull(lock_uuid); Assert.assertTrue(mService.isGroupLocked(group_id)); lock_uuid = mService.lockGroup(group_id, mCsipSetCoordinatorLockCallback); - verify(mCsipSetCoordinatorNativeInterface, times(1)).groupLockSet(eq(group_id), eq(true)); + verify(mCsipSetCoordinatorNativeInterface).groupLockSet(eq(group_id), eq(true)); doCallRealMethod() .when(mCsipSetCoordinatorNativeInterface) .onGroupLockChanged(anyInt(), anyBoolean(), anyInt()); try { - verify(mCsipSetCoordinatorLockCallback, times(1)) + verify(mCsipSetCoordinatorLockCallback) .onGroupLockSet( group_id, BluetoothStatusCodes.ERROR_CSIP_GROUP_LOCKED_BY_OTHER, true); } catch (RemoteException e) { @@ -648,12 +648,12 @@ public class CsipSetCoordinatorServiceTest { mTestDevice2, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED); // When LEA is FORBIDDEN, verify we disable CSIP once all set devices are available - verify(mDatabaseManager, times(1)) + verify(mDatabaseManager) .setProfileConnectionPolicy( mTestDevice, BluetoothProfile.CSIP_SET_COORDINATOR, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - verify(mDatabaseManager, times(1)) + verify(mDatabaseManager) .setProfileConnectionPolicy( mTestDevice2, BluetoothProfile.CSIP_SET_COORDINATOR, diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java index b5aa597273c..1fe9bfb1365 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.after; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothAdapter; @@ -201,7 +200,7 @@ public class DistanceMeasurementManagerTest { DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); ArgumentCaptor result = ArgumentCaptor.forClass(DistanceMeasurementResult.class); - verify(mCallback, times(1)).onResult(eq(mDevice), result.capture()); + verify(mCallback).onResult(eq(mDevice), result.capture()); assertThat(result.getValue().getResultMeters()).isEqualTo(1.00); assertThat(result.getValue().getErrorMeters()).isEqualTo(1.00); assertThat(result.getValue().getAzimuthAngle()).isEqualTo(Double.NaN); 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 3e5aaf84f50..eb0e166a778 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 @@ -1286,7 +1286,7 @@ public class HeadsetServiceAndStateMachineTest { // Check that AptX SWB disabled, LC3 SWB disabled verifySetParametersToAudioSystemInvocation(false, true, false); - verify(mNativeInterface, times(1)).connectAudio(eq(device)); + verify(mNativeInterface).connectAudio(eq(device)); verify(mNativeInterface).sendBsir(eq(device), eq(true)); verify(mNativeInterface, times(2)) .enableSwb( @@ -1370,7 +1370,7 @@ public class HeadsetServiceAndStateMachineTest { // Check that AptX SWB enabled, LC3 SWB disabled verifySetParametersToAudioSystemInvocation(false, true, true); - verify(mNativeInterface, times(1)).connectAudio(eq(device)); + verify(mNativeInterface).connectAudio(eq(device)); verify(mNativeInterface).sendBsir(eq(device), eq(true)); verify(mNativeInterface, times(2)) .enableSwb( @@ -1782,7 +1782,7 @@ public class HeadsetServiceAndStateMachineTest { mTestLooper.stopAutoDispatch(); mTestLooper.dispatchAll(); // HeadsetStateMachine completes processing CALL_STATE_CHANGED message - verify(mNativeInterface, times(1)).phoneStateChange(device, headsetCallState); + verify(mNativeInterface).phoneStateChange(device, headsetCallState); Utils.setIsScoManagedByAudioEnabled(false); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java index 34077ad0c1d..e7130842000 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java @@ -1333,7 +1333,7 @@ public class HeadsetStateMachineTest { ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)) .sendBroadcast(intentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - verify(mHeadsetService, times(1)).sendBroadcast(any(), any(), any()); + verify(mHeadsetService).sendBroadcast(any(), any(), any()); Assert.assertEquals( mTestDevice, intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)); @@ -1361,7 +1361,7 @@ public class HeadsetStateMachineTest { ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)) .sendBroadcast(intentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - verify(mHeadsetService, times(1)).sendBroadcast(any(), any(), any()); + verify(mHeadsetService).sendBroadcast(any(), any(), any()); Assert.assertEquals( mTestDevice, intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)); @@ -1389,7 +1389,7 @@ public class HeadsetStateMachineTest { ArgumentCaptor intentArgument = ArgumentCaptor.forClass(Intent.class); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)) .sendBroadcast(intentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - verify(mHeadsetService, times(1)).sendBroadcast(any(), any(), any()); + verify(mHeadsetService).sendBroadcast(any(), any(), any()); Assert.assertEquals( mTestDevice, intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 16fe2d79896..309c7310d2e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -290,7 +290,7 @@ public class LeAudioBroadcastServiceTest { .map(setting -> setting.getContentMetadata().getRawMetadata()) .toArray(byte[][]::new); - verify(mLeAudioBroadcasterNativeInterface, times(1)) + verify(mLeAudioBroadcasterNativeInterface) .createBroadcast( eq(true), eq(TEST_BROADCAST_NAME), @@ -307,7 +307,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); // Verify if broadcast is auto-started on start - verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); // Notify initial paused state LeAudioStackEvent state_event = @@ -323,7 +323,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(state_event); // Check if metadata is requested when the broadcast starts to stream - verify(mLeAudioBroadcasterNativeInterface, times(1)).getBroadcastMetadata(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).getBroadcastMetadata(eq(broadcastId)); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); Assert.assertFalse(mOnBroadcastStartFailedCalled); @@ -334,7 +334,7 @@ public class LeAudioBroadcastServiceTest { Mockito.clearInvocations(mMetricsLogger); mService.stopBroadcast(broadcastId); - verify(mLeAudioBroadcasterNativeInterface, times(1)).stopBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).stopBroadcast(eq(broadcastId)); LeAudioStackEvent state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); @@ -343,7 +343,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(state_event); // Verify if broadcast is auto-destroyed on stop - verify(mLeAudioBroadcasterNativeInterface, times(1)).destroyBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).destroyBroadcast(eq(broadcastId)); state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED); state_event.valueInt1 = broadcastId; @@ -425,7 +425,7 @@ public class LeAudioBroadcastServiceTest { settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata() }; - verify(mLeAudioBroadcasterNativeInterface, times(1)) + verify(mLeAudioBroadcasterNativeInterface) .createBroadcast( eq(true), eq(TEST_BROADCAST_NAME), @@ -483,7 +483,7 @@ public class LeAudioBroadcastServiceTest { settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata() }; - verify(mLeAudioBroadcasterNativeInterface, times(1)) + verify(mLeAudioBroadcasterNativeInterface) .createBroadcast( eq(true), eq(TEST_BROADCAST_NAME), @@ -500,7 +500,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); // Verify if broadcast is auto-started on start - verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); Assert.assertTrue(mOnBroadcastStartedCalled); @@ -513,7 +513,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(state_event); // Check if broadcast is destroyed after timeout - verify(mLeAudioBroadcasterNativeInterface, timeout(CREATE_BROADCAST_TIMEOUT_MS).times(1)) + verify(mLeAudioBroadcasterNativeInterface, timeout(CREATE_BROADCAST_TIMEOUT_MS)) .destroyBroadcast(eq(broadcastId)); state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED); @@ -565,7 +565,7 @@ public class LeAudioBroadcastServiceTest { settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata() }; - verify(mLeAudioBroadcasterNativeInterface, times(1)) + verify(mLeAudioBroadcasterNativeInterface) .createBroadcast( eq(true), eq(TEST_BROADCAST_NAME), @@ -607,7 +607,7 @@ public class LeAudioBroadcastServiceTest { settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata() }; - verify(mLeAudioBroadcasterNativeInterface, times(1)) + verify(mLeAudioBroadcasterNativeInterface) .createBroadcast( eq(true), eq(TEST_BROADCAST_NAME), @@ -780,14 +780,14 @@ public class LeAudioBroadcastServiceTest { Assert.assertTrue(mService.isBroadcastActive()); mService.stopBroadcast(broadcastId); - verify(mLeAudioBroadcasterNativeInterface, times(1)).stopBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).stopBroadcast(eq(broadcastId)); state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); state_event.valueInt1 = broadcastId; state_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_STOPPED; mService.messageFromNative(state_event); - verify(mLeAudioBroadcasterNativeInterface, times(1)).destroyBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).destroyBroadcast(eq(broadcastId)); state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED); state_event.valueInt1 = broadcastId; @@ -945,7 +945,7 @@ public class LeAudioBroadcastServiceTest { .map(setting -> setting.getContentMetadata().getRawMetadata()) .toArray(byte[][]::new); - verify(mLeAudioBroadcasterNativeInterface, times(1)) + verify(mLeAudioBroadcasterNativeInterface) .createBroadcast( eq(true), eq(TEST_BROADCAST_NAME), @@ -1009,7 +1009,7 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); - verify(mTbsService, times(1)).setInbandRingtoneSupport(eq(mDevice)); + verify(mTbsService).setInbandRingtoneSupport(eq(mDevice)); /* Verify Unicast input and output devices changed from null to mDevice */ verify(mAudioManager, times(2)) @@ -1035,7 +1035,7 @@ public class LeAudioBroadcastServiceTest { create_event.valueBool1 = true; mService.messageFromNative(create_event); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); @@ -1050,7 +1050,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Only one Unicast device should become inactive due to Sink monitor mode */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); Mockito.clearInvocations(mAudioManager); @@ -1063,7 +1063,7 @@ public class LeAudioBroadcastServiceTest { .map(setting -> setting.getContentMetadata().getRawMetadata()) .toArray(byte[][]::new); - verify(mLeAudioBroadcasterNativeInterface, times(1)) + verify(mLeAudioBroadcasterNativeInterface) .createBroadcast( eq(true), eq(TEST_BROADCAST_NAME), @@ -1071,7 +1071,7 @@ public class LeAudioBroadcastServiceTest { eq(settings.getPublicBroadcastMetadata().getRawMetadata()), eq(expectedQualityArray), eq(expectedDataArray)); - verify(mLeAudioNativeInterface, times(1)) + verify(mLeAudioNativeInterface) .setUnicastMonitorMode(eq(LeAudioStackEvent.DIRECTION_SINK), eq(true)); activeGroup = mService.getActiveGroupId(); @@ -1084,7 +1084,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); /* Switch to active streaming */ create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); @@ -1109,7 +1109,7 @@ public class LeAudioBroadcastServiceTest { mService.setInCall(true); /* Check if broadcast is paused by InCall handling */ - verify(mLeAudioBroadcasterNativeInterface, times(1)).pauseBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).pauseBroadcast(eq(broadcastId)); LeAudioStackEvent state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); @@ -1117,7 +1117,7 @@ public class LeAudioBroadcastServiceTest { state_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_PAUSED; mService.messageFromNative(state_event); - verify(mLeAudioNativeInterface, times(1)).setInCall(eq(true)); + verify(mLeAudioNativeInterface).setInCall(eq(true)); LeAudioStackEvent create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); @@ -1125,10 +1125,10 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); @@ -1148,10 +1148,10 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Only one Unicast device should become inactive due to Sink monitor mode */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); @@ -1173,7 +1173,7 @@ public class LeAudioBroadcastServiceTest { mService.handleAudioModeChange(AudioManager.MODE_IN_CALL); /* Check if broadcast is paused by AudioMode handling */ - verify(mLeAudioBroadcasterNativeInterface, times(1)).pauseBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).pauseBroadcast(eq(broadcastId)); LeAudioStackEvent state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); @@ -1187,10 +1187,10 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); @@ -1206,7 +1206,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Device should not be inactivated if in IN_CALL audio mode */ - verify(mLeAudioNativeInterface, times(1)).groupSetActive(eq(LE_AUDIO_GROUP_ID_INVALID)); + verify(mLeAudioNativeInterface).groupSetActive(eq(LE_AUDIO_GROUP_ID_INVALID)); /* Imitate setting device not in call */ mService.handleAudioModeChange(AudioManager.MODE_NORMAL); @@ -1220,10 +1220,10 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Only one Unicast device should become inactive due to Sink monitor mode */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); @@ -1240,7 +1240,7 @@ public class LeAudioBroadcastServiceTest { prepareHandoverStreamingBroadcast(groupId, broadcastId, code); /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); /* Imitate group change request by Bluetooth Sink HAL resume request */ LeAudioStackEvent create_event = @@ -1250,7 +1250,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Check if broadcast is paused triggered by group change request */ - verify(mLeAudioBroadcasterNativeInterface, times(1)).pauseBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface).pauseBroadcast(eq(broadcastId)); LeAudioStackEvent state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); @@ -1263,10 +1263,10 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); @@ -1290,10 +1290,10 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Only one Unicast device should become inactive due to Sink monitor mode */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); @@ -1324,7 +1324,7 @@ public class LeAudioBroadcastServiceTest { /* Broadcast already paused, not call pause again by InCall handling */ verify(mLeAudioBroadcasterNativeInterface, never()).pauseBroadcast(eq(broadcastId)); - verify(mLeAudioNativeInterface, times(1)).setInCall(eq(true)); + verify(mLeAudioNativeInterface).setInCall(eq(true)); LeAudioStackEvent create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); @@ -1332,10 +1332,10 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); @@ -1355,10 +1355,10 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Only one Unicast device should become inactive due to Sink monitor mode */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); @@ -1395,10 +1395,10 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); @@ -1414,7 +1414,7 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Device should not be inactivated if in IN_CALL audio mode */ - verify(mLeAudioNativeInterface, times(1)).groupSetActive(eq(LE_AUDIO_GROUP_ID_INVALID)); + verify(mLeAudioNativeInterface).groupSetActive(eq(LE_AUDIO_GROUP_ID_INVALID)); /* Imitate setting device not in call */ mService.handleAudioModeChange(AudioManager.MODE_NORMAL); @@ -1428,10 +1428,10 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Only one Unicast device should become inactive due to Sink monitor mode */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); @@ -1470,10 +1470,10 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); @@ -1497,10 +1497,10 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(create_event); /* Only one Unicast device should become inactive due to Sink monitor mode */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); @@ -1525,17 +1525,16 @@ public class LeAudioBroadcastServiceTest { mService.messageFromNative(state_event); if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - verify(mBassClientService, times(1)) - .suspendReceiversSourceSynchronization(eq(broadcastId)); + verify(mBassClientService).suspendReceiversSourceSynchronization(eq(broadcastId)); } else { - verify(mBassClientService, times(1)).cacheSuspendingSources(eq(broadcastId)); + verify(mBassClientService).cacheSuspendingSources(eq(broadcastId)); } /* Internal broadcast resumed due to onAudioResumed */ state_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_STREAMING; mService.messageFromNative(state_event); - verify(mBassClientService, times(1)).resumeReceiversSourceSynchronization(); + verify(mBassClientService).resumeReceiversSourceSynchronization(); } @Test @@ -1560,7 +1559,7 @@ public class LeAudioBroadcastServiceTest { Assert.assertTrue(mService.setActiveDevice(mDevice2)); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mDevice2), eq(mDevice), connectionInfoArgumentCaptor.capture()); List connInfos = 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 6e694c5c824..90dd85cac2a 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 @@ -958,8 +958,8 @@ public class LeAudioServiceTest { mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - verify(mTbsService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice); - verify(mMcpService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice); + verify(mTbsService).removeDeviceAuthorizationInfo(mLeftDevice); + verify(mMcpService).removeDeviceAuthorizationInfo(mLeftDevice); reset(mTbsService); reset(mMcpService); @@ -1012,8 +1012,8 @@ public class LeAudioServiceTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING); - verify(mTbsService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice); - verify(mMcpService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice); + verify(mTbsService).removeDeviceAuthorizationInfo(mLeftDevice); + verify(mMcpService).removeDeviceAuthorizationInfo(mLeftDevice); reset(mTbsService); reset(mMcpService); @@ -1047,8 +1047,8 @@ public class LeAudioServiceTest { // Device unbond mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); - verify(mTbsService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice); - verify(mMcpService, times(1)).removeDeviceAuthorizationInfo(mLeftDevice); + verify(mTbsService).removeDeviceAuthorizationInfo(mLeftDevice); + verify(mMcpService).removeDeviceAuthorizationInfo(mLeftDevice); } /** @@ -1224,14 +1224,14 @@ public class LeAudioServiceTest { .isTrue(); // Verify connection policy for CSIP and VCP are also set - verify(mVolumeControlService, times(1)) + verify(mVolumeControlService) .setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - verify(mCsipSetCoordinatorService, times(1)) + verify(mCsipSetCoordinatorService) .setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - verify(mHapClientService, times(1)) + verify(mHapClientService) .setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED); if (BluetoothProperties.isProfileBapBroadcastAssistEnabled().orElse(false)) { - verify(mBassClientService, times(1)) + verify(mBassClientService) .setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED); } // Verify the connection state broadcast, and that we are in Connecting state @@ -1267,14 +1267,14 @@ public class LeAudioServiceTest { .isTrue(); // Verify connection policy for CSIP and VCP are also set - verify(mVolumeControlService, times(1)) + verify(mVolumeControlService) .setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - verify(mCsipSetCoordinatorService, times(1)) + verify(mCsipSetCoordinatorService) .setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - verify(mHapClientService, times(1)) + verify(mHapClientService) .setConnectionPolicy(mSingleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); if (BluetoothProperties.isProfileBapBroadcastAssistEnabled().orElse(false)) { - verify(mBassClientService, times(1)) + verify(mBassClientService) .setConnectionPolicy( mSingleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); } @@ -1467,7 +1467,7 @@ public class LeAudioServiceTest { /* Expect 2 calles to Audio Manager - one for output as this is * Ringtone use case */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(), any(), any(BluetoothProfileConnectionInfo.class)); /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback @@ -1645,7 +1645,7 @@ public class LeAudioServiceTest { /* Expect 2 calles to Audio Manager - one for output as this is * Ringtone use case */ - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mSingleDevice), eq(null), connectionInfoArgumentCaptor.capture()); @@ -1658,7 +1658,7 @@ public class LeAudioServiceTest { // set active device again assertThat(mService.setActiveDevice(mSingleDevice_2)).isTrue(); - verify(mNativeInterface, times(1)).groupSetActive(groupId_2); + verify(mNativeInterface).groupSetActive(groupId_2); // First wait for INACTIVE state will be sent from native LeAudioStackEvent inactiveGroupState = @@ -1668,7 +1668,7 @@ public class LeAudioServiceTest { mService.messageFromNative(inactiveGroupState); // Make sure suppressNoisyIntent is set to true. Soon new group will be active - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mSingleDevice), connectionInfoArgumentCaptor.capture()); connInfo = connectionInfoArgumentCaptor.getValue(); @@ -1685,7 +1685,7 @@ public class LeAudioServiceTest { activeGroupState.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(activeGroupState); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mSingleDevice_2), eq(null), connectionInfoArgumentCaptor.capture()); connInfo = connectionInfoArgumentCaptor.getValue(); @@ -1961,7 +1961,7 @@ public class LeAudioServiceTest { BluetoothLeAudio.CONTEXT_TYPE_MEDIA | BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL, 1); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mSingleDevice), testConnectioInfoCapture.capture()); @@ -1982,10 +1982,10 @@ public class LeAudioServiceTest { BluetoothLeAudio.CONTEXT_TYPE_MEDIA | BluetoothLeAudio.CONTEXT_TYPE_CONVERSATIONAL, 2); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(mSingleDevice), testConnectioInfoCapture.capture()); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mSingleDevice), eq(null), testConnectioInfoCapture.capture()); @@ -2092,7 +2092,7 @@ public class LeAudioServiceTest { // Set group and device as active. injectGroupStatusChange(testGroupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mSingleDevice), any(), any(BluetoothProfileConnectionInfo.class)); @@ -2104,12 +2104,12 @@ public class LeAudioServiceTest { LeAudioStackEvent.HEALTH_RECOMMENDATION_ACTION_INACTIVATE_GROUP; mService.messageFromNative(healthBasedGroupAction); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), any(), any(BluetoothProfileConnectionInfo.class)); injectAudioConfChanged(testGroupId, contexts, 1); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mSingleDevice), any(), any(BluetoothProfileConnectionInfo.class)); } @@ -2127,7 +2127,7 @@ public class LeAudioServiceTest { // Set group and device as active. injectGroupStatusChange(testGroupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mSingleDevice), any(), any(BluetoothProfileConnectionInfo.class)); @@ -2151,7 +2151,7 @@ public class LeAudioServiceTest { .isAnyReceiverReceivingBroadcast(mService.getGroupDevices(testGroupId)); mService.messageFromNative(healthBasedGroupAction); // Verify setting device inactive if group is not receiving broadcast - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), any(), any(BluetoothProfileConnectionInfo.class)); } @@ -2478,7 +2478,7 @@ public class LeAudioServiceTest { TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); assertThat(onGroupCodecConfChangedCallbackCalled).isTrue(); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(), any(), any(BluetoothProfileConnectionInfo.class)); @@ -2604,7 +2604,7 @@ public class LeAudioServiceTest { mService.messageFromNative(groupStatusChangedEvent); assertThat(mService.getActiveDevices().contains(leadDevice)).isTrue(); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(leadDevice), any(), any(BluetoothProfileConnectionInfo.class)); /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback @@ -2627,7 +2627,7 @@ public class LeAudioServiceTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(), eq(leadDevice), any(BluetoothProfileConnectionInfo.class)); @@ -2680,7 +2680,7 @@ public class LeAudioServiceTest { mService.messageFromNative(groupStatusChangedEvent); assertThat(mService.getActiveDevices().contains(leadDevice)).isTrue(); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(leadDevice), any(), any(BluetoothProfileConnectionInfo.class)); /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback @@ -2703,7 +2703,7 @@ public class LeAudioServiceTest { injectAndVerifyDeviceDisconnected(memberDevice); injectAndVerifyDeviceDisconnected(leadDevice); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), eq(leadDevice), any(BluetoothProfileConnectionInfo.class)); @@ -2739,17 +2739,17 @@ public class LeAudioServiceTest { // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged(any(), eq(null), profileInfo.capture()); assertThat(profileInfo.getValue().getVolume()).isEqualTo(-1); mService.setVolume(volume); - verify(mVolumeControlService, times(1)).setGroupVolume(groupId, volume); + verify(mVolumeControlService).setGroupVolume(groupId, volume); // Set group to inactive. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), any(), any(BluetoothProfileConnectionInfo.class)); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); @@ -2799,7 +2799,7 @@ public class LeAudioServiceTest { // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged(any(), eq(null), profileInfo.capture()); assertThat(profileInfo.getValue().getVolume()).isEqualTo(volume); @@ -2807,7 +2807,7 @@ public class LeAudioServiceTest { injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); injectGroupStatusChange(groupId2, LeAudioStackEvent.GROUP_STATUS_INACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), any(), any(BluetoothProfileConnectionInfo.class)); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); @@ -2825,7 +2825,7 @@ public class LeAudioServiceTest { mService.setVolume(newVolume); // Verify set volume only on primary group - verify(mVolumeControlService, times(1)).setGroupVolume(groupId, newVolume); + verify(mVolumeControlService).setGroupVolume(groupId, newVolume); verify(mVolumeControlService, never()).setGroupVolume(groupId2, newVolume); } @@ -2937,8 +2937,8 @@ public class LeAudioServiceTest { doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class)); connectTestDevice(mLeftDevice, groupId); connectTestDevice(mRightDevice, groupId); - verify(mMcpService, times(1)).setDeviceAuthorized(mLeftDevice, true); - verify(mMcpService, times(1)).setDeviceAuthorized(mRightDevice, true); + verify(mMcpService).setDeviceAuthorized(mLeftDevice, true); + verify(mMcpService).setDeviceAuthorized(mRightDevice, true); } /** Test setting authorization for LeAudio device in the McpService */ @@ -2958,14 +2958,14 @@ public class LeAudioServiceTest { mService.handleBluetoothEnabled(); - verify(mMcpService, times(1)).setDeviceAuthorized(mLeftDevice, true); - verify(mMcpService, times(1)).setDeviceAuthorized(mRightDevice, true); + verify(mMcpService).setDeviceAuthorized(mLeftDevice, true); + verify(mMcpService).setDeviceAuthorized(mRightDevice, true); generateGroupNodeRemoved(mLeftDevice, groupId); - verify(mMcpService, times(1)).setDeviceAuthorized(mLeftDevice, false); + verify(mMcpService).setDeviceAuthorized(mLeftDevice, false); generateGroupNodeRemoved(mRightDevice, groupId); - verify(mMcpService, times(1)).setDeviceAuthorized(mRightDevice, false); + verify(mMcpService).setDeviceAuthorized(mRightDevice, false); } /** @@ -2997,16 +2997,16 @@ public class LeAudioServiceTest { // Connects the test device and verifies GATT server services are authorized connectTestDevice(mSingleDevice, groupId); - verify(mMcpService, times(1)).setDeviceAuthorized(mSingleDevice, true); - verify(mTbsService, times(1)).setDeviceAuthorized(mSingleDevice, true); + verify(mMcpService).setDeviceAuthorized(mSingleDevice, true); + verify(mTbsService).setDeviceAuthorized(mSingleDevice, true); // Ensure that disconnecting unauthorizes GATT server services assertThat( mService.setConnectionPolicy( mSingleDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) .isTrue(); - verify(mMcpService, times(1)).setDeviceAuthorized(mSingleDevice, false); - verify(mTbsService, times(1)).setDeviceAuthorized(mSingleDevice, false); + verify(mMcpService).setDeviceAuthorized(mSingleDevice, false); + verify(mTbsService).setDeviceAuthorized(mSingleDevice, false); // Connecting a device that has a group re-authorizes the GATT server services assertThat( @@ -3150,7 +3150,7 @@ public class LeAudioServiceTest { // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), @@ -3168,10 +3168,10 @@ public class LeAudioServiceTest { audioConfChangedEvent.valueInt5 = 0; mService.messageFromNative(audioConfChangedEvent); - verify(mNativeInterface, times(1)).groupSetActive(-1); + verify(mNativeInterface).groupSetActive(-1); injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), any(BluetoothDevice.class), @@ -3189,7 +3189,7 @@ public class LeAudioServiceTest { // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), @@ -3245,11 +3245,11 @@ public class LeAudioServiceTest { audioConfChangedEvent.valueInt5 = availableContexts; mService.messageFromNative(audioConfChangedEvent); - verify(mNativeInterface, times(1)).groupSetActive(groupId); + verify(mNativeInterface).groupSetActive(groupId); // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), @@ -3262,10 +3262,10 @@ public class LeAudioServiceTest { audioConfChangedEvent.valueInt5 = 0; mService.messageFromNative(audioConfChangedEvent); - verify(mNativeInterface, times(1)).groupSetActive(-1); + verify(mNativeInterface).groupSetActive(-1); injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), any(BluetoothDevice.class), @@ -3278,12 +3278,12 @@ public class LeAudioServiceTest { audioConfChangedEvent.valueInt5 = availableContexts; mService.messageFromNative(audioConfChangedEvent); - verify(mNativeInterface, times(1)).groupSetActive(groupId); + verify(mNativeInterface).groupSetActive(groupId); reset(mNativeInterface); // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), @@ -3334,11 +3334,11 @@ public class LeAudioServiceTest { mService.messageFromNative(audioConfChangedEvent); assertThat(mService.setActiveDevice(mLeftDevice)).isTrue(); - verify(mNativeInterface, times(1)).groupSetActive(groupId); + verify(mNativeInterface).groupSetActive(groupId); // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), @@ -3351,10 +3351,10 @@ public class LeAudioServiceTest { audioConfChangedEvent.valueInt5 = 0; mService.messageFromNative(audioConfChangedEvent); - verify(mNativeInterface, times(1)).groupSetActive(-1); + verify(mNativeInterface).groupSetActive(-1); injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(null), any(BluetoothDevice.class), @@ -3397,11 +3397,11 @@ public class LeAudioServiceTest { audioConfChangedEvent.valueInt5 = availableContexts; mService.messageFromNative(audioConfChangedEvent); - verify(mNativeInterface, times(1)).groupSetActive(groupId); + verify(mNativeInterface).groupSetActive(groupId); // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), @@ -3450,11 +3450,11 @@ public class LeAudioServiceTest { mService.messageFromNative(audioConfChangedEvent); assertThat(mService.setActiveDevice(mLeftDevice)).isTrue(); - verify(mNativeInterface, times(1)).groupSetActive(groupId); + verify(mNativeInterface).groupSetActive(groupId); // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), @@ -3496,11 +3496,11 @@ public class LeAudioServiceTest { audioConfChangedEvent.valueInt5 = availableContexts; mService.messageFromNative(audioConfChangedEvent); - verify(mNativeInterface, times(1)).groupSetActive(groupId); + verify(mNativeInterface).groupSetActive(groupId); // Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); - verify(mAudioManager, times(1)) + verify(mAudioManager) .handleBluetoothActiveDeviceChanged( any(BluetoothDevice.class), eq(null), diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java index 0eea74fe333..29116ced0ff 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java @@ -25,7 +25,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothGattCharacteristic; @@ -74,8 +73,8 @@ public class LeAudioTmapGattServerTest { ArgumentCaptor captor = ArgumentCaptor.forClass(BluetoothGattService.class); mServer.start(TEST_ROLE_MASK); - verify(mGattServerProxy, times(1)).open(any()); - verify(mGattServerProxy, times(1)).addService(captor.capture()); + verify(mGattServerProxy).open(any()); + verify(mGattServerProxy).addService(captor.capture()); // verify primary service with TMAP UUID BluetoothGattService service = captor.getValue(); @@ -96,7 +95,7 @@ public class LeAudioTmapGattServerTest { // verify stop triggers stop method call mServer.stop(); - verify(mGattServerProxy, times(1)).close(); + verify(mGattServerProxy).close(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java index 773b8b95e53..23f7242e64e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java @@ -522,7 +522,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msgSent); TestUtils.waitForLooperToFinishScheduledTask(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase, times(1)) + verify(mMockDatabase) .storeMessage( eq(mTestIncomingSmsBmessage), eq(mTestMessageSmsHandle), @@ -704,7 +704,7 @@ public class MapClientStateMachineTest { mMceStateMachine.receiveEvent(event); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, times(1)).makeRequest(any(RequestGetMessage.class)); + verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); msg = Message.obtain( @@ -714,7 +714,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase, times(1)) + verify(mMockDatabase) .storeMessage( eq(mTestIncomingSmsBmessage), eq(mTestMessageSmsHandle), @@ -753,7 +753,7 @@ public class MapClientStateMachineTest { mMceStateMachine.receiveEvent(event); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, times(1)).makeRequest(any(RequestGetMessage.class)); + verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); msg = Message.obtain( @@ -763,7 +763,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase, times(1)) + verify(mMockDatabase) .storeMessage( eq(mTestIncomingMmsBmessage), eq(mTestMessageMmsHandle), @@ -799,7 +799,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, times(1)).makeRequest(any(RequestGetMessagesListing.class)); + verify(mMockMasClient).makeRequest(any(RequestGetMessagesListing.class)); msg = Message.obtain( @@ -809,7 +809,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, times(1)).makeRequest(any(RequestGetMessage.class)); + verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); msg = Message.obtain( @@ -819,7 +819,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase, times(1)).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); + verify(mMockDatabase).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); } /** Test seen status set in database on initial download */ @@ -853,7 +853,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, times(1)).makeRequest(any(RequestGetMessagesListing.class)); + verify(mMockMasClient).makeRequest(any(RequestGetMessagesListing.class)); msg = Message.obtain( @@ -863,7 +863,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, times(1)).makeRequest(any(RequestGetMessage.class)); + verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); msg = Message.obtain( @@ -873,7 +873,7 @@ public class MapClientStateMachineTest { mMceStateMachine.sendMessage(msg); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase, times(1)).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); + verify(mMockDatabase).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); } /** Test receiving a new message notification. */ @@ -988,7 +988,7 @@ public class MapClientStateMachineTest { mMceStateMachine.receiveEvent(event); TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, times(1)).makeRequest(any(RequestGetMessage.class)); + verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); msg = Message.obtain( diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java index 54d8f929d52..03fbe7f71a3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java @@ -1043,7 +1043,7 @@ public class MediaControlGattServiceTest { final List metadataList = mock(List.class); when(mMockLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); - verify(mMockMcsCallbacks, times(1)).onMediaControlRequest(any(Request.class)); + verify(mMockMcsCallbacks).onMediaControlRequest(any(Request.class)); } @Test @@ -1072,7 +1072,7 @@ public class MediaControlGattServiceTest { mMcpService.mServerCallback.onCharacteristicWriteRequest( mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); } @@ -1109,12 +1109,12 @@ public class MediaControlGattServiceTest { characteristic, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone()); mMcpService.updateSupportedOpcodesChar(opcodes_supported, true); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); // Verify if there will be no new notification triggered when nothing changes mMcpService.updateSupportedOpcodesChar(opcodes_supported, true); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); opcodes_supported = 0; @@ -1141,14 +1141,14 @@ public class MediaControlGattServiceTest { bb.put((byte) playing_order.getValue()); mMcpService.mServerCallback.onCharacteristicWriteRequest( mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); - verify(mMockMcsCallbacks, times(1)).onPlayingOrderSetRequest(anyInt()); + verify(mMockMcsCallbacks).onPlayingOrderSetRequest(anyInt()); // Not supported playing order should be ignored playing_order = PlayingOrder.SHUFFLE_ONCE; bb.put(0, (byte) playing_order.getValue()); mMcpService.mServerCallback.onCharacteristicWriteRequest( mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); - verify(mMockMcsCallbacks, times(1)).onPlayingOrderSetRequest(anyInt()); + verify(mMockMcsCallbacks).onPlayingOrderSetRequest(anyInt()); playing_order = PlayingOrder.NEWEST_ONCE; bb.put(0, (byte) playing_order.getValue()); @@ -1225,7 +1225,7 @@ public class MediaControlGattServiceTest { .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic2), eq(false)); verify(mMockGattServer, times(0)) .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic3), eq(false)); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java index a80863120b5..7641eec65d5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java @@ -18,7 +18,6 @@ package com.android.bluetooth.pan; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -106,8 +105,8 @@ public class BluetoothTetheringNetworkFactoryTest { bluetoothTetheringNetworkFactory.stopReverseTether(); - verify(mPanService, times(1)).getConnectedDevices(); - verify(mPanService, times(1)).disconnect(bluetoothDevice); + verify(mPanService).getConnectedDevices(); + verify(mPanService).disconnect(bluetoothDevice); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java index 04626d5591b..aea37588861 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -197,6 +196,6 @@ public class PbapClientConnectionHandlerTest { public void createAndDisconnectWithoutAddingAccount_doesNotCrash() { mHandler.obtainMessage(PbapClientConnectionHandler.MSG_DISCONNECT).sendToTarget(); TestUtils.waitForLooperToFinishScheduledTask(mHandler.getLooper()); - verify(mStateMachine, times(1)).sendMessage(PbapClientStateMachine.MSG_CONNECTION_CLOSED); + verify(mStateMachine).sendMessage(PbapClientStateMachine.MSG_CONNECTION_CLOSED); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java index 2ad93593319..2e5e12ffd55 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java @@ -137,7 +137,7 @@ public class TbsGattTest { mMockTbsGattCallback)); Assert.assertNotNull(mMockGattServer); - verify(mAdapterService, times(1)).registerBluetoothStateCallback(any(), any()); + verify(mAdapterService).registerBluetoothStateCallback(any(), any()); verify(mMockGattServer).addService(mGattServiceCaptor.capture()); doReturn(mGattServiceCaptor.getValue()).when(mMockGattServer).getService(any(UUID.class)); Assert.assertNotNull(mMockGattServer); @@ -758,7 +758,7 @@ public class TbsGattTest { mTbsGatt.setInbandRingtoneFlag(mFirstDevice); mTbsGatt.setInbandRingtoneFlag(mFirstDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mFirstDevice), eq(characteristic), eq(false), eq(valueBytes)); @@ -766,7 +766,7 @@ public class TbsGattTest { mTbsGatt.setInbandRingtoneFlag(mSecondDevice); mTbsGatt.setInbandRingtoneFlag(mSecondDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mSecondDevice), eq(characteristic), eq(false), eq(valueBytes)); } @@ -785,14 +785,14 @@ public class TbsGattTest { valueBytes[1] = (byte) ((statusFlagValue >> 8) & 0xFF); mTbsGatt.setInbandRingtoneFlag(mFirstDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mFirstDevice), eq(characteristic), eq(false), eq(valueBytes)); reset(mMockGattServer); mTbsGatt.setInbandRingtoneFlag(mSecondDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mSecondDevice), eq(characteristic), eq(false), eq(valueBytes)); @@ -805,14 +805,14 @@ public class TbsGattTest { mTbsGatt.clearInbandRingtoneFlag(mFirstDevice); mTbsGatt.clearInbandRingtoneFlag(mFirstDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mFirstDevice), eq(characteristic), eq(false), eq(valueBytes)); reset(mMockGattServer); mTbsGatt.clearInbandRingtoneFlag(mSecondDevice); mTbsGatt.clearInbandRingtoneFlag(mSecondDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mSecondDevice), eq(characteristic), eq(false), eq(valueBytes)); } @@ -847,14 +847,14 @@ public class TbsGattTest { mTbsGatt.setInbandRingtoneFlag(mFirstDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mFirstDevice), eq(characteristic), eq(false), eq(valueBytes)); reset(mMockGattServer); mTbsGatt.setInbandRingtoneFlag(mSecondDevice); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged( eq(mSecondDevice), eq(characteristic), eq(false), eq(valueBytes)); reset(mMockGattServer); @@ -1091,7 +1091,7 @@ public class TbsGattTest { mTbsGatt.onDeviceAuthorizationSet(mFirstDevice); verify(mMockGattServer, times(0)) .notifyCharacteristicChanged(any(), eq(characteristic2), eq(false)); - verify(mMockGattServer, times(1)) + verify(mMockGattServer) .notifyCharacteristicChanged(any(), eq(characteristic), eq(false), eq(valueBytes)); } 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 e08a4b182f8..b681a96fb8e 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 @@ -18,6 +18,7 @@ package com.android.bluetooth.vc; import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; + import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; @@ -583,7 +584,7 @@ public class VolumeControlServiceTest { // Verify that setting LeAudio Volume, sets the original volume index to // Audio FW - verify(mAudioManager, times(1)) + verify(mAudioManager) .setStreamVolume(eq(streamType), eq(idx), anyInt()); }); } @@ -616,14 +617,14 @@ public class VolumeControlServiceTest { // Verify that muting LeAudio device, sets the mute state on the audio device generateVolumeStateChanged(null, 1, streamVol, 0, true, true); - verify(mAudioManager, times(1)) + verify(mAudioManager) .adjustStreamVolume(eq(streamType), eq(AudioManager.ADJUST_MUTE), anyInt()); doReturn(true).when(mAudioManager).isStreamMute(eq(AudioManager.STREAM_MUSIC)); // Verify that unmuting LeAudio device, unsets the mute state on the audio device generateVolumeStateChanged(null, 1, streamVol, 0, false, true); - verify(mAudioManager, times(1)) + verify(mAudioManager) .adjustStreamVolume(eq(streamType), eq(AudioManager.ADJUST_UNMUTE), anyInt()); } @@ -670,13 +671,13 @@ public class VolumeControlServiceTest { // Expected index for STREAM_MUSIC int expectedVol = (int) Math.round((double) (volume_groupId_1 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); + verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); mServiceBinder.setGroupActive(groupId_2, true, mAttributionSource); expectedVol = (int) Math.round((double) (volume_groupId_2 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); + verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); } /** Test Volume Control Mute cache. */ @@ -716,7 +717,7 @@ public class VolumeControlServiceTest { // Mute mService.muteGroup(groupId); Assert.assertEquals(true, mService.getGroupMute(groupId)); - verify(mNativeInterface, times(1)).muteGroup(eq(groupId)); + verify(mNativeInterface).muteGroup(eq(groupId)); // Make sure the volume is kept even when muted doReturn(true).when(mAudioManager).isStreamMute(eq(AudioManager.STREAM_MUSIC)); @@ -725,13 +726,13 @@ public class VolumeControlServiceTest { // Lower the volume and keep it mute mService.setGroupVolume(groupId, --volume); Assert.assertEquals(true, mService.getGroupMute(groupId)); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); verify(mNativeInterface, times(0)).unmuteGroup(eq(groupId)); // Don't unmute on consecutive calls either mService.setGroupVolume(groupId, --volume); Assert.assertEquals(true, mService.getGroupMute(groupId)); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); verify(mNativeInterface, times(0)).unmuteGroup(eq(groupId)); // Raise the volume and unmute @@ -739,13 +740,13 @@ public class VolumeControlServiceTest { doReturn(false).when(mAudioManager).isStreamMute(eq(AudioManager.STREAM_MUSIC)); mService.setGroupVolume(groupId, ++volume); Assert.assertEquals(false, mService.getGroupMute(groupId)); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); // Verify the number of unmute calls after the second volume change mService.setGroupVolume(groupId, ++volume); Assert.assertEquals(false, mService.getGroupMute(groupId)); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); // Make sure we unmuted only once - verify(mNativeInterface, times(1)).unmuteGroup(eq(groupId)); + verify(mNativeInterface).unmuteGroup(eq(groupId)); } /** Test if phone will set volume which is read from the buds */ @@ -791,7 +792,7 @@ public class VolumeControlServiceTest { mServiceBinder.setGroupActive(groupId, true, mAttributionSource); int expectedAfVol = (int) Math.round((double) (volumeDevice * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); + verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); // Connect second device and read different volume. Expect it will be set to AF and to // another set member @@ -812,7 +813,7 @@ public class VolumeControlServiceTest { initialAutonomousFlag); expectedAfVol = (int) Math.round((double) (volumeDeviceTwo * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); + verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); } private void testConnectedDeviceWithResetFlag( @@ -863,8 +864,8 @@ public class VolumeControlServiceTest { when(mLeAudioService.getActiveGroupId()).thenReturn(groupId); mServiceBinder.setGroupActive(groupId, true, mAttributionSource); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(streamVolume), anyInt()); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(expectedAfVol)); + verify(mAudioManager).setStreamVolume(anyInt(), eq(streamVolume), anyInt()); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(expectedAfVol)); // Connect second device and read different volume. Expect it will be set to AF and to // another set member @@ -884,7 +885,7 @@ public class VolumeControlServiceTest { initialMuteState, initialAutonomousFlag); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), anyInt(), anyInt()); + verify(mAudioManager).setStreamVolume(anyInt(), anyInt(), anyInt()); verify(mNativeInterface, times(2)).setGroupVolume(eq(groupId), eq(expectedAfVol)); } @@ -927,7 +928,7 @@ public class VolumeControlServiceTest { Assert.assertTrue(mService.getDevices().contains(mDevice)); mService.setGroupVolume(groupId, groupVolume); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(groupVolume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(groupVolume)); // Verify that second device gets the proper group volume level when connected @@ -936,7 +937,7 @@ public class VolumeControlServiceTest { Assert.assertEquals( BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); - verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(groupVolume)); + verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); } /** @@ -979,7 +980,7 @@ public class VolumeControlServiceTest { // But gets the volume when it becomes the group member when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); mService.handleGroupNodeAdded(groupId, mDeviceTwo); - verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(groupVolume)); + verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); } /** @@ -1013,10 +1014,10 @@ public class VolumeControlServiceTest { doReturn(true).when(mAudioManager).isStreamMute(anyInt()); mService.setGroupVolume(groupId, volume); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(volume)); // Check if it was muted - verify(mNativeInterface, times(1)).muteGroup(eq(groupId)); + verify(mNativeInterface).muteGroup(eq(groupId)); Assert.assertEquals(true, mService.getGroupMute(groupId)); @@ -1026,9 +1027,9 @@ public class VolumeControlServiceTest { Assert.assertEquals( BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); - verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(volume)); + verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(volume)); // Check if new device was muted - verify(mNativeInterface, times(1)).mute(eq(mDeviceTwo)); + verify(mNativeInterface).mute(eq(mDeviceTwo)); } /** @@ -1075,8 +1076,8 @@ public class VolumeControlServiceTest { // But gets the volume when it becomes the group member when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); mService.handleGroupNodeAdded(groupId, mDeviceTwo); - verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(volume)); - verify(mNativeInterface, times(1)).mute(eq(mDeviceTwo)); + verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(volume)); + verify(mNativeInterface).mute(eq(mDeviceTwo)); } @Test @@ -1199,7 +1200,7 @@ public class VolumeControlServiceTest { Assert.assertTrue(mService.getDevices().contains(mDevice)); mService.setGroupVolume(groupId, groupVolume); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(groupVolume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(groupVolume)); // Verify that second device gets the proper group volume level when connected @@ -1209,7 +1210,7 @@ public class VolumeControlServiceTest { Assert.assertEquals( BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); - verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(groupVolume)); + verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); // Generate events for both devices generateDeviceOffsetChangedMessageFromNative(mDevice, 1, 100); @@ -1288,7 +1289,7 @@ public class VolumeControlServiceTest { Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); Assert.assertTrue(mService.getDevices().contains(mDevice)); mService.setDeviceVolume(mDevice, deviceOneVolume, false); - verify(mNativeInterface, times(1)).setVolume(eq(mDevice), eq(deviceOneVolume)); + verify(mNativeInterface).setVolume(eq(mDevice), eq(deviceOneVolume)); // Verify that second device gets the proper group volume level when connected generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); @@ -1298,7 +1299,7 @@ public class VolumeControlServiceTest { BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); mService.setDeviceVolume(mDeviceTwo, deviceTwoVolume, false); - verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(deviceTwoVolume)); + verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(deviceTwoVolume)); // Both devices are in the same group when(mLeAudioService.getGroupId(mDevice)).thenReturn(groupId); @@ -1316,8 +1317,8 @@ public class VolumeControlServiceTest { Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); } - verify(callback, times(1)).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); - verify(callback, times(1)).onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); + verify(callback).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); + verify(callback).onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); } @Test @@ -1342,7 +1343,7 @@ public class VolumeControlServiceTest { Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); Assert.assertTrue(mService.getDevices().contains(mDevice)); mService.setDeviceVolume(mDevice, deviceOneVolume, false); - verify(mNativeInterface, times(1)).setVolume(eq(mDevice), eq(deviceOneVolume)); + verify(mNativeInterface).setVolume(eq(mDevice), eq(deviceOneVolume)); // Verify that second device gets the proper group volume level when connected generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); @@ -1352,7 +1353,7 @@ public class VolumeControlServiceTest { BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); mService.setDeviceVolume(mDeviceTwo, deviceTwoVolume, false); - verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(deviceTwoVolume)); + verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(deviceTwoVolume)); // Both devices are in the same group when(mLeAudioService.getGroupId(mDevice)).thenReturn(groupId); @@ -1382,14 +1383,12 @@ public class VolumeControlServiceTest { } // This shall be done only once after mService.registerCallback - verify(callback, times(1)).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); - verify(callback, times(1)).onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); + verify(callback).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); + verify(callback).onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); // This shall be done only once after mServiceBinder.updateNewRegisteredCallback - verify(callback_new_client, times(1)) - .onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); - verify(callback_new_client, times(1)) - .onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); + verify(callback_new_client).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); + verify(callback_new_client).onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); } @Test @@ -1434,7 +1433,7 @@ public class VolumeControlServiceTest { generateDeviceAvailableMessageFromNative(mDevice, 2); mServiceBinder.setDeviceVolume(mDevice, groupVolume, true, mAttributionSource); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(groupVolume)); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); // Register callback and verify it is called with known devices IBluetoothVolumeControlCallback callback = @@ -1512,7 +1511,7 @@ public class VolumeControlServiceTest { // Group is not broadcast primary group, AF will not be notified generateVolumeStateChanged(null, groupId, groupVolume, 0, false, true); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), anyInt(), anyInt()); + verify(mAudioManager).setStreamVolume(anyInt(), anyInt(), anyInt()); } private void connectDevice(BluetoothDevice device) throws Exception { -- GitLab From b2b618d97c659b4a3a622b5377eb7062b76f6a55 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 14 Oct 2024 11:30:15 -0700 Subject: [PATCH 310/875] MetricsLogger: sort connection change logs Sort alphabetically in order to spot error easily Test: atest BluetoothInstrumentationTests Bug: 311772251 Flag: Exempt refactor moving code without op change Change-Id: I54c3555f2cd432b36acbd3a43de85ea9d5b064bd --- .../bluetooth/btservice/MetricsLogger.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java index 10c92eab85b..afbadf71f90 100644 --- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java @@ -188,12 +188,12 @@ public class MetricsLogger { } IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); @@ -215,32 +215,32 @@ public class MetricsLogger { return; } switch (action) { - case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.HEADSET, intent); - break; case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.A2DP, intent); break; + case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.A2DP_SINK, intent); + break; + case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.AVRCP_CONTROLLER, intent); + break; + case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.HEADSET, intent); + break; case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.HEADSET_CLIENT, intent); break; case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.HEARING_AID, intent); break; - case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.A2DP_SINK, intent); - break; case BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.HID_DEVICE, intent); break; case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.HID_HOST, intent); break; - case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.AVRCP_CONTROLLER, intent); - break; - case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.PAN, intent); + case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.LE_AUDIO, intent); break; case BluetoothMap.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.MAP, intent); @@ -248,17 +248,17 @@ public class MetricsLogger { case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.MAP_CLIENT, intent); break; - case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.SAP, intent); - break; - case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.PBAP_CLIENT, intent); + case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.PAN, intent); break; case BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED: logConnectionStateChanges(BluetoothProfile.PBAP, intent); break; - case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED: - logConnectionStateChanges(BluetoothProfile.LE_AUDIO, intent); + case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.PBAP_CLIENT, intent); + break; + case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED: + logConnectionStateChanges(BluetoothProfile.SAP, intent); break; default: Log.w(TAG, "Received unknown intent " + intent); -- GitLab From 7beac6cb722196248e321ed12dfcff68973f2e99 Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Mon, 14 Oct 2024 22:50:55 +0000 Subject: [PATCH 311/875] Resolve incomplete fix for SMP authentication bypass Fix for b/25992313 was landed correctly on main, but in older branches SMP contains identical functions smp_proc_init and smp_proc_rand, both of which exhibit the problem, and only the former of which was patched. This allows the problem to still appear on branches from sc-dev to udc-dev. Add the logic to smp_proc_rand. Bug: 251514170 Test: m com.android.btservices Tag: #security Ignore-AOSP-First: security Merged-In: Id36c06beb13bcbc9b499ef59f6d4e43ac616da10 Change-Id: I51e99c18a322a29632a6cac09ddb2b07bea482fc --- system/stack/smp/smp_act.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/system/stack/smp/smp_act.cc b/system/stack/smp/smp_act.cc index bbbf3dc29ba..5dbef5854c1 100644 --- a/system/stack/smp/smp_act.cc +++ b/system/stack/smp/smp_act.cc @@ -686,6 +686,17 @@ void smp_proc_rand(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) { return; } + if (!((p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) && + (p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT)) && + !(p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM_SENT)) { + // in legacy pairing, the peer should send its rand after + // we send our confirm + tSMP_INT_DATA smp_int_data{}; + smp_int_data.status = SMP_INVALID_PARAMETERS; + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data); + return; + } + /* save the SRand for comparison */ STREAM_TO_ARRAY(p_cb->rrand.data(), p, OCTET16_LEN); } -- GitLab From cee50eb69e8210644cbbfc4e8a0c23685e9a089f Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 14 Oct 2024 11:31:11 -0700 Subject: [PATCH 312/875] MetricsLogger: fix pbap connection metrics This metric has never been added to the filter and never reported anything Test: atest BluetoothInstrumentationTests Bug: 311772251 Flag: Exempt trivial Change-Id: Ia4408e51f6b430f69339bcd7a114746ad6f27439 --- .../app/src/com/android/bluetooth/btservice/MetricsLogger.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java index afbadf71f90..6031e3be24b 100644 --- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java @@ -200,6 +200,7 @@ public class MetricsLogger { filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); mAdapterService.registerReceiver(mReceiver, filter); -- GitLab From b10bac90572f5d7996728fd78c33857db065f56f Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 14 Oct 2024 10:45:11 -0700 Subject: [PATCH 313/875] RootCanal: Implement the command LE Read Local P-256 Public Key Bug: 354107188 Test: atest --host rootcanal_ll_test Flag: EXEMPT, tool change Change-Id: Ic7342ecd7d1de46dadf88c7d2d71c925f97f3904 --- tools/rootcanal/Android.bp | 1 + .../model/controller/controller_properties.cc | 2 +- .../model/controller/dual_mode_controller.cc | 63 ++++++++++++++++++- .../model/controller/dual_mode_controller.h | 3 + tools/rootcanal/packets/hci_packets.pdl | 15 ++--- tools/rootcanal/py/controller.py | 2 +- tools/rootcanal/test/HCI/AEN/BV_06_C.py | 51 +++++++++++++++ tools/rootcanal/test/main.py | 1 + 8 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 tools/rootcanal/test/HCI/AEN/BV_06_C.py diff --git a/tools/rootcanal/Android.bp b/tools/rootcanal/Android.bp index c28ad576fcc..69fc4bc4561 100644 --- a/tools/rootcanal/Android.bp +++ b/tools/rootcanal/Android.bp @@ -305,6 +305,7 @@ python_test_host { ":llcp_packets_python3_gen", "py/bluetooth.py", "py/controller.py", + "test/HCI/AEN/*.py", "test/LL/*.py", "test/LL/CIS/CEN/*.py", "test/LL/CIS/PER/*.py", diff --git a/tools/rootcanal/model/controller/controller_properties.cc b/tools/rootcanal/model/controller/controller_properties.cc index b1ad2e80820..4ee868b159f 100644 --- a/tools/rootcanal/model/controller/controller_properties.cc +++ b/tools/rootcanal/model/controller/controller_properties.cc @@ -285,7 +285,7 @@ static std::array SupportedCommands() { // OpCodeIndex::LE_SET_DATA_LENGTH, OpCodeIndex::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH, OpCodeIndex::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH, - // OpCodeIndex::LE_READ_LOCAL_P_256_PUBLIC_KEY, + OpCodeIndex::LE_READ_LOCAL_P_256_PUBLIC_KEY, // OpCodeIndex::LE_GENERATE_DHKEY_V1, OpCodeIndex::LE_ADD_DEVICE_TO_RESOLVING_LIST, OpCodeIndex::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST, OpCodeIndex::LE_CLEAR_RESOLVING_LIST, diff --git a/tools/rootcanal/model/controller/dual_mode_controller.cc b/tools/rootcanal/model/controller/dual_mode_controller.cc index 7480496a6ea..5563d8319dd 100644 --- a/tools/rootcanal/model/controller/dual_mode_controller.cc +++ b/tools/rootcanal/model/controller/dual_mode_controller.cc @@ -16,6 +16,10 @@ #include "model/controller/dual_mode_controller.h" +#include +#include +#include +#include #include #include @@ -2210,6 +2214,61 @@ void DualModeController::LeWriteSuggestedDefaultDataLength(CommandView command) kNumCommandPackets, status)); } +static ErrorCode generateP256Key(std::array& key_x_coordinate, + std::array& key_y_coordinate) { + auto ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (!ec_key) { + WARNING("EC_KEY_new_by_curve_name(NID_X9_62_prime256v1) failed"); + return ErrorCode::UNSPECIFIED_ERROR; + } + + if (!EC_KEY_generate_key(ec_key)) { + WARNING("EC_KEY_generate_key failed"); + EC_KEY_free(ec_key); + return ErrorCode::UNSPECIFIED_ERROR; + } + + uint8_t* out_buf = nullptr; + auto size = EC_KEY_key2buf(ec_key, POINT_CONVERSION_UNCOMPRESSED, &out_buf, nullptr); + if (!out_buf) { + WARNING("EC_KEY_key2buf failed"); + EC_KEY_free(ec_key); + return ErrorCode::UNSPECIFIED_ERROR; + } + + const size_t expected_size = key_x_coordinate.size() + key_y_coordinate.size() + 1; + if (size != expected_size) { + WARNING("unexpected size {}", size); + OPENSSL_free(out_buf); + EC_KEY_free(ec_key); + return ErrorCode::UNSPECIFIED_ERROR; + } + + memcpy(key_x_coordinate.data(), out_buf + 1, key_x_coordinate.size()); + memcpy(key_y_coordinate.data(), out_buf + 1 + key_x_coordinate.size(), key_y_coordinate.size()); + + // OPENSSL_free(out_buf); // <-- this call fails with error invalid pointer + EC_KEY_free(ec_key); + return ErrorCode::SUCCESS; +} + +void DualModeController::LeReadLocalP256PublicKey(CommandView command) { + auto command_view = bluetooth::hci::LeReadLocalP256PublicKeyView::Create(command); + CHECK_PACKET_VIEW(command_view); + + DEBUG(id_, "<< LE Read Local P-256 Public Key"); + + send_event_(bluetooth::hci::LeReadLocalP256PublicKeyStatusBuilder::Create(ErrorCode::SUCCESS, + kNumCommandPackets)); + + std::array key_x_coordinate = {}; + std::array key_y_coordinate = {}; + ErrorCode status = generateP256Key(key_x_coordinate, key_y_coordinate); + + send_event_(bluetooth::hci::LeReadLocalP256PublicKeyCompleteBuilder::Create( + status, key_x_coordinate, key_y_coordinate)); +} + void DualModeController::LeAddDeviceToResolvingList(CommandView command) { auto command_view = bluetooth::hci::LeAddDeviceToResolvingListView::Create(command); CHECK_PACKET_VIEW(command_view); @@ -3959,8 +4018,8 @@ const std::unordered_map &DualModeController::LeReadSuggestedDefaultDataLength}, {OpCode::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH, &DualModeController::LeWriteSuggestedDefaultDataLength}, - //{OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY, - //&DualModeController::LeReadLocalP256PublicKey}, + {OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY, + &DualModeController::LeReadLocalP256PublicKey}, //{OpCode::LE_GENERATE_DHKEY_V1, //&DualModeController::LeGenerateDhkeyV1}, {OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST, diff --git a/tools/rootcanal/model/controller/dual_mode_controller.h b/tools/rootcanal/model/controller/dual_mode_controller.h index bf95c8a95f4..901d13d8025 100644 --- a/tools/rootcanal/model/controller/dual_mode_controller.h +++ b/tools/rootcanal/model/controller/dual_mode_controller.h @@ -450,6 +450,9 @@ public: void LeReadSuggestedDefaultDataLength(CommandView command); void LeWriteSuggestedDefaultDataLength(CommandView command); + // 7.8.36 + void LeReadLocalP256PublicKey(CommandView command); + // 7.8.38 - 7.8.41 void LeAddDeviceToResolvingList(CommandView command); void LeRemoveDeviceFromResolvingList(CommandView command); diff --git a/tools/rootcanal/packets/hci_packets.pdl b/tools/rootcanal/packets/hci_packets.pdl index 6cb90fea7f9..ec34b4da0f1 100644 --- a/tools/rootcanal/packets/hci_packets.pdl +++ b/tools/rootcanal/packets/hci_packets.pdl @@ -3536,17 +3536,17 @@ packet LeWriteSuggestedDefaultDataLengthComplete : CommandComplete (command_op_c status : ErrorCode, } -packet LeReadLocalP256PublicKeyCommand : Command (op_code = LE_READ_LOCAL_P_256_PUBLIC_KEY) { +packet LeReadLocalP256PublicKey : Command (op_code = LE_READ_LOCAL_P_256_PUBLIC_KEY) { } -packet LeReadLocalP256PublicKeyCommandStatus : CommandStatus (command_op_code = LE_READ_LOCAL_P_256_PUBLIC_KEY) { +packet LeReadLocalP256PublicKeyStatus : CommandStatus (command_op_code = LE_READ_LOCAL_P_256_PUBLIC_KEY) { } -packet LeGenerateDhkeyV1Command : Command (op_code = LE_GENERATE_DHKEY_V1) { +packet LeGenerateDhkeyV1 : Command (op_code = LE_GENERATE_DHKEY_V1) { remote_p_256_public_key : 8[64], } -packet LeGenerateDhkeyV1CommandStatus : CommandStatus (command_op_code = LE_GENERATE_DHKEY_V1) { +packet LeGenerateDhkeyV1Status : CommandStatus (command_op_code = LE_GENERATE_DHKEY_V1) { } packet LeAddDeviceToResolvingList : Command (op_code = LE_ADD_DEVICE_TO_RESOLVING_LIST) { @@ -5211,12 +5211,13 @@ packet LeDataLengthChange : LeMetaEvent (subevent_code = DATA_LENGTH_CHANGE) { max_rx_time : 16, // 0x0148 - 0x4290 } -packet ReadLocalP256PublicKeyComplete : LeMetaEvent (subevent_code = READ_LOCAL_P256_PUBLIC_KEY_COMPLETE) { +packet LeReadLocalP256PublicKeyComplete : LeMetaEvent (subevent_code = READ_LOCAL_P256_PUBLIC_KEY_COMPLETE) { status : ErrorCode, - local_p_256_public_key : 8[64], + key_x_coordinate : 8[32], + key_y_coordinate : 8[32], } -packet GenerateDhKeyComplete : LeMetaEvent (subevent_code = GENERATE_DHKEY_COMPLETE) { +packet LeGenerateDhKeyComplete : LeMetaEvent (subevent_code = GENERATE_DHKEY_COMPLETE) { status : ErrorCode, dh_key : 8[32], } diff --git a/tools/rootcanal/py/controller.py b/tools/rootcanal/py/controller.py index be3488cbcb1..80e83072b4f 100644 --- a/tools/rootcanal/py/controller.py +++ b/tools/rootcanal/py/controller.py @@ -315,7 +315,7 @@ class ControllerTest(unittest.IsolatedAsyncioTestCase): async with asyncio.timeout(timeout): while True: - packet = await asyncio.wait_for(self.controller.receive_ll()) + packet = await self.controller.receive_ll() pdu = ll.LinkLayerPacket.parse_all(packet) for ignored_pdu in ignored_pdus: diff --git a/tools/rootcanal/test/HCI/AEN/BV_06_C.py b/tools/rootcanal/test/HCI/AEN/BV_06_C.py new file mode 100644 index 00000000000..7a04979bcd0 --- /dev/null +++ b/tools/rootcanal/test/HCI/AEN/BV_06_C.py @@ -0,0 +1,51 @@ +# Copyright 2024 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 hci_packets as hci +import link_layer_packets as ll +import unittest +from hci_packets import ErrorCode +from py.bluetooth import Address +from py.controller import ControllerTest + + +class Test(ControllerTest): + + # HCI/AEN/BV-06-C [Public Keys] + # + # Verify that the IUT can generate a P-256 Public-Private key pair and + # return the P-256 Public Key + async def test(self): + controller = self.controller + + controller.send_cmd(hci.LeReadLocalP256PublicKey()) + + await self.expect_evt(hci.LeReadLocalP256PublicKeyStatus(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + first = await self.expect_evt( + hci.LeReadLocalP256PublicKeyComplete(status=ErrorCode.SUCCESS, + key_x_coordinate=self.Any, + key_y_coordinate=self.Any)) + + controller.send_cmd(hci.LeReadLocalP256PublicKey()) + + await self.expect_evt(hci.LeReadLocalP256PublicKeyStatus(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + second = await self.expect_evt( + hci.LeReadLocalP256PublicKeyComplete(status=ErrorCode.SUCCESS, + key_x_coordinate=self.Any, + key_y_coordinate=self.Any)) + + self.assertTrue( + (first.key_x_coordinate, first.key_y_coordinate) != (second.key_x_coordinate, second.key_y_coordinate)) diff --git a/tools/rootcanal/test/main.py b/tools/rootcanal/test/main.py index b61a5b87a78..fba8d2aba3b 100644 --- a/tools/rootcanal/test/main.py +++ b/tools/rootcanal/test/main.py @@ -20,6 +20,7 @@ import tempfile import unittest tests = [ + 'HCI.AEN.BV_06_C', 'LL.CIS.CEN.BV_01_C', 'LL.CIS.CEN.BV_03_C', 'LL.CIS.CEN.BV_10_C', -- GitLab From eeea0338a602f521c78f71d24fd7581ea9cbd7fa Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 19 Sep 2024 19:11:12 -0700 Subject: [PATCH 314/875] HAP avatar test: Delete preset and check notify Test: atest avater:HapTest Bug: 350514735 Flag: TEST_ONLY Change-Id: I1ba15b41b2fb782f59076eab16127485ad4f50dd --- android/pandora/test/hap_test.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/android/pandora/test/hap_test.py b/android/pandora/test/hap_test.py index ec1fd40f89d..6b825dfe3df 100644 --- a/android/pandora/test/hap_test.py +++ b/android/pandora/test/hap_test.py @@ -157,7 +157,7 @@ class HapTest(base_test.BaseTestClass): return dut_connection_to_ref - async def assertIdentiqPresetInDutAndRef(self, dut_connection_to_ref: Connection): + async def assertIdenticalPreset(self, dut_connection_to_ref: Connection): remote_preset = toBumblePresetList( (await self.hap_grpc.GetAllPresetRecords(connection=dut_connection_to_ref)).preset_record_list) AssertThat(remote_preset).ContainsExactlyElementsIn( # type: ignore @@ -177,5 +177,17 @@ class HapTest(base_test.BaseTestClass): await self.logcat.Log("test_get_preset") dut_connection_to_ref = await self.setupHapConnection() - await self.assertIdentiqPresetInDutAndRef(dut_connection_to_ref) + await self.assertIdenticalPreset(dut_connection_to_ref) + @asynchronous + async def test_preset__remove_preset__verify_dut_is_updated(self) -> None: + await self.logcat.Log("test_preset__remove_preset__verify_dut_is_updated") + dut_connection_to_ref = await self.setupHapConnection() + + await self.assertIdenticalPreset(dut_connection_to_ref) + + await self.logcat.Log("Remove preset in server") + await self.has.delete_preset(unavailable_preset.index) + await asyncio.sleep(1) # wait event + + await self.assertIdenticalPreset(dut_connection_to_ref) -- GitLab From 7a99de96c8ca5927b3d87f8c074bf9f97070c8cd Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 4 Oct 2024 17:24:48 -0700 Subject: [PATCH 315/875] Hap: add relevant preset test Bug: 371636624 Bug: 362424892 Test: atest avatar:HapTest Flag: TEST_ONLY Change-Id: Ida5ef4cb03fb93c783ac7451d1fe1504ff0be511 --- android/pandora/server/src/Hap.kt | 26 ++++++++ android/pandora/test/hap_test.py | 62 ++++++++++++++++++- .../interfaces/pandora_experimental/hap.proto | 12 ++++ 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/android/pandora/server/src/Hap.kt b/android/pandora/server/src/Hap.kt index c4a6f84805d..416879b46cf 100644 --- a/android/pandora/server/src/Hap.kt +++ b/android/pandora/server/src/Hap.kt @@ -232,6 +232,32 @@ class Hap(val context: Context) : HAPImplBase(), Closeable { } } + override fun getActivePresetRecord( + request: GetActivePresetRecordRequest, + responseObserver: StreamObserver, + ) { + grpcUnary(scope, responseObserver) { + val device = request.connection.toBluetoothDevice(bluetoothAdapter) + Log.i(TAG, "GetActivePresetRecord($device)") + + val presetInfo: BluetoothHapPresetInfo? = bluetoothHapClient.getActivePresetInfo(device) + + if (presetInfo != null) { + GetActivePresetRecordResponse.newBuilder() + .setPresetRecord( + PresetRecord.newBuilder() + .setIndex(presetInfo.getIndex()) + .setName(presetInfo.getName()) + .setIsWritable(presetInfo.isWritable()) + .setIsAvailable(presetInfo.isAvailable()) + ) + .build() + } else { + GetActivePresetRecordResponse.getDefaultInstance() + } + } + } + override fun setNextPreset( request: SetNextPresetRequest, responseObserver: StreamObserver, diff --git a/android/pandora/test/hap_test.py b/android/pandora/test/hap_test.py index 6b825dfe3df..b3d670f8528 100644 --- a/android/pandora/test/hap_test.py +++ b/android/pandora/test/hap_test.py @@ -16,7 +16,7 @@ import asyncio from avatar import BumblePandoraDevice, PandoraDevice, PandoraDevices, asynchronous from bumble.gatt import GATT_HEARING_ACCESS_SERVICE, GATT_AUDIO_STREAM_CONTROL_SERVICE, GATT_PUBLISHED_AUDIO_CAPABILITIES_SERVICE from bumble.profiles import hap -from bumble.profiles.hap import DynamicPresets, HearingAccessService, HearingAidFeatures, HearingAidType, IndependentPresets, PresetRecord, PresetSynchronizationSupport, WritablePresetsSupport +from bumble.profiles.hap import DynamicPresets, HearingAccessService, HearingAidFeatures, HearingAidType, IndependentPresets, PresetChangedOperation, PresetChangedOperationAvailable, PresetRecord, PresetSynchronizationSupport, WritablePresetsSupport from pandora_experimental.os_grpc_aio import Os as OsAio from pandora_experimental.gatt_grpc_aio import GATT @@ -157,12 +157,18 @@ class HapTest(base_test.BaseTestClass): return dut_connection_to_ref - async def assertIdenticalPreset(self, dut_connection_to_ref: Connection): + async def assertIdenticalPreset(self, dut_connection_to_ref: Connection) -> None: remote_preset = toBumblePresetList( (await self.hap_grpc.GetAllPresetRecords(connection=dut_connection_to_ref)).preset_record_list) AssertThat(remote_preset).ContainsExactlyElementsIn( # type: ignore get_server_preset_sorted(self.has)).InOrder() # type: ignore + async def verify_no_crash(self, dut_connection_to_ref: Connection) -> None: + ''' Periodically check that there is no android crash ''' + for __i__ in range(10): + await asyncio.sleep(.3) + await self.assertIdenticalPreset(dut_connection_to_ref) + @asynchronous async def test_get_features(self) -> None: await self.logcat.Log("test_get_features") @@ -191,3 +197,55 @@ class HapTest(base_test.BaseTestClass): await asyncio.sleep(1) # wait event await self.assertIdenticalPreset(dut_connection_to_ref) + + @asynchronous + async def test__add_preset__verify_dut_is_updated(self) -> None: + await self.logcat.Log("test__add_preset__verify_dut_is_updated") + dut_connection_to_ref = await self.setupHapConnection() + + await self.assertIdenticalPreset(dut_connection_to_ref) + + added_preset = PresetRecord(bar_preset.index + 3, "added_preset") + self.has.preset_records[added_preset.index] = added_preset + + await self.logcat.Log("Preset added in server. Notify now") + await self.has.generic_update( + PresetChangedOperation(PresetChangedOperation.ChangeId.GENERIC_UPDATE, + PresetChangedOperation.Generic(bar_preset.index, added_preset))) + await asyncio.sleep(1) # wait event + + await self.assertIdenticalPreset(dut_connection_to_ref) + + @asynchronous + async def test__set_non_existing_preset_as_active__verify_no_crash_and_no_update(self) -> None: + await self.logcat.Log("test__set_non_existing_preset_as_active__verify_no_crash_and_no_update") + non_existing_preset_index = 79 + AssertThat(non_existing_preset_index).IsNotIn(self.has.preset_records.keys()) # type: ignore + dut_connection_to_ref = await self.setupHapConnection() + AssertThat( + toBumblePreset( # type: ignore + (await self.hap_grpc.GetActivePresetRecord(connection=dut_connection_to_ref + )).preset_record)).IsEqualTo(foo_preset) + + await self.logcat.Log("Notify active update to non existing index") + # bypass the set_active_preset checks by sending an invalid index on purpose + self.has.active_preset_index = non_existing_preset_index + await self.has.notify_active_preset() + + await self.verify_no_crash(dut_connection_to_ref) + AssertThat( + toBumblePreset( # type: ignore + (await self.hap_grpc.GetActivePresetRecord(connection=dut_connection_to_ref + )).preset_record)).IsEqualTo(foo_preset) + + @asynchronous + async def test__set_non_existing_preset_as_available__verify_no_crash_and_no_update(self) -> None: + await self.logcat.Log("test__set_non_existing_preset_as_available__verify_no_crash_and_no_update") + non_existing_preset_index = 79 + AssertThat(non_existing_preset_index).IsNotIn(self.has.preset_records.keys()) # type: ignore + dut_connection_to_ref = await self.setupHapConnection() + + await self.logcat.Log("Notify available preset to non existing index") + await self.has.generic_update(PresetChangedOperationAvailable(non_existing_preset_index)) + + await self.verify_no_crash(dut_connection_to_ref) diff --git a/pandora/interfaces/pandora_experimental/hap.proto b/pandora/interfaces/pandora_experimental/hap.proto index dc6298d70de..5847887529e 100644 --- a/pandora/interfaces/pandora_experimental/hap.proto +++ b/pandora/interfaces/pandora_experimental/hap.proto @@ -22,6 +22,8 @@ service HAP { rpc GetFeatures(GetFeaturesRequest) returns (GetFeaturesResponse); // Set active preset by index rpc SetActivePreset(SetActivePresetRequest) returns (google.protobuf.Empty); + // Get active preset record + rpc GetActivePresetRecord(GetActivePresetRecordRequest) returns (GetActivePresetRecordResponse); // Set next preset rpc SetNextPreset(SetNextPresetRequest) returns (google.protobuf.Empty); // Set next preset @@ -66,6 +68,16 @@ message SetActivePresetRequest { uint32 index = 2; } +message GetActivePresetRecordRequest { + // Connection crafted by grpc server + Connection connection = 1; +} + +message GetActivePresetRecordResponse { + // Received Preset Record + PresetRecord preset_record = 1; +} + // Request of the `SetNextPreset` method. message SetNextPresetRequest { // Connection crafted by grpc server -- GitLab From eed2e6b623f213856b47bddce68e081243da7944 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 15 Oct 2024 00:38:49 +0000 Subject: [PATCH 316/875] system/stack/avdt: Fix potential null dereference Bug: 358212054 Flag: com.android.bluetooth.flags.btsec_avdt_msg_ind_type_confusion Test: m libbluetooth Ignore-AOSP-First: security Change-Id: Iada59725db8cd68d7e1ca6f06b0119b3c3df71f3 --- system/stack/avdt/avdt_msg.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system/stack/avdt/avdt_msg.cc b/system/stack/avdt/avdt_msg.cc index 6d59fbaaf3b..115a9bc2603 100644 --- a/system/stack/avdt/avdt_msg.cc +++ b/system/stack/avdt/avdt_msg.cc @@ -1554,8 +1554,7 @@ void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf) { if (com::android::bluetooth::flags::btsec_avdt_msg_ind_type_confusion()) { if (((msg_type == AVDT_MSG_TYPE_RSP) || (msg_type == AVDT_MSG_TYPE_REJ)) && (p_ccb->p_curr_cmd == nullptr || p_ccb->p_curr_cmd->event != sig)) { - log::warn("Dropping msg with mismatched sig; sig={} event type={}", sig, - p_ccb->p_curr_cmd->event); + log::warn("Dropping msg with mismatched sig; sig={}", sig); ok = false; } } -- GitLab From 38cd00772f1685bb3942a8da357b7b8cd5981e81 Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Wed, 2 Oct 2024 20:07:38 +0800 Subject: [PATCH 317/875] Add flag rfcomm_cancel_ongoing_sdp_on_close Bug: 370916753 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: I66a0aa1d275db4a2899b97dc3c6adcb14be0877a --- flags/rfcomm.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/rfcomm.aconfig b/flags/rfcomm.aconfig index d5c5f1ab05b..df53931078d 100644 --- a/flags/rfcomm.aconfig +++ b/flags/rfcomm.aconfig @@ -37,3 +37,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "rfcomm_cancel_ongoing_sdp_on_close" + namespace: "bluetooth" + description: "Make sure the ongoing SDP is cleaned up when the socket is closed" + bug: "370916753" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From d41a2fac4267c6d904b9366aa4a47e18ba8e4b72 Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Tue, 15 Oct 2024 04:51:14 +0000 Subject: [PATCH 318/875] stack: add support to convert HCI error codes into bt_status Convert HCI error codes to bt_status_t to provide accurate error reports for upper layers. Bug: 353527430 Test: m com.android.btservices Test: emerge-brya floss Flag: EXEMPT, error code refactoring, no logic change Change-Id: I37cd7b31a1493a46d8fa9699bf0145f077ff64ae --- system/stack/include/hci_error_code.h | 90 +++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/system/stack/include/hci_error_code.h b/system/stack/include/hci_error_code.h index cb20570591c..04ebb4700a5 100644 --- a/system/stack/include/hci_error_code.h +++ b/system/stack/include/hci_error_code.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -124,6 +125,95 @@ inline std::string hci_error_code_text(const tHCI_ERROR_CODE& error_code) { } } +inline bt_status_t hci_error_to_bt_status(const tHCI_ERROR_CODE& error_code) { + switch (error_code) { + case HCI_SUCCESS: /* 0x00 */ + return BT_STATUS_SUCCESS; + case HCI_ERR_ILLEGAL_COMMAND: /* 0x01 */ + return BT_STATUS_UNSUPPORTED; + case HCI_ERR_NO_CONNECTION: /* 0x02 */ + return BT_STATUS_NOT_READY; + case HCI_ERR_HW_FAILURE: /* 0x03 */ + return BT_STATUS_FAIL; + case HCI_ERR_PAGE_TIMEOUT: /* 0x04 */ + return BT_STATUS_TIMEOUT; + case HCI_ERR_AUTH_FAILURE: /* 0x05 */ + return BT_STATUS_AUTH_FAILURE; + case HCI_ERR_KEY_MISSING: /* 0x06 */ + return BT_STATUS_AUTH_FAILURE; + case HCI_ERR_MEMORY_FULL: /* 0x07 */ + return BT_STATUS_NOMEM; + case HCI_ERR_CONNECTION_TOUT: /* 0x08 */ + return BT_STATUS_TIMEOUT; + case HCI_ERR_MAX_NUM_OF_CONNECTIONS: /* 0x09 */ + return BT_STATUS_FAIL; + case HCI_ERR_MAX_NUM_OF_SCOS: /* 0x0A */ + return BT_STATUS_FAIL; + case HCI_ERR_CONNECTION_EXISTS: /* 0x0B */ + return BT_STATUS_BUSY; + case HCI_ERR_COMMAND_DISALLOWED: /* 0x0C */ + return BT_STATUS_UNSUPPORTED; + case HCI_ERR_HOST_REJECT_RESOURCES: /* 0x0D */ + return BT_STATUS_BUSY; + case HCI_ERR_HOST_REJECT_SECURITY: /* 0x0E */ + return BT_STATUS_AUTH_REJECTED; + case HCI_ERR_HOST_REJECT_DEVICE: /* 0x0F */ + return BT_STATUS_AUTH_REJECTED; + case HCI_ERR_HOST_TIMEOUT: /* 0x10 */ + return BT_STATUS_TIMEOUT; + case HCI_ERR_ILLEGAL_PARAMETER_FMT: /* 0x12 */ + return BT_STATUS_PARM_INVALID; + case HCI_ERR_PEER_USER: /* 0x13 */ + return BT_STATUS_RMT_DEV_DOWN; + case HCI_ERR_REMOTE_LOW_RESOURCE: /* 0x14 */ + return BT_STATUS_RMT_DEV_DOWN; + case HCI_ERR_REMOTE_POWER_OFF: /* 0x15 */ + return BT_STATUS_RMT_DEV_DOWN; + case HCI_ERR_CONN_CAUSE_LOCAL_HOST: /* 0x16 */ + return BT_STATUS_DONE; + case HCI_ERR_REPEATED_ATTEMPTS: /* 0x17 */ + return BT_STATUS_FAIL; + case HCI_ERR_PAIRING_NOT_ALLOWED: /* 0x18 */ + return BT_STATUS_AUTH_REJECTED; + case HCI_ERR_UNSUPPORTED_REM_FEATURE: /* 0x1A */ + return BT_STATUS_UNSUPPORTED; + case HCI_ERR_UNSPECIFIED: /* 0x1F */ + return BT_STATUS_FAIL; + case HCI_ERR_LMP_RESPONSE_TIMEOUT: /* 0x22 */ + return BT_STATUS_TIMEOUT; + case HCI_ERR_LMP_ERR_TRANS_COLLISION: /* 0x23 */ + return BT_STATUS_FAIL; + case HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE: /* 0x25 */ + return BT_STATUS_AUTH_REJECTED; + case HCI_ERR_UNIT_KEY_USED: /* 0x26 */ + return BT_STATUS_AUTH_FAILURE; + case HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED: /* 0x29 */ + return BT_STATUS_UNSUPPORTED; + case HCI_ERR_DIFF_TRANSACTION_COLLISION: /* 0x2A */ + return BT_STATUS_FAIL; + case HCI_ERR_INSUFFCIENT_SECURITY: /* 0x2F */ + return BT_STATUS_AUTH_REJECTED; + case HCI_ERR_ROLE_SWITCH_PENDING: /* 0x32 */ + return BT_STATUS_BUSY; + case HCI_ERR_ROLE_SWITCH_FAILED: /* 0x35 */ + return BT_STATUS_FAIL; + case HCI_ERR_HOST_BUSY_PAIRING: /* 0x38 */ + return BT_STATUS_BUSY; + case HCI_ERR_UNACCEPT_CONN_INTERVAL: /* 0x3B */ + return BT_STATUS_PARM_INVALID; + case HCI_ERR_ADVERTISING_TIMEOUT: /* 0x3C */ + return BT_STATUS_TIMEOUT; + case HCI_ERR_CONN_FAILED_ESTABLISHMENT: /* 0x3E */ + return BT_STATUS_FAIL; + case HCI_ERR_LIMIT_REACHED: /* 0x43 */ + return BT_STATUS_FAIL; + case HCI_ERR_CANCELLED_BY_LOCAL_HOST: /* 0x44 */ + return BT_STATUS_DONE; + default: + return BT_STATUS_FAIL; + } +} + // Context equivalence using tHCI_STATUS = tHCI_ERROR_CODE; inline std::string hci_status_code_text(const tHCI_STATUS& status_code) { -- GitLab From 98f51566912ff2b16f19c2b7c5a2651b6f34e97a Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Mon, 14 Oct 2024 19:12:37 +0000 Subject: [PATCH 319/875] btif: fix btif_dm lint error Fix btif_dm lint error Bug: 353527430 Test: mmm packages/modules/Bluetooth Flag: EXEMPT, lint fix only Change-Id: I91f023a19fcedcff9a5eca44d3f90aa8ca9eaaa8 --- system/btif/src/btif_dm.cc | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 082dded39db..5f443e03a8f 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -59,7 +59,6 @@ #include "btif_api.h" #include "btif_bqr.h" #include "btif_config.h" -#include "btif_dm.h" #include "btif_metrics_logging.h" #include "btif_sdp.h" #include "btif_storage.h" @@ -462,7 +461,7 @@ static bool check_eir_appearance(tBTA_DM_SEARCH* p_search_data, uint16_t* p_appe * Populate p_remote_name, if provided and remote name found * ******************************************************************************/ -static bool get_cached_remote_name(const RawAddress& bd_addr, uint8_t* p_remote_name, +static bool get_cached_remote_name(const RawAddress& bd_addr, bt_bdname_t* p_remote_name, uint8_t* p_remote_name_len) { bt_bdname_t bdname; bt_property_t prop_name; @@ -472,7 +471,7 @@ static bool get_cached_remote_name(const RawAddress& bd_addr, uint8_t* p_remote_ BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME, sizeof(bt_bdname_t), &bdname); if (btif_storage_get_remote_device_property(&bd_addr, &prop_name) == BT_STATUS_SUCCESS) { if (p_remote_name && p_remote_name_len) { - strcpy((char*)p_remote_name, (char*)bdname.name); + snprintf((char*)p_remote_name->name, sizeof(p_remote_name->name), "%s", (char*)bdname.name); *p_remote_name_len = strlen((char*)p_remote_name); } return true; @@ -1335,7 +1334,7 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* bdname.name[0] = 0; if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len)) { - get_cached_remote_name(p_search_data->inq_res.bd_addr, bdname.name, &remote_name_len); + get_cached_remote_name(p_search_data->inq_res.bd_addr, &bdname, &remote_name_len); } /* Check EIR for services */ @@ -3125,39 +3124,40 @@ bool btif_dm_get_smp_config(tBTE_APPL_CFG* p_cfg) { char conf[64]; char* pch; char* endptr; + char* saveptr; strncpy(conf, recv->c_str(), 64); conf[63] = 0; // null terminate - pch = strtok(conf, ","); + pch = strtok_r(conf, ",", &saveptr); if (pch != NULL) { p_cfg->ble_auth_req = (uint8_t)strtoul(pch, &endptr, 16); } else { return false; } - pch = strtok(NULL, ","); + pch = strtok_r(NULL, ",", &saveptr); if (pch != NULL) { p_cfg->ble_io_cap = (uint8_t)strtoul(pch, &endptr, 16); } else { return false; } - pch = strtok(NULL, ","); + pch = strtok_r(NULL, ",", &saveptr); if (pch != NULL) { p_cfg->ble_init_key = (uint8_t)strtoul(pch, &endptr, 16); } else { return false; } - pch = strtok(NULL, ","); + pch = strtok_r(NULL, ",", &saveptr); if (pch != NULL) { p_cfg->ble_resp_key = (uint8_t)strtoul(pch, &endptr, 16); } else { return false; } - pch = strtok(NULL, ","); + pch = strtok_r(NULL, ",", &saveptr); if (pch != NULL) { p_cfg->ble_max_key_size = (uint8_t)strtoul(pch, &endptr, 16); } else { @@ -3770,7 +3770,8 @@ void btif_debug_bond_event_dump(int fd) { char eventtime[20]; char temptime[20]; - struct tm* tstamp = localtime(&event->timestamp.tv_sec); + struct tm buf; + struct tm* tstamp = localtime_r(&event->timestamp.tv_sec, &buf); strftime(temptime, sizeof(temptime), "%H:%M:%S", tstamp); snprintf(eventtime, sizeof(eventtime), "%s.%03ld", temptime, event->timestamp.tv_nsec / 1000000); -- GitLab From 597b95bf5512859594cc7f781a3744812ee340d0 Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Tue, 15 Oct 2024 04:54:44 +0000 Subject: [PATCH 320/875] btif: Improve ACL connection failure reporting This commit enhances the reporting of ACL connection failures by providing more specific error codes. Instead of always reporting `BT_STATUS_FAIL` when a link up fails, we now map the underlying HCI error code to a more informative `bt_status_t` value. This allows higher-level components to better understand the cause of the connection failure. E.g., Floss metrics system which tracks connection failure reasons. Bug: 353527430 Test: mmm packages/modules/Bluetooth Test: manually verified new error code are used Flag: EXEMPT, error code refactoring, no logic change Change-Id: Icafe9fd5032f732477beb9e680dc6b69cb0035a1 --- system/btif/src/btif_dm.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 5f443e03a8f..419f6886400 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -2207,8 +2207,9 @@ void btif_dm_acl_evt(tBTA_DM_ACL_EVT event, tBTA_DM_ACL* p_data) { case BTA_DM_LINK_UP_FAILED_EVT: GetInterfaceToProfiles()->events->invoke_acl_state_changed_cb( - BT_STATUS_FAIL, p_data->link_up_failed.bd_addr, BT_ACL_STATE_DISCONNECTED, - p_data->link_up_failed.transport_link_type, p_data->link_up_failed.status, + hci_error_to_bt_status(p_data->link_up_failed.status), p_data->link_up_failed.bd_addr, + BT_ACL_STATE_DISCONNECTED, p_data->link_up_failed.transport_link_type, + p_data->link_up_failed.status, btm_is_acl_locally_initiated() ? bt_conn_direction_t::BT_CONN_DIRECTION_OUTGOING : bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING, INVALID_ACL_HANDLE); -- GitLab From 67df3b4f022064ef9c66c344289d9fea6df47664 Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Thu, 12 Sep 2024 10:46:10 +0000 Subject: [PATCH 321/875] Flag: com.android.bluetooth.flags.ignore_unrelated_cancel_bond Test: mmm packages/modules/Bluetooth Bug: 366150975 Bug: 315241296 Change-Id: I6a2069862776b599261eb1b76f2fc04b07e58e43 --- flags/btif_dm.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/btif_dm.aconfig b/flags/btif_dm.aconfig index 978acc9550d..2f16904b8fc 100644 --- a/flags/btif_dm.aconfig +++ b/flags/btif_dm.aconfig @@ -10,3 +10,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "ignore_unrelated_cancel_bond" + namespace: "bluetooth" + description: "Accept the cancelBond request only for the currently pairing device" + bug: "366150975" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 6126cbf48b1c2ce47274c17eed3f284786f70b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Thu, 10 Oct 2024 10:06:26 +0000 Subject: [PATCH 322/875] leaudio: Fix switching between LeAudio headsets When switching between LeAudio Headsets, Java is interested only in getting ACTIVE groups status with new group. This is because, LeAudioService is aware about active group and when switching to new active group, it can update AudioManager in a single call which improves user experiance when switching during the streaming. Bug: 369599302 Test: atest LeAudioServiceTest bluetooth_le_audio_client_test Flag: Exempt, regression tested with unit tests, new test added Change-Id: Ifc6564e973c1255ad04d5221249b3313fa60d6af --- .../bluetooth/le_audio/LeAudioService.java | 21 ++++- .../le_audio/LeAudioServiceTest.java | 87 +++++++++++++++---- system/bta/le_audio/client.cc | 6 +- 3 files changed, 90 insertions(+), 24 deletions(-) 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 b1a47f34df5..c93e10febd7 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -2108,7 +2108,8 @@ public class LeAudioService extends ProfileService { + (", isSink: " + isSink) + (" isSource: " + isSource) + (", mActiveAudioInDevice: " + mActiveAudioInDevice) - + (", mActiveAudioOutDevice: " + mActiveAudioOutDevice)); + + (", mActiveAudioOutDevice: " + mActiveAudioOutDevice) + + (", mExposedActiveDevice: " + mExposedActiveDevice)); if (!device.equals(mExposedActiveDevice)) { return; @@ -2123,9 +2124,21 @@ public class LeAudioService extends ProfileService { return; } - Log.i(TAG, "Audio manager disactivate LeAudio device " + mExposedActiveDevice); - mExposedActiveDevice = null; - setActiveDevice(null); + if (device.equals(mActiveAudioInDevice) || device.equals(mActiveAudioOutDevice)) { + Log.i(TAG, "Audio manager disactivate LeAudio device " + mExposedActiveDevice); + mExposedActiveDevice = null; + setActiveDevice(null); + return; + } + + Log.i( + TAG, + ("LeAudio active device switch: " + + mExposedActiveDevice + + " -> " + + (mActiveAudioInDevice != null + ? mActiveAudioInDevice + : mActiveAudioOutDevice))); } /* Notifications of audio device connection/disconn events. */ 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 90dd85cac2a..6b9668f9cf2 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 @@ -1643,8 +1643,6 @@ public class LeAudioServiceTest { ArgumentCaptor connectionInfoArgumentCaptor = ArgumentCaptor.forClass(BluetoothProfileConnectionInfo.class); - /* Expect 2 calles to Audio Manager - one for output as this is - * Ringtone use case */ verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mSingleDevice), eq(null), connectionInfoArgumentCaptor.capture()); @@ -1660,39 +1658,90 @@ public class LeAudioServiceTest { assertThat(mService.setActiveDevice(mSingleDevice_2)).isTrue(); verify(mNativeInterface).groupSetActive(groupId_2); - // First wait for INACTIVE state will be sent from native - LeAudioStackEvent inactiveGroupState = + + // First wait for ACTIVE state will be sent from native + LeAudioStackEvent activeGroupState = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); - inactiveGroupState.valueInt1 = groupId_1; - inactiveGroupState.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE; - mService.messageFromNative(inactiveGroupState); + activeGroupState.valueInt1 = groupId_2; + activeGroupState.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; + activeGroupState.valueInt3 = groupId_1; + mService.messageFromNative(activeGroupState); - // Make sure suppressNoisyIntent is set to true. Soon new group will be active verify(mAudioManager) .handleBluetoothActiveDeviceChanged( - eq(null), eq(mSingleDevice), connectionInfoArgumentCaptor.capture()); + eq(mSingleDevice_2), + eq(mSingleDevice), + connectionInfoArgumentCaptor.capture()); connInfo = connectionInfoArgumentCaptor.getValue(); assertThat(connInfo.isSuppressNoisyIntent()).isTrue(); + injectAudioDeviceRemoved( mSingleDevice, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, false); + injectAudioDeviceAdded( + mSingleDevice_2, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, true); + verify(mNativeInterface, times(0)).groupSetActive(-1); + } - reset(mAudioManager); + /** Test switching active groups */ + @Test + public void testAudioFrameworkAutonomousDeviceRemoval() { + int groupId_1 = 1; - // First wait for ACTIVE state will be sent from native - LeAudioStackEvent activeGroupState = + /* AUDIO_DIRECTION_OUTPUT_BIT = 0x01 */ + int direction = 1; + int snkAudioLocation = 3; + int srcAudioLocation = 4; + int availableContexts = 5 + BluetoothLeAudio.CONTEXT_TYPE_RINGTONE; + + // Not connected device + assertThat(mService.setActiveDevice(mSingleDevice)).isFalse(); + + // Define some return values needed in test + doReturn(-1).when(mVolumeControlService).getAudioDeviceGroupVolume(anyInt()); + doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class)); + + // Connect both + connectTestDevice(mSingleDevice, groupId_1); + + // Add location support + LeAudioStackEvent audioConfChangedEvent = + new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED); + audioConfChangedEvent.device = mSingleDevice; + audioConfChangedEvent.valueInt1 = direction; + audioConfChangedEvent.valueInt2 = groupId_1; + audioConfChangedEvent.valueInt3 = snkAudioLocation; + audioConfChangedEvent.valueInt4 = srcAudioLocation; + audioConfChangedEvent.valueInt5 = availableContexts; + mService.messageFromNative(audioConfChangedEvent); + + assertThat(mService.setActiveDevice(mSingleDevice)).isTrue(); + verify(mNativeInterface).groupSetActive(groupId_1); + + // Set group and device as active + LeAudioStackEvent groupStatusChangedEvent = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); - activeGroupState.valueInt1 = groupId_2; - activeGroupState.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; - mService.messageFromNative(activeGroupState); + groupStatusChangedEvent.valueInt1 = groupId_1; + groupStatusChangedEvent.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; + mService.messageFromNative(groupStatusChangedEvent); + + verify(mTbsService).setInbandRingtoneSupport(mSingleDevice); + + ArgumentCaptor connectionInfoArgumentCaptor = + ArgumentCaptor.forClass(BluetoothProfileConnectionInfo.class); verify(mAudioManager) .handleBluetoothActiveDeviceChanged( - eq(mSingleDevice_2), eq(null), connectionInfoArgumentCaptor.capture()); - connInfo = connectionInfoArgumentCaptor.getValue(); + eq(mSingleDevice), eq(null), connectionInfoArgumentCaptor.capture()); + + injectAudioDeviceAdded(mSingleDevice, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, true); + + BluetoothProfileConnectionInfo connInfo = connectionInfoArgumentCaptor.getValue(); assertThat(connInfo.isSuppressNoisyIntent()).isTrue(); - injectAudioDeviceAdded( - mSingleDevice_2, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, true); + // AudioManager removes audio device + injectAudioDeviceRemoved( + mSingleDevice, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, false); + verify(mNativeInterface, times(1)).groupSetActive(-1); } /** Test setting active device group without Ringtone context */ diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 69a6b501961..e76c7eee2da 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -1434,8 +1434,12 @@ public: * the new group so the group change is correctly handled in OnStateMachineStatusReportCb */ active_group_id_ = group_id; + SuspendedForReconfiguration(); GroupStop(previous_active_group); - callbacks_->OnGroupStatus(previous_active_group, GroupStatus::INACTIVE); + /* Note: On purpose we are not sending INACTIVE status up to Java, because previous active + * group will be provided in ACTIVE status. This is in order to have single call to audio + * framework + */ } /* Reset sink listener notified status */ -- GitLab From d2cbc3cd7647a19fa6e6a3536665d69cb0e2be68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 1 Oct 2024 13:42:44 +0000 Subject: [PATCH 323/875] leaudio: Fix clearing watchdog Clear watchdog only when group is either in IDLE or CONFIGURED state on the way back from STREAMING. Bug: 369599302 Flag: Exempt, regression tested with unit test, new test added Test: atest bluetooth_le_audio_test Change-Id: Ie3f51ae37e65d189eaabbde452ac666d8cc3a501 --- system/bta/le_audio/state_machine.cc | 4 +- system/bta/le_audio/state_machine_test.cc | 181 ++++++++++++++++++++++ 2 files changed, 183 insertions(+), 2 deletions(-) diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index e3e3b9c481b..48d09a30b12 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -1228,14 +1228,14 @@ public: * In such an event, there is need to notify upper layer about state * from here. */ - cancel_watchdog_if_needed(group->group_id_); - if (current_group_state == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) { + cancel_watchdog_if_needed(group->group_id_); log::info("Cises disconnected for group {}, we are good in Idle state.", group->group_id_); ReleaseCisIds(group); state_machine_callbacks_->StatusReportCb(group->group_id_, GroupStreamStatus::IDLE); } else if (current_group_state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) { + cancel_watchdog_if_needed(group->group_id_); auto reconfig = group->IsPendingConfiguration(); log::info( "Cises disconnected for group: {}, we are good in Configured " diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index ed44a5003fa..84b997b3ff0 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -766,6 +766,15 @@ protected: } } + void InjectCachedConfigurationForGroup(LeAudioDeviceGroup* group) { + auto leAudioDevice = group->GetFirstActiveDevice(); + while (leAudioDevice) { + log::info("Group : {}, dev: {}", group->group_id_, leAudioDevice->address_); + InjectCachedConfigurationForActiveAses(group, leAudioDevice); + leAudioDevice = group->GetNextActiveDevice(leAudioDevice); + } + } + void InjectStreamingStateFroActiveAses(LeAudioDeviceGroup* group, LeAudioDevice* device) { for (auto& ase : device->ases_) { if (!ase.active) { @@ -3806,6 +3815,178 @@ static void InjectCisDisconnected(LeAudioDeviceGroup* group, LeAudioDevice* leAu } } +TEST_F(StateMachineTest, testReleaseMultiple_CisDisconnectedBeforeGettingToIdleState) { + const auto context_type = kContextTypeMedia; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + /* Test Scenario: + * 1. Start stream + * 2. Stop the stream + * 3. While stopping, make sure that CISes are disconnected before current state is IDLE - verify + * watchdog keeps running + * 4. Move to IDLE, make sure watchdog is cleared + */ + + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + + stay_in_releasing_state_ = true; + + auto* leAudioDevice = group->GetFirstDevice(); + auto expected_devices_written = 0; + while (leAudioDevice) { + EXPECT_CALL(gatt_queue, + WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(AtLeast(4)); + expected_devices_written++; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + ASSERT_EQ(expected_devices_written, num_devices); + + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); + EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2); + EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2); + EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1); + + InjectInitialIdleNotification(group); + + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)) + .Times(1); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + reset_mock_function_count_map(); + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + + // Validate GroupStreamStatus + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING)); + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE)); + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)) + .Times(0); + + // Stop the stream + LeAudioGroupStateMachine::Get()->StopStream(group); + + // Watchdog shall not be cancled here. + ASSERT_EQ(0, get_func_call_count("alarm_cancel")); + + InjectReleaseAndIdleStateForAGroup(group, false, true); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); +} + +TEST_F(StateMachineTest, testReleaseMultiple_CisDisconnectedBeforeGettingToConfiguredState) { + const auto context_type = kContextTypeMedia; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + /* Test Scenario: + * 1. Start stream + * 2. Stop the stream + * 3. While stopping, make sure that CISes are disconnected before current state is CONFIGURED - + * verify watchdog keeps running + * 4. Move to CONFIGURED, make sure watchdog is cleared + */ + + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group, 0, true); + PrepareConfigureQosHandler(group, 0, true); + PrepareEnableHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + + stay_in_releasing_state_ = true; + + auto* leAudioDevice = group->GetFirstDevice(); + auto expected_devices_written = 0; + while (leAudioDevice) { + EXPECT_CALL(gatt_queue, + WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(AtLeast(4)); + expected_devices_written++; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + ASSERT_EQ(expected_devices_written, num_devices); + + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); + EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2); + EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2); + EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1); + + InjectInitialIdleNotification(group); + + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)) + .Times(1); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + reset_mock_function_count_map(); + + // Validate GroupStreamStatus + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING)); + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS)); + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)) + .Times(0); + + // Stop the stream + LeAudioGroupStateMachine::Get()->StopStream(group); + + // Watchdog shall not be cancled here. + ASSERT_EQ(0, get_func_call_count("alarm_cancel")); + + InjectCachedConfigurationForGroup(group); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); +} + TEST_F(StateMachineTest, testAutonomousReleaseMultiple) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; -- GitLab From ab969251eaaf26bd573242b5f1a90def4ae9501e Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 30 Sep 2024 18:56:19 +0000 Subject: [PATCH 324/875] supports back 2 back measurement seperate the cs tracker as requester and responder Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 368617974 Test: m com.android.btservices Change-Id: I074da454c7443ca2bb0827c1e680f33460304fc4 --- system/gd/hci/distance_measurement_manager.cc | 481 ++++++++++-------- 1 file changed, 266 insertions(+), 215 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index dc0617be0ae..d21a42947d4 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -69,6 +69,7 @@ static constexpr uint8_t kProcedureDataBufferSize = 0x10; // Buffer size of Pro static constexpr uint16_t kMtuForRasData = 507; // 512 - 5 static constexpr uint16_t kRangingCounterMask = 0x0FFF; static constexpr uint8_t kInvalidConfigId = 0xFF; +static constexpr uint16_t kDefaultIntervalMs = 1000; // 1s struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { struct CsProcedureData { @@ -143,24 +144,25 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { struct CsTracker { Address address; - hci::Role local_hci_role; - uint16_t procedure_counter; - CsRole role; + hci::Role local_hci_role = hci::Role::CENTRAL; + uint16_t procedure_counter = 0; + CsRole role = CsRole::INITIATOR; bool local_start = false; // If the CS was started by the local device. bool measurement_ongoing = false; bool ras_connected = false; bool setup_complete = false; bool config_set = false; - CsMainModeType main_mode_type; - CsSubModeType sub_mode_type; - CsRttType rtt_type; + uint16_t n_procedure_count = 0; + CsMainModeType main_mode_type = CsMainModeType::MODE_2; + CsSubModeType sub_mode_type = CsSubModeType::UNUSED; + CsRttType rtt_type = CsRttType::RTT_AA_ONLY; bool remote_support_phase_based_ranging = false; uint8_t config_id = kInvalidConfigId; uint8_t selected_tx_power = 0; - std::vector procedure_data_list; - uint16_t interval_ms; + std::vector procedure_data_list = {}; + uint16_t interval_ms = kDefaultIntervalMs; bool waiting_for_start_callback = false; - std::unique_ptr repeating_alarm; + std::unique_ptr repeating_alarm = nullptr; // RAS data RangingHeader ranging_header_; PacketViewForRecombination segment_data_; @@ -171,12 +173,12 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { const std::vector& vendor_specific_reply) { log::info("connection_handle:0x{:04x}, vendor_specific_reply size:{}", connection_handle, vendor_specific_reply.size()); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) { log::error("Can't find CS tracker for connection_handle {}", connection_handle); return; } - auto& tracker = cs_trackers_[connection_handle]; + auto& tracker = cs_requester_trackers_[connection_handle]; if (!vendor_specific_reply.empty()) { // Send reply to remote distance_measurement_callbacks_->OnVendorSpecificReply(tracker.address, @@ -189,37 +191,38 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { void OnOpenFailed(uint16_t connection_handle) { log::info("connection_handle:0x{:04x}", connection_handle); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) { log::error("Can't find CS tracker for connection_handle {}", connection_handle); return; } distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - cs_trackers_[connection_handle].address, REASON_INTERNAL_ERROR, METHOD_CS); + cs_requester_trackers_[connection_handle].address, REASON_INTERNAL_ERROR, METHOD_CS); } void OnHandleVendorSpecificReplyComplete(uint16_t connection_handle, bool success) { log::info("connection_handle:0x{:04x}, success:{}", connection_handle, success); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_responder_trackers_.find(connection_handle); + if (it == cs_responder_trackers_.end()) { log::error("Can't find CS tracker for connection_handle {}", connection_handle); return; } - distance_measurement_callbacks_->OnHandleVendorSpecificReplyComplete( - cs_trackers_[connection_handle].address, success); + distance_measurement_callbacks_->OnHandleVendorSpecificReplyComplete(it->second.address, + success); } void OnResult(uint16_t connection_handle, const bluetooth::hal::RangingResult& ranging_result) { - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) { log::warn("Can't find CS tracker for connection_handle {}", connection_handle); return; } - log::debug("address {}, resultMeters {}", cs_trackers_[connection_handle].address, + log::debug("address {}, resultMeters {}", cs_requester_trackers_[connection_handle].address, ranging_result.result_meters_); using namespace std::chrono; long elapsedRealtimeNanos = duration_cast(steady_clock::now().time_since_epoch()).count(); distance_measurement_callbacks_->OnDistanceMeasurementResult( - cs_trackers_[connection_handle].address, ranging_result.result_meters_ * 100, 0.0, -1, - -1, -1, -1, elapsedRealtimeNanos, ranging_result.confidence_level_, + cs_requester_trackers_[connection_handle].address, ranging_result.result_meters_ * 100, + 0.0, -1, -1, -1, -1, elapsedRealtimeNanos, ranging_result.confidence_level_, DistanceMeasurementMethod::METHOD_CS); } @@ -289,33 +292,35 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } break; case METHOD_CS: { - init_cs_tracker(address, connection_handle, local_hci_role, interval); + init_cs_requester_tracker(address, connection_handle, local_hci_role, interval); start_distance_measurement_with_cs(address, connection_handle); } break; } } - void init_cs_tracker(const Address& cs_remote_address, uint16_t connection_handle, - hci::Role local_hci_role, uint16_t interval) { - if (cs_trackers_.find(connection_handle) != cs_trackers_.end() && - cs_trackers_[connection_handle].address != cs_remote_address) { - log::debug("Remove old tracker for {}", cs_remote_address); - cs_trackers_.erase(connection_handle); - } - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { - cs_trackers_[connection_handle].address = cs_remote_address; + void init_cs_requester_tracker(const Address& cs_remote_address, uint16_t connection_handle, + hci::Role local_hci_role, uint16_t interval) { + auto it = cs_requester_trackers_.find(connection_handle); + if (it != cs_requester_trackers_.end()) { + if (it->second.address != cs_remote_address) { + log::debug("replace old tracker as {}", cs_remote_address); + it->second = CsTracker(); + } + } else { + cs_requester_trackers_[connection_handle] = CsTracker(); + it = cs_requester_trackers_.find(connection_handle); } + it->second.address = cs_remote_address; // make sure the repeating_alarm is initialized. - if (cs_trackers_[connection_handle].repeating_alarm == nullptr) { - cs_trackers_[connection_handle].repeating_alarm = - std::make_unique(handler_); - } - cs_trackers_[connection_handle].interval_ms = interval; - cs_trackers_[connection_handle].local_start = true; - cs_trackers_[connection_handle].measurement_ongoing = true; - cs_trackers_[connection_handle].waiting_for_start_callback = true; - cs_trackers_[connection_handle].local_hci_role = local_hci_role; - cs_trackers_[connection_handle].config_id = kConfigId; + if (it->second.repeating_alarm == nullptr) { + it->second.repeating_alarm = std::make_unique(handler_); + } + it->second.interval_ms = interval; + it->second.local_start = true; + it->second.measurement_ongoing = true; + it->second.waiting_for_start_callback = true; + it->second.local_hci_role = local_hci_role; + it->second.config_id = kConfigId; } void start_distance_measurement_with_cs(const Address& cs_remote_address, @@ -328,29 +333,28 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } - if (!cs_trackers_[connection_handle].ras_connected) { + if (!cs_requester_trackers_[connection_handle].ras_connected) { log::info("Waiting for RAS connected"); return; } - if (!cs_trackers_[connection_handle].setup_complete) { + if (!cs_requester_trackers_[connection_handle].setup_complete) { send_le_cs_read_remote_supported_capabilities(connection_handle); return; } - if (!cs_trackers_[connection_handle].config_set) { - // TODO: compare the config set with the requested config. - // The config may be override by reflector. consider to use different tracker for reflector - send_le_cs_create_config(connection_handle, cs_trackers_[connection_handle].config_id); + if (!cs_requester_trackers_[connection_handle].config_set) { + send_le_cs_create_config(connection_handle, + cs_requester_trackers_[connection_handle].config_id); return; } log::info("enable cs procedure regularly with interval: {} ms", - cs_trackers_[connection_handle].interval_ms); - cs_trackers_[connection_handle].repeating_alarm->Cancel(); + cs_requester_trackers_[connection_handle].interval_ms); + cs_requester_trackers_[connection_handle].repeating_alarm->Cancel(); send_le_cs_procedure_enable(connection_handle, Enable::ENABLED); - cs_trackers_[connection_handle].repeating_alarm->Schedule( + cs_requester_trackers_[connection_handle].repeating_alarm->Schedule( common::Bind(&impl::send_le_cs_procedure_enable, common::Unretained(this), connection_handle, Enable::ENABLED), - std::chrono::milliseconds(cs_trackers_[connection_handle].interval_ms)); + std::chrono::milliseconds(cs_requester_trackers_[connection_handle].interval_ms)); } void stop_distance_measurement(const Address address, uint16_t connection_handle, @@ -359,24 +363,26 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { switch (method) { case METHOD_AUTO: case METHOD_RSSI: { - if (rssi_trackers.find(address) == rssi_trackers.end()) { + auto it = rssi_trackers.find(address); + if (it == rssi_trackers.end()) { log::warn("Can't find rssi tracker for {}", address); } else { hci_layer_->EnqueueCommand( - LeSetTransmitPowerReportingEnableBuilder::Create(rssi_trackers[address].handle, - 0x00, 0x00), + LeSetTransmitPowerReportingEnableBuilder::Create(it->second.handle, 0x00, 0x00), handler_->BindOnce( check_complete)); - rssi_trackers[address].repeating_alarm->Cancel(); - rssi_trackers[address].repeating_alarm.reset(); + it->second.repeating_alarm->Cancel(); + it->second.repeating_alarm.reset(); rssi_trackers.erase(address); } } break; case METHOD_CS: { - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_requester_trackers_.find(connection_handle); + if (it == cs_requester_trackers_.end()) { log::warn("Can't find CS tracker for {}", address); - } else if (cs_trackers_[connection_handle].measurement_ongoing) { - cs_trackers_[connection_handle].repeating_alarm->Cancel(); + } else if (it->second.measurement_ongoing) { + it->second.repeating_alarm->Cancel(); + reset_tracker_on_stopped(it->second); send_le_cs_procedure_enable(connection_handle, Enable::DISABLED); } } break; @@ -391,27 +397,27 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { "vendor_specific_data {}", address, connection_handle, att_handle, vendor_specific_data.size()); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_requester_trackers_.find(connection_handle); + if (it == cs_requester_trackers_.end()) { log::warn("can't find tracker for 0x{:04x}", connection_handle); return; } - auto& tracker = cs_trackers_[connection_handle]; - if (tracker.ras_connected) { + if (it->second.ras_connected) { log::debug("Already connected"); return; } - tracker.ras_connected = true; + it->second.ras_connected = true; if (ranging_hal_->IsBound()) { ranging_hal_->OpenSession(connection_handle, att_handle, vendor_specific_data); return; } - start_distance_measurement_with_cs(tracker.address, connection_handle); + start_distance_measurement_with_cs(it->second.address, connection_handle); } void handle_ras_client_disconnected_event(const Address address) { log::info("address:{}", address); - for (auto it = cs_trackers_.begin(); it != cs_trackers_.end();) { + for (auto it = cs_requester_trackers_.begin(); it != cs_requester_trackers_.end();) { if (it->second.address == address) { if (it->second.repeating_alarm != nullptr) { it->second.repeating_alarm->Cancel(); @@ -419,7 +425,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } distance_measurement_callbacks_->OnDistanceMeasurementStopped( address, REASON_NO_LE_CONNECTION, METHOD_CS); - it = cs_trackers_.erase(it); // erase and get the next iterator + it = cs_requester_trackers_.erase(it); // erase and get the next iterator } else { ++it; } @@ -429,13 +435,13 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { void handle_ras_server_vendor_specific_reply( const Address& address, uint16_t connection_handle, const std::vector vendor_specific_reply) { - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_responder_trackers_.find(connection_handle); + if (it == cs_responder_trackers_.end()) { log::info("no cs tracker found for {}", connection_handle); return; } - if (cs_trackers_[connection_handle].address != address) { - log::info("the cs tracker address was changed as {}, not {}.", - cs_trackers_[connection_handle].address, address); + if (it->second.address != address) { + log::info("the cs tracker address was changed as {}, not {}.", it->second.address, address); return; } if (ranging_hal_->IsBound()) { @@ -446,46 +452,45 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { void handle_ras_server_connected(const Address& identity_address, uint16_t connection_handle, hci::Role local_hci_role) { - log::info("initialize the cs tracker for {}", connection_handle); + log::info("initialize the responder tracker for {} with {}", connection_handle, + identity_address); // create CS tracker to serve the ras_server - if (cs_trackers_.find(connection_handle) != cs_trackers_.end()) { - if (cs_trackers_[connection_handle].local_start && - cs_trackers_[connection_handle].measurement_ongoing) { - log::info("cs tracker for {} is being used for measurement.", identity_address); - return; + auto it = cs_responder_trackers_.find(connection_handle); + if (it != cs_responder_trackers_.end()) { + if (it->second.address != identity_address) { + log::debug("Remove old tracker for {}", identity_address); + it->second = CsTracker(); } + } else { + cs_responder_trackers_[connection_handle] = CsTracker(); + it = cs_responder_trackers_.find(connection_handle); } - if (cs_trackers_[connection_handle].address != identity_address) { - log::debug("Remove old tracker for {}", identity_address); - cs_trackers_.erase(connection_handle); - } - - cs_trackers_[connection_handle].address = identity_address; - cs_trackers_[connection_handle].local_start = false; - cs_trackers_[connection_handle].local_hci_role = local_hci_role; + it->second.address = identity_address; + it->second.local_start = false; + it->second.local_hci_role = local_hci_role; } void handle_ras_server_disconnected(const Address& identity_address, uint16_t connection_handle) { - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_responder_trackers_.find(connection_handle); + if (it == cs_responder_trackers_.end()) { log::info("no CS tracker available."); return; } - if (cs_trackers_[connection_handle].address != identity_address) { + if (it->second.address != identity_address) { log::info("cs tracker connection is associated with device {}, not device {}", - cs_trackers_[connection_handle].address, identity_address); + it->second.address, identity_address); return; } - if (!cs_trackers_[connection_handle].local_start) { - log::info("erase cs tracker for {}, as ras server is disconnected.", connection_handle); - cs_trackers_.erase(connection_handle); - } + + cs_responder_trackers_.erase(connection_handle); } void handle_vendor_specific_reply_complete(const Address address, uint16_t connection_handle, bool success) { log::info("address:{}, connection_handle:0x{:04x}, success:{}", address, connection_handle, success); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_requester_trackers_.find(connection_handle); + if (it == cs_requester_trackers_.end()) { log::warn("can't find tracker for 0x{:04x}", connection_handle); distance_measurement_callbacks_->OnDistanceMeasurementStartFail( address, REASON_INTERNAL_ERROR, METHOD_CS); @@ -498,8 +503,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } - auto& tracker = cs_trackers_[connection_handle]; - start_distance_measurement_with_cs(tracker.address, connection_handle); + start_distance_measurement_with_cs(it->second.address, connection_handle); } void send_read_rssi(const Address& address, uint16_t connection_handle) { @@ -603,18 +607,18 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handler_->BindOnceOn(this, &impl::on_cs_set_procedure_parameters)); } - static void reset_tracker_on_stopped(CsTracker* cs_tracker) { - cs_tracker->local_start = false; - cs_tracker->measurement_ongoing = false; + static void reset_tracker_on_stopped(CsTracker& cs_tracker) { + cs_tracker.measurement_ongoing = false; } void handle_cs_setup_failure(uint16_t connection_handle, DistanceMeasurementErrorCode errorCode) { - auto it = cs_trackers_.find(connection_handle); - if (it == cs_trackers_.end()) { - log::debug("no cs tracker is found for connection - {}", connection_handle); + // responder is stateless. only requester needs to handle the set up failure. + auto it = cs_requester_trackers_.find(connection_handle); + if (it == cs_requester_trackers_.end()) { + log::info("no requester tracker is found for {}.", connection_handle); return; } - if (it->second.local_start) { + if (it->second.measurement_ongoing) { if (it->second.waiting_for_start_callback) { distance_measurement_callbacks_->OnDistanceMeasurementStartFail(it->second.address, errorCode, METHOD_CS); @@ -625,28 +629,28 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { it->second.repeating_alarm->Cancel(); it->second.repeating_alarm.reset(); } - reset_tracker_on_stopped(&(it->second)); + reset_tracker_on_stopped(it->second); // the cs_tracker should be kept until the connection is disconnected } void send_le_cs_procedure_enable(uint16_t connection_handle, Enable enable) { log::debug("cmd {}", enable); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_requester_trackers_.find(connection_handle); + if (it == cs_requester_trackers_.end()) { log::warn("Can't find cs tracker for connection {}", connection_handle); return; } - if (!cs_trackers_[connection_handle].measurement_ongoing) { + if (!it->second.measurement_ongoing) { log::error("safe guard, error state, no local measurement request."); - if (cs_trackers_[connection_handle].repeating_alarm) { - cs_trackers_[connection_handle].repeating_alarm->Cancel(); + if (it->second.repeating_alarm) { + it->second.repeating_alarm->Cancel(); } return; } hci_layer_->EnqueueCommand( - LeCsProcedureEnableBuilder::Create(connection_handle, - cs_trackers_[connection_handle].config_id, enable), + LeCsProcedureEnableBuilder::Create(connection_handle, it->second.config_id, enable), handler_->BindOnceOn(this, &impl::on_cs_procedure_enable_command_status_cb, connection_handle, enable)); } @@ -657,8 +661,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { // controller may send error if the procedure instance has finished all scheduled procedures. if (enable == Enable::DISABLED && status == ErrorCode::COMMAND_DISALLOWED) { log::info("ignored the procedure disable command disallow error."); - if (cs_trackers_.find(connection_handle) != cs_trackers_.end()) { - reset_tracker_on_stopped(&cs_trackers_[connection_handle]); + if (cs_requester_trackers_.find(connection_handle) != cs_requester_trackers_.end()) { + reset_tracker_on_stopped(cs_requester_trackers_[connection_handle]); } } else { on_cs_setup_command_status_cb(connection_handle, status_view); @@ -703,15 +707,22 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); return; } - send_le_cs_set_default_settings(event_view.GetConnectionHandle()); - if (cs_trackers_.find(connection_handle) != cs_trackers_.end() && - cs_trackers_[connection_handle].local_hci_role == hci::Role::CENTRAL) { - // send the cmd from the BLE central only. - send_le_cs_security_enable(connection_handle); + auto res_it = cs_responder_trackers_.find(connection_handle); + if (res_it != cs_responder_trackers_.end()) { + res_it->second.remote_support_phase_based_ranging = + event_view.GetOptionalSubfeaturesSupported().phase_based_ranging_ == 0x01; } + send_le_cs_set_default_settings(connection_handle); - if (event_view.GetOptionalSubfeaturesSupported().phase_based_ranging_ == 0x01) { - cs_trackers_[connection_handle].remote_support_phase_based_ranging = true; + auto req_it = cs_requester_trackers_.find(connection_handle); + if (req_it != cs_requester_trackers_.end() && req_it->second.measurement_ongoing) { + req_it->second.remote_support_phase_based_ranging = + event_view.GetOptionalSubfeaturesSupported().phase_based_ranging_ == 0x01; + req_it->second.setup_complete = true; + log::info("Setup phase complete, connection_handle: {}, address: {}", connection_handle, + cs_requester_trackers_[connection_handle].address); + send_le_cs_create_config(connection_handle, + cs_requester_trackers_[connection_handle].config_id); } log::info( "connection_handle:{}, num_antennas_supported:{}, max_antenna_paths_supported:{}, " @@ -748,15 +759,11 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); return; } - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { - log::warn("Can't find cs tracker for connection_handle {}", connection_handle); - return; - } - if (cs_trackers_[connection_handle].local_start) { - cs_trackers_[connection_handle].setup_complete = true; - log::info("Setup phase complete, connection_handle: {}, address: {}", connection_handle, - cs_trackers_[connection_handle].address); - send_le_cs_create_config(connection_handle, cs_trackers_[connection_handle].config_id); + auto it = cs_requester_trackers_.find(connection_handle); + if (it != cs_requester_trackers_.end() && it->second.measurement_ongoing && + !it->second.config_set) { + it->second.config_set = true; + send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), it->second.config_id); } } @@ -772,23 +779,25 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); return; } - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + uint8_t config_id = event_view.GetConfigId(); + CsTracker* live_tracker = get_live_tracker(connection_handle, config_id); + if (live_tracker == nullptr) { log::warn("Can't find cs tracker for connection_handle {}", connection_handle); return; } + // assign the config_id, as this may be the 1st time to get the config_id from responder. + live_tracker->config_id = config_id; if (event_view.GetAction() == CsAction::CONFIG_REMOVED) { return; } log::info("Get {}", event_view.ToString()); - cs_trackers_[connection_handle].role = event_view.GetRole(); - cs_trackers_[connection_handle].main_mode_type = event_view.GetMainModeType(); - cs_trackers_[connection_handle].sub_mode_type = event_view.GetSubModeType(); - cs_trackers_[connection_handle].rtt_type = event_view.GetRttType(); - - if (cs_trackers_[connection_handle].local_start) { - cs_trackers_[connection_handle].config_set = true; - send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), - cs_trackers_[connection_handle].config_id); + live_tracker->role = event_view.GetRole(); + live_tracker->main_mode_type = event_view.GetMainModeType(); + live_tracker->sub_mode_type = event_view.GetSubModeType(); + live_tracker->rtt_type = event_view.GetRttType(); + if (live_tracker->local_hci_role == hci::Role::CENTRAL) { + // send the cmd from the BLE central only. + send_le_cs_security_enable(connection_handle); } } @@ -805,22 +814,39 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); return; } - - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + auto it = cs_requester_trackers_.find(connection_handle); + if (it == cs_requester_trackers_.end()) { log::warn("Can't find cs tracker for connection_handle {}", connection_handle); return; } - if (cs_trackers_[connection_handle].local_start) { - log::info("enable cs procedure regularly with interval: {} ms", - cs_trackers_[connection_handle].interval_ms); - cs_trackers_[connection_handle].repeating_alarm->Cancel(); + if (it->second.measurement_ongoing) { + log::info("enable cs procedure regularly with interval: {} ms", it->second.interval_ms); + it->second.repeating_alarm->Cancel(); send_le_cs_procedure_enable(connection_handle, Enable::ENABLED); - cs_trackers_[connection_handle].repeating_alarm->Schedule( + it->second.repeating_alarm->Schedule( common::Bind(&impl::send_le_cs_procedure_enable, common::Unretained(this), connection_handle, Enable::ENABLED), - std::chrono::milliseconds(cs_trackers_[connection_handle].interval_ms)); + std::chrono::milliseconds(it->second.interval_ms)); + } + } + + CsTracker* get_live_tracker(uint16_t connection_handle, uint8_t config_id) { + // suppose the config_id is unique, otherwise, no way to know if the event from controller + // is from local(requester) or remote(responder). + // CAVEAT: if the remote is sending request with the same config id, the behavior is undefined. + auto it = cs_requester_trackers_.find(connection_handle); + if (it != cs_requester_trackers_.end() && it->second.measurement_ongoing && + it->second.config_id == config_id) { + return &(it->second); } + // take it as responder any way + if (cs_responder_trackers_.find(connection_handle) != cs_responder_trackers_.end()) { + return &cs_responder_trackers_[connection_handle]; + } + + log::error("no event is expected as no any live cs tracker for {}", connection_handle); + return nullptr; } void on_cs_procedure_enable_complete(LeCsProcedureEnableCompleteView event_view) { @@ -833,23 +859,40 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); return; } - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + uint8_t config_id = event_view.GetConfigId(); + CsTracker* live_tracker = get_live_tracker(connection_handle, config_id); + if (live_tracker == nullptr) { + log::error("no tracker is available for {}", connection_handle); return; } if (event_view.GetState() == Enable::ENABLED) { log::debug("Procedure enabled, {}", event_view.ToString()); - cs_trackers_[connection_handle].config_id = event_view.GetConfigId(); - cs_trackers_[connection_handle].selected_tx_power = event_view.GetSelectedTxPower(); - - if (cs_trackers_[connection_handle].waiting_for_start_callback) { - cs_trackers_[connection_handle].waiting_for_start_callback = false; - distance_measurement_callbacks_->OnDistanceMeasurementStarted( - cs_trackers_[connection_handle].address, METHOD_CS); + // assign the config_id, as this is may be the 1st time to get it for responder; + live_tracker->config_id = config_id; + live_tracker->selected_tx_power = event_view.GetSelectedTxPower(); + live_tracker->n_procedure_count = event_view.GetProcedureCount(); + + 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); + } + // cs role switch from requester to responder, may reset the config if conflict. + if (!live_tracker->local_start && + cs_requester_trackers_.find(connection_handle) != cs_requester_trackers_.end() && + cs_requester_trackers_[connection_handle].config_id == live_tracker->config_id) { + log::debug("config id {} from remote is the same as the cached local, reset config_set.", + cs_requester_trackers_[connection_handle].config_id); + cs_requester_trackers_[connection_handle].config_set = false; } } else if (event_view.GetState() == Enable::DISABLED) { - reset_tracker_on_stopped(&cs_trackers_[connection_handle]); + reset_tracker_on_stopped(*live_tracker); + } + // reset the procedure data list. + std::vector& data_list = live_tracker->procedure_data_list; + while (!data_list.empty()) { + data_list.erase(data_list.begin()); } - cs_delete_obsolete_data(connection_handle); } void on_cs_subevent(LeMetaEventView event) { @@ -865,6 +908,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { ProcedureAbortReason procedure_abort_reason; SubeventAbortReason subevent_abort_reason; std::vector result_data_structures; + CsTracker* live_tracker = nullptr; if (event.GetSubeventCode() == SubeventCode::LE_CS_SUBEVENT_RESULT) { auto cs_event_result = LeCsSubeventResultView::Create(event); if (!cs_event_result.IsValid()) { @@ -872,19 +916,21 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } connection_handle = cs_event_result.GetConnectionHandle(); + live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId()); + if (live_tracker == nullptr) { + log::error("no live tracker is available for {}", connection_handle); + return; + } procedure_done_status = cs_event_result.GetProcedureDoneStatus(); subevent_done_status = cs_event_result.GetSubeventDoneStatus(); procedure_abort_reason = cs_event_result.GetProcedureAbortReason(); subevent_abort_reason = cs_event_result.GetSubeventAbortReason(); result_data_structures = cs_event_result.GetResultDataStructures(); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { - log::warn("Can't find any tracker for {}", connection_handle); - return; - } + CsProcedureData* procedure_data = - init_cs_procedure_data(connection_handle, cs_event_result.GetProcedureCounter(), + init_cs_procedure_data(live_tracker, cs_event_result.GetProcedureCounter(), cs_event_result.GetNumAntennaPaths()); - if (cs_trackers_[connection_handle].role == CsRole::INITIATOR) { + if (live_tracker->role == CsRole::INITIATOR) { procedure_data->frequency_compensation.push_back( cs_event_result.GetFrequencyCompensation()); } @@ -902,18 +948,19 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } connection_handle = cs_event_result.GetConnectionHandle(); + live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId()); procedure_done_status = cs_event_result.GetProcedureDoneStatus(); subevent_done_status = cs_event_result.GetSubeventDoneStatus(); procedure_abort_reason = cs_event_result.GetProcedureAbortReason(); subevent_abort_reason = cs_event_result.GetSubeventAbortReason(); result_data_structures = cs_event_result.GetResultDataStructures(); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + if (live_tracker == nullptr) { log::warn("Can't find any tracker for {}", connection_handle); return; } } - uint16_t counter = cs_trackers_[connection_handle].procedure_counter; + uint16_t counter = live_tracker->procedure_counter; log::debug( "Connection_handle {}, procedure_done_status: {}, subevent_done_status: {}, counter: " "{}", @@ -929,8 +976,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { SubeventAbortReasonText(subevent_abort_reason), connection_handle, counter); } - CsProcedureData* procedure_data = get_procedure_data(connection_handle, counter); + CsProcedureData* procedure_data = get_procedure_data(live_tracker, counter); if (procedure_data == nullptr) { + log::warn("no procedure data for counter {} of connection {}", counter, connection_handle); return; } procedure_data->ras_subevent_header_.num_steps_reported_ += result_data_structures.size(); @@ -945,13 +993,12 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { procedure_data->ras_subevent_header_.subevent_abort_reason_ = static_cast(subevent_abort_reason); } - parse_cs_result_data(result_data_structures, *procedure_data, - cs_trackers_[connection_handle].role); + parse_cs_result_data(result_data_structures, *procedure_data, live_tracker->role); // Update procedure status procedure_data->local_status = procedure_done_status; - check_cs_procedure_complete(procedure_data, connection_handle); + check_cs_procedure_complete(live_tracker, procedure_data, connection_handle); - if (cs_trackers_[connection_handle].local_start) { + if (live_tracker->local_start) { // Skip to send remote return; } @@ -968,7 +1015,11 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { append_vector(procedure_data->ras_raw_data_, subevent_raw); // erase buffer procedure_data->ras_subevent_data_.clear(); - send_on_demand_data(cs_trackers_[connection_handle].address, procedure_data); + send_on_demand_data(live_tracker->address, procedure_data); + // remove procedure data sent previously + if (procedure_done_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE) { + delete_consumed_procedure_data(live_tracker, live_tracker->procedure_counter); + } } } @@ -1016,11 +1067,11 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::debug("address:{}, connection_handle 0x{:04x}, size:{}", address.ToString(), connection_handle, raw_data.size()); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) { log::warn("can't find tracker for 0x{:04x}", connection_handle); return; } - auto& tracker = cs_trackers_[connection_handle]; + auto& tracker = cs_requester_trackers_[connection_handle]; SegmentationHeader segmentation_header; PacketView packet_bytes_view(std::make_shared>(raw_data)); @@ -1063,18 +1114,18 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { void handle_remote_data_timeout(const Address address, uint16_t connection_handle) { log::warn("address:{}, connection_handle 0x{:04x}", address.ToString(), connection_handle); - if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) { + if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) { log::error("Can't find CS tracker for connection_handle {}", connection_handle); return; } - auto& tracker = cs_trackers_[connection_handle]; + auto& tracker = cs_requester_trackers_[connection_handle]; if (tracker.measurement_ongoing && tracker.local_start) { - cs_trackers_[connection_handle].repeating_alarm->Cancel(); + cs_requester_trackers_[connection_handle].repeating_alarm->Cancel(); send_le_cs_procedure_enable(connection_handle, Enable::DISABLED); distance_measurement_callbacks_->OnDistanceMeasurementStopped( tracker.address, REASON_INTERNAL_ERROR, METHOD_CS); } - reset_tracker_on_stopped(&tracker); + reset_tracker_on_stopped(tracker); } void parse_ras_segments(RangingHeader ranging_header, PacketViewForRecombination& segment_data, @@ -1094,8 +1145,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } // Get role of the remote device - CsRole role = cs_trackers_[connection_handle].role == CsRole::INITIATOR ? CsRole::REFLECTOR - : CsRole::INITIATOR; + CsRole remote_role = cs_requester_trackers_[connection_handle].role == CsRole::INITIATOR + ? CsRole::REFLECTOR + : CsRole::INITIATOR; auto parse_index = segment_data.begin(); uint16_t remaining_data_size = std::distance(parse_index, segment_data.end()); @@ -1128,12 +1180,12 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { switch (step_mode.mode_type_) { case 0: { - if (role == CsRole::INITIATOR) { + if (remote_role == CsRole::INITIATOR) { LeCsMode0InitatorData tone_data; after = LeCsMode0InitatorData::Parse(&tone_data, parse_index); if (after == parse_index) { log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, - CsRoleText(role)); + CsRoleText(remote_role)); return; } parse_index = after; @@ -1142,7 +1194,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { after = LeCsMode0ReflectorData::Parse(&tone_data, parse_index); if (after == parse_index) { log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, - CsRoleText(role)); + CsRoleText(remote_role)); return; } } @@ -1171,7 +1223,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { after = LeCsMode2Data::Parse(&tone_data, packet_bytes_view.begin()); if (after == packet_bytes_view.begin()) { log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, - CsRoleText(role)); + CsRoleText(remote_role)); return; } parse_index += data_len; @@ -1188,7 +1240,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { uint8_t tone_quality_indicator = tone_data.tone_data_[k].tone_quality_indicator_; log::verbose("antenna_path {}, {:f}, {:f}", (uint16_t)(antenna_path + 1), i_value, q_value); - if (role == CsRole::INITIATOR) { + if (remote_role == CsRole::INITIATOR) { procedure_data->tone_pct_initiator[antenna_path].emplace_back(i_value, q_value); procedure_data->tone_quality_indicator_initiator[antenna_path].emplace_back( tone_quality_indicator); @@ -1208,25 +1260,26 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::debug("Parse subevent done with remaining data size {}", remaining_data_size); procedure_data->remote_status = (CsProcedureDoneStatus)subevent_header.ranging_done_status_; } - check_cs_procedure_complete(procedure_data, connection_handle); + check_cs_procedure_complete(&cs_requester_trackers_[connection_handle], procedure_data, + connection_handle); } - CsProcedureData* init_cs_procedure_data(uint16_t connection_handle, uint16_t procedure_counter, + CsProcedureData* init_cs_procedure_data(CsTracker* live_tracker, uint16_t procedure_counter, uint8_t num_antenna_paths) { // Update procedure count - cs_trackers_[connection_handle].procedure_counter = procedure_counter; + live_tracker->procedure_counter = procedure_counter; - std::vector& data_list = cs_trackers_[connection_handle].procedure_data_list; + std::vector& data_list = live_tracker->procedure_data_list; for (auto& data : data_list) { if (data.counter == procedure_counter) { // Data already exists, return + log::warn("duplicated procedure counter - {}.", procedure_counter); return &data; } } log::info("Create data for procedure_counter: {}", procedure_counter); - data_list.emplace_back(procedure_counter, num_antenna_paths, - cs_trackers_[connection_handle].config_id, - cs_trackers_[connection_handle].selected_tx_power); + data_list.emplace_back(procedure_counter, num_antenna_paths, live_tracker->config_id, + live_tracker->selected_tx_power); // Append ranging header raw data std::vector ranging_header_raw = {}; @@ -1241,15 +1294,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return &data_list.back(); } - void cs_delete_obsolete_data(uint16_t connection_handle) { - std::vector& data_list = cs_trackers_[connection_handle].procedure_data_list; - while (!data_list.empty()) { - data_list.erase(data_list.begin()); - } - } - - CsProcedureData* get_procedure_data(uint16_t connection_handle, uint16_t counter) { - std::vector& data_list = cs_trackers_[connection_handle].procedure_data_list; + CsProcedureData* get_procedure_data(CsTracker* live_tracker, uint16_t counter) { + std::vector& data_list = live_tracker->procedure_data_list; CsProcedureData* procedure_data = nullptr; for (uint8_t i = 0; i < data_list.size(); i++) { if (data_list[i].counter == counter) { @@ -1258,19 +1304,19 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } if (procedure_data == nullptr) { - log::warn("Can't find data for connection_handle:{}, counter: {}", connection_handle, - counter); + log::warn("Can't find data for counter: {}", counter); } return procedure_data; } CsProcedureData* get_procedure_data_for_ras(uint16_t connection_handle, uint16_t ranging_counter) { - std::vector& data_list = cs_trackers_[connection_handle].procedure_data_list; + std::vector& data_list = + cs_requester_trackers_[connection_handle].procedure_data_list; CsProcedureData* procedure_data = nullptr; - for (uint8_t i = 0; i < data_list.size(); i++) { - if ((data_list[i].counter & kRangingCounterMask) == ranging_counter) { - procedure_data = &data_list[i]; + for (auto& i : data_list) { + if ((i.counter & kRangingCounterMask) == ranging_counter) { + procedure_data = &i; break; } } @@ -1281,14 +1327,15 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return procedure_data; } - void check_cs_procedure_complete(CsProcedureData* procedure_data, uint16_t connection_handle) { - if (procedure_data->local_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE && + void check_cs_procedure_complete(CsTracker* live_tracker, CsProcedureData* procedure_data, + uint16_t connection_handle) const { + if (live_tracker->local_start && + procedure_data->local_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE && procedure_data->remote_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE && !procedure_data->aborted) { log::debug("Procedure complete counter:{} data size:{}, main_mode_type:{}, sub_mode_type:{}", (uint16_t)procedure_data->counter, (uint16_t)procedure_data->step_channel.size(), - (uint16_t)cs_trackers_[connection_handle].main_mode_type, - (uint16_t)cs_trackers_[connection_handle].sub_mode_type); + (uint16_t)live_tracker->main_mode_type, (uint16_t)live_tracker->sub_mode_type); if (ranging_hal_->IsBound()) { // Use algorithm in the HAL @@ -1309,20 +1356,23 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { // If the procedure is completed or aborted, delete all previous data if (procedure_data->local_status != CsProcedureDoneStatus::PARTIAL_RESULTS && procedure_data->remote_status != CsProcedureDoneStatus::PARTIAL_RESULTS) { - std::vector& data_list = cs_trackers_[connection_handle].procedure_data_list; - uint16_t counter = procedure_data->counter; // Get value from pointer first. - while (data_list.begin()->counter < counter) { - log::debug("Delete obsolete procedure data, counter:{}", data_list.begin()->counter); - data_list.erase(data_list.begin()); - } + delete_consumed_procedure_data(live_tracker, procedure_data->counter); + } + } + + static void delete_consumed_procedure_data(CsTracker* live_tracker, uint16_t current_counter) { + std::vector& data_list = live_tracker->procedure_data_list; + while (data_list.begin()->counter < current_counter) { + log::debug("Delete obsolete procedure data, counter:{}", data_list.begin()->counter); + data_list.erase(data_list.begin()); } } - void parse_cs_result_data(std::vector result_data_structures, + void parse_cs_result_data(const std::vector& result_data_structures, CsProcedureData& procedure_data, CsRole role) { uint8_t num_antenna_paths = procedure_data.num_antenna_paths; auto& ras_data = procedure_data.ras_subevent_data_; - for (auto result_data_structure : result_data_structures) { + for (auto& result_data_structure : result_data_structures) { uint16_t mode = result_data_structure.step_mode_; uint16_t step_channel = result_data_structure.step_channel_; uint16_t data_length = result_data_structure.step_data_.size(); @@ -1591,7 +1641,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { hci::AclManager* acl_manager_; hci::DistanceMeasurementInterface* distance_measurement_interface_; std::unordered_map rssi_trackers; - std::unordered_map cs_trackers_; + std::unordered_map cs_requester_trackers_; + std::unordered_map cs_responder_trackers_; DistanceMeasurementCallbacks* distance_measurement_callbacks_; CsOptionalSubfeaturesSupported cs_subfeature_supported_; // Antenna path permutations. See Channel Sounding CR_PR for the details. -- GitLab From aaa616069fbeab9835f302b6bb8e9fac59478b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 15 Oct 2024 10:50:11 +0000 Subject: [PATCH 325/875] has_client.cc: fix single device disconnection Before BTA_GATTC_Close is called, DoDisconnectCleanUp() and devices_.erase() shall be called, preventing second call of disconnect from GATT. Bug: 370405555 Bug: 361014973 Test: atest --host --no-bazel-mode HasClientTest Flag: com.android.bluetooth.flags.hap_connect_only_requested_device Change-Id: Id1c1944b0ea15a6c0caa10be38092997c98f1cb9 --- system/bta/has/has_client.cc | 4 ++++ system/bta/has/has_client_test.cc | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 034bbf43e57..6992211a4f0 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -224,6 +224,10 @@ public: std::find_if(devices_.begin(), devices_.end(), HasDevice::MatchAddress(address)); auto conn_id = device->conn_id; auto is_connecting_actively = device->is_connecting_actively; + + DoDisconnectCleanUp(*device); + devices_.erase(device); + if (conn_id != GATT_INVALID_CONN_ID) { BTA_GATTC_Close(conn_id); callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address); diff --git a/system/bta/has/has_client_test.cc b/system/bta/has/has_client_test.cc index 9be5c92a695..6ca1067116a 100644 --- a/system/bta/has/has_client_test.cc +++ b/system/bta/has/has_client_test.cc @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -622,6 +624,7 @@ protected: } void SetUp(void) override { + __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); reset_mock_function_count_map(); bluetooth::manager::SetMockBtmInterface(&btm_interface); bluetooth::storage::SetMockBtifStorageInterface(&btif_storage_interface_); @@ -1129,6 +1132,7 @@ class HasClientTest : public HasClientTestBase { TestAppRegister(); } void TearDown(void) override { + com::android::bluetooth::flags::provider_->reset_flags(); TestAppUnregister(); HasClientTestBase::TearDown(); } @@ -1213,7 +1217,24 @@ TEST_F(HasClientTest, test_has_connected) { TestConnect(test_address); } +TEST_F(HasClientTest, test_disconnect_connected_without_hap_connect_only_requested_device_flag) { + /* TODO: this test shall be removed b/370405555 */ + com::android::bluetooth::flags::provider_->hap_connect_only_requested_device(false); + const RawAddress test_address = GetTestAddress(1); + /* Minimal possible HA device (only feature flags) */ + SetSampleDatabaseHasNoPresetChange(test_address, + bluetooth::has::kFeatureBitHearingAidTypeBinaural); + + EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(1); + TestConnect(test_address); + + EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1); + EXPECT_CALL(gatt_queue, Clean(1)).Times(1); + TestDisconnect(test_address, 1); +} + TEST_F(HasClientTest, test_disconnect_connected) { + com::android::bluetooth::flags::provider_->hap_connect_only_requested_device(true); const RawAddress test_address = GetTestAddress(1); /* Minimal possible HA device (only feature flags) */ SetSampleDatabaseHasNoPresetChange(test_address, -- GitLab From 0d60b024d6874ce028c43a953f5b53bc47b87e1f Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Tue, 15 Oct 2024 18:02:52 +0000 Subject: [PATCH 326/875] floss: Add on_device_connection_failed callback Add a callback to immediately notify the browser that a pending connection attempt failed. Uprev btmanagerd version to 0.7.1, this is backward compatible API change. Bug: 353527430 Test: mmm packages/modules/Bluetooth Flag: EXEMPT, Floss only change Change-Id: I27cc51c76731c8d9113ad5bf025a14bec48d27ca --- system/gd/rust/linux/client/src/callbacks.rs | 8 ++++++++ system/gd/rust/linux/client/src/dbus_iface.rs | 3 +++ system/gd/rust/linux/mgmt/Cargo.toml | 2 +- system/gd/rust/linux/service/src/iface_bluetooth.rs | 8 ++++++++ system/gd/rust/linux/stack/src/bluetooth.rs | 9 +++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/system/gd/rust/linux/client/src/callbacks.rs b/system/gd/rust/linux/client/src/callbacks.rs index ea117b1e38d..0d1d998b7df 100644 --- a/system/gd/rust/linux/client/src/callbacks.rs +++ b/system/gd/rust/linux/client/src/callbacks.rs @@ -377,6 +377,14 @@ impl IBluetoothConnectionCallback for BtConnectionCallback { remote_device.name ); } + + fn on_device_connection_failed(&mut self, remote_device: BluetoothDevice, status: BtStatus) { + print_info!( + "Connection to [{}] failed, status = {:?}", + remote_device.address.to_string(), + status + ); + } } impl RPCProxy for BtConnectionCallback { diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index c1368aeff2d..6209ee58c45 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -677,6 +677,9 @@ impl IBluetoothConnectionCallback for IBluetoothConnectionCallbackDBus { #[dbus_method("OnDeviceDisconnected", DBusLog::Disable)] fn on_device_disconnected(&mut self, remote_device: BluetoothDevice) {} + + #[dbus_method("OnDeviceConnectionFailed", DBusLog::Disable)] + fn on_device_connection_failed(&mut self, remote_device: BluetoothDevice, status: BtStatus) {} } #[allow(dead_code)] diff --git a/system/gd/rust/linux/mgmt/Cargo.toml b/system/gd/rust/linux/mgmt/Cargo.toml index b6dbfc30cc8..66c239a4af0 100644 --- a/system/gd/rust/linux/mgmt/Cargo.toml +++ b/system/gd/rust/linux/mgmt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "manager_service" -version = "0.7.0" +version = "0.7.1" edition = "2018" build = "build.rs" diff --git a/system/gd/rust/linux/service/src/iface_bluetooth.rs b/system/gd/rust/linux/service/src/iface_bluetooth.rs index 3de32bbbb5e..ae379d7353f 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth.rs @@ -196,6 +196,14 @@ impl IBluetoothConnectionCallback for BluetoothConnectionCallbackDBus { fn on_device_disconnected(&mut self, remote_device: BluetoothDevice) { dbus_generated!() } + + #[dbus_method( + "OnDeviceConnectionFailed", + DBusLog::Enable(DBusLogOptions::LogAll, DBusLogVerbosity::Verbose) + )] + fn on_device_connection_failed(&mut self, remote_device: BluetoothDevice, status: BtStatus) { + dbus_generated!() + } } impl_dbus_arg_enum!(BtSdpType); diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index b93f70c64ef..57b12c63af4 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -574,6 +574,9 @@ pub trait IBluetoothConnectionCallback: RPCProxy { /// Notification sent when a remote device completes HCI disconnection. fn on_device_disconnected(&mut self, remote_device: BluetoothDevice); + + /// Notification sent when a remote device fails to complete HCI connection. + fn on_device_connection_failed(&mut self, remote_device: BluetoothDevice, status: BtStatus); } /// Implementation of the adapter API. @@ -2061,6 +2064,12 @@ impl BtifBluetoothCallbacks for Bluetooth { conn_direction, hci_reason, ); + self.connection_callbacks.for_all_callbacks(|callback| { + callback.on_device_connection_failed( + BluetoothDevice::new(addr, String::from("")), + status, + ); + }); return; } -- GitLab From 5d029087338f1a330ef81f885b8f782ed7cde0f3 Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Tue, 15 Oct 2024 10:59:51 -0700 Subject: [PATCH 327/875] Add flag associate_browse_l2cap_request_with_active_control_channel Bug: 373482555 Bug: 315241296 Bug: 373471940 Test: mmm packages/modules/Bluetooth Change-Id: Ib1a71650301b05e1164e788965edd71d42e2a017 --- flags/avrcp_controller.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/avrcp_controller.aconfig b/flags/avrcp_controller.aconfig index 11e8dc85e8c..de205eba5cb 100644 --- a/flags/avrcp_controller.aconfig +++ b/flags/avrcp_controller.aconfig @@ -30,3 +30,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "associate_browse_l2cap_request_with_active_control_channel" + namespace: "bluetooth" + description: " Associate a browse l2cap channel connection with the control channel from that same device regardless of specified role" + bug: "373482555" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 56c6d9afc15b06acf25c9cc352c1e0daf8d31fb2 Mon Sep 17 00:00:00 2001 From: Michael Sun Date: Tue, 15 Oct 2024 18:23:06 +0000 Subject: [PATCH 328/875] Add comments to interop database Add comments to specify interop devices in interop database. Bug: 332761737 Change-Id: I383002b45a8d6e353e6e0a861057b4eac77bbd2f Test: mmm packages/modules/Bluetooth Flag: EXEMPT, comment only --- system/conf/interop_database.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/conf/interop_database.conf b/system/conf/interop_database.conf index 588d567a053..e6521a3f141 100644 --- a/system/conf/interop_database.conf +++ b/system/conf/interop_database.conf @@ -871,8 +871,10 @@ BSK10 = Name_Based # Some HOGP devices have the report map longer than the maximum GATT attribute value length (512 # bytes). [INTEROP_HOGP_LONG_REPORT] +# 0x03f6-0xa001 - Brydge C-Type Wireless Desktop Keyboard 0x03f6-0xa001 = Vndr_Prdt_Based # Some HOGP devices requires MTU exchange be part of the initial setup to function. +# 0x03f6-0xa001 - Brydge C-Type Wireless Desktop Keyboard [INTEROP_HOGP_FORCE_MTU_EXCHANGE] 0x03f6-0xa001 = Vndr_Prdt_Based -- GitLab From ad9b228be7abfa2d4ec95460404747130a4a349f Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sat, 12 Oct 2024 19:49:11 +0000 Subject: [PATCH 329/875] Simplify the onStartFail, keep java layer check only. Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 373042559 Test: m com.android.btservices Change-Id: I6bdae5d794dce195468a13fe39b01e83e7b71193 --- .../app/jni/com_android_bluetooth_gatt.cpp | 14 +---- .../gatt/DistanceMeasurementManager.java | 54 +++---------------- .../DistanceMeasurementNativeInterface.java | 5 -- .../gatt/DistanceMeasurementManagerTest.java | 2 +- system/gd/hci/distance_measurement_manager.cc | 45 +++++++--------- system/gd/hci/distance_measurement_manager.h | 2 - .../hci/distance_measurement_manager_mock.h | 2 - .../hardware/distance_measurement_interface.h | 2 - .../main/shim/distance_measurement_manager.cc | 9 ---- 9 files changed, 28 insertions(+), 107 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index 15cab4f12b2..71325ee0c74 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -197,7 +197,6 @@ static jmethodID method_onBigInfoReport; * Distance Measurement callback methods */ static jmethodID method_onDistanceMeasurementStarted; -static jmethodID method_onDistanceMeasurementStartFail; static jmethodID method_onDistanceMeasurementStopped; static jmethodID method_onDistanceMeasurementResult; @@ -1210,16 +1209,7 @@ public: sCallbackEnv->CallVoidMethod(mDistanceMeasurementCallbacksObj, method_onDistanceMeasurementStarted, addr.get(), method); } - void OnDistanceMeasurementStartFail(RawAddress address, uint8_t reason, uint8_t method) { - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || !mDistanceMeasurementCallbacksObj) { - return; - } - ScopedLocalRef addr(sCallbackEnv.get(), bdaddr2newjstr(sCallbackEnv.get(), &address)); - sCallbackEnv->CallVoidMethod(mDistanceMeasurementCallbacksObj, - method_onDistanceMeasurementStartFail, addr.get(), reason, method); - } + void OnDistanceMeasurementStopped(RawAddress address, uint8_t reason, uint8_t method) { std::shared_lock lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); @@ -2975,8 +2965,6 @@ static int register_com_android_bluetooth_gatt_distance_measurement(JNIEnv* env) const JNIJavaMethod javaMethods[] = { {"onDistanceMeasurementStarted", "(Ljava/lang/String;I)V", &method_onDistanceMeasurementStarted}, - {"onDistanceMeasurementStartFail", "(Ljava/lang/String;II)V", - &method_onDistanceMeasurementStartFail}, {"onDistanceMeasurementStopped", "(Ljava/lang/String;II)V", &method_onDistanceMeasurementStopped}, {"onDistanceMeasurementResult", "(Ljava/lang/String;IIIIIIJII)V", diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java index b4f27559bc8..f9f3cc14007 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java @@ -364,52 +364,6 @@ public class DistanceMeasurementManager { } } - void onDistanceMeasurementStartFail(String address, int reason, int method) { - logd( - "onDistanceMeasurementStartFail address:" - + BluetoothUtils.toAnonymizedAddress(address) - + ", method:" - + method); - switch (method) { - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: - handleRssiStartFail(address, reason); - break; - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: - handleCsStartFail(address, reason); - break; - default: - Log.w(TAG, "onDistanceMeasurementStartFail: invalid method " + method); - } - } - - void handleRssiStartFail(String address, int reason) { - CopyOnWriteArraySet set = mRssiTrackers.get(address); - if (set == null) { - Log.w(TAG, "Can't find rssi tracker"); - return; - } - for (DistanceMeasurementTracker tracker : set) { - if (!tracker.mStarted) { - invokeStartFail(tracker.mCallback, tracker.mDevice, reason); - } - } - set.removeIf(tracker -> !tracker.mStarted); - } - - void handleCsStartFail(String address, int reason) { - CopyOnWriteArraySet set = mCsTrackers.get(address); - if (set == null) { - Log.w(TAG, "Can't find CS tracker"); - return; - } - for (DistanceMeasurementTracker tracker : set) { - if (!tracker.mStarted) { - invokeStartFail(tracker.mCallback, tracker.mDevice, reason); - } - } - set.removeIf(tracker -> !tracker.mStarted); - } - void onDistanceMeasurementStopped(String address, int reason, int method) { logd( "onDistanceMeasurementStopped address:" @@ -440,9 +394,11 @@ public class DistanceMeasurementManager { if (tracker.mStarted) { tracker.cancelTimer(); invokeOnStopped(tracker.mCallback, tracker.mDevice, reason); + } else { + invokeStartFail(tracker.mCallback, tracker.mDevice, reason); } } - set.removeIf(tracker -> tracker.mStarted); + mRssiTrackers.remove(address); } void handleCsStopped(String address, int reason) { @@ -455,9 +411,11 @@ public class DistanceMeasurementManager { if (tracker.mStarted) { tracker.cancelTimer(); invokeOnStopped(tracker.mCallback, tracker.mDevice, reason); + } else { + invokeStartFail(tracker.mCallback, tracker.mDevice, reason); } } - set.removeIf(tracker -> tracker.mStarted); + mCsTrackers.remove(address); } void onDistanceMeasurementResult( diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java index 5d1b56b8db5..7009dde6979 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java @@ -92,11 +92,6 @@ public class DistanceMeasurementNativeInterface { mDistanceMeasurementManager.onDistanceMeasurementStarted(address, method); } - void onDistanceMeasurementStartFail(String address, int reason, int method) { - mDistanceMeasurementManager.onDistanceMeasurementStartFail( - address, convertErrorCode(reason), method); - } - void onDistanceMeasurementStopped(String address, int reason, int method) { mDistanceMeasurementManager.onDistanceMeasurementStopped( address, convertErrorCode(reason), method); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java index 1fe9bfb1365..2adcd38274f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java @@ -146,7 +146,7 @@ public class DistanceMeasurementManagerTest { IDENTITY_ADDRESS, RSSI_FREQUENCY_LOW, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); - mDistanceMeasurementManager.onDistanceMeasurementStartFail( + mDistanceMeasurementManager.onDistanceMeasurementStopped( IDENTITY_ADDRESS, BluetoothStatusCodes.ERROR_DISTANCE_MEASUREMENT_INTERNAL, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index d21a42947d4..b5761e7afa3 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -195,7 +195,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::error("Can't find CS tracker for connection_handle {}", connection_handle); return; } - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( + distance_measurement_callbacks_->OnDistanceMeasurementStopped( cs_requester_trackers_[connection_handle].address, REASON_INTERNAL_ERROR, METHOD_CS); } @@ -269,7 +269,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { // Remove this check if we support any connection less method if (connection_handle == kIllegalConnectionHandle) { log::warn("Can't find any LE connection for {}", address); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( + distance_measurement_callbacks_->OnDistanceMeasurementStopped( address, REASON_NO_LE_CONNECTION, method); return; } @@ -328,7 +328,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::info("connection_handle: {}, address: {}", connection_handle, cs_remote_address); if (!com::android::bluetooth::flags::channel_sounding_in_stack()) { log::error("Channel Sounding is not enabled"); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( + distance_measurement_callbacks_->OnDistanceMeasurementStopped( cs_remote_address, REASON_INTERNAL_ERROR, METHOD_CS); return; } @@ -492,14 +492,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { auto it = cs_requester_trackers_.find(connection_handle); if (it == cs_requester_trackers_.end()) { log::warn("can't find tracker for 0x{:04x}", connection_handle); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - address, REASON_INTERNAL_ERROR, METHOD_CS); + distance_measurement_callbacks_->OnDistanceMeasurementStopped(address, REASON_INTERNAL_ERROR, + METHOD_CS); return; } if (!success) { - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - address, REASON_INTERNAL_ERROR, METHOD_CS); + distance_measurement_callbacks_->OnDistanceMeasurementStopped(address, REASON_INTERNAL_ERROR, + METHOD_CS); return; } @@ -619,13 +619,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } if (it->second.measurement_ongoing) { - if (it->second.waiting_for_start_callback) { - distance_measurement_callbacks_->OnDistanceMeasurementStartFail(it->second.address, - errorCode, METHOD_CS); - } else { - distance_measurement_callbacks_->OnDistanceMeasurementStopped(it->second.address, errorCode, - METHOD_CS); - } + distance_measurement_callbacks_->OnDistanceMeasurementStopped(it->second.address, errorCode, + METHOD_CS); it->second.repeating_alarm->Cancel(); it->second.repeating_alarm.reset(); } @@ -1505,14 +1500,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { auto status_view = LeReadRemoteTransmitPowerLevelStatusView::Create(view); if (!status_view.IsValid()) { log::warn("Invalid LeReadRemoteTransmitPowerLevelStatus event"); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - address, REASON_INTERNAL_ERROR, METHOD_RSSI); + distance_measurement_callbacks_->OnDistanceMeasurementStopped(address, REASON_INTERNAL_ERROR, + METHOD_RSSI); rssi_trackers.erase(address); } else if (status_view.GetStatus() != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(status_view.GetStatus()); log::warn("Received LeReadRemoteTransmitPowerLevelStatus with error code {}", error_code); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - address, REASON_INTERNAL_ERROR, METHOD_RSSI); + distance_measurement_callbacks_->OnDistanceMeasurementStopped(address, REASON_INTERNAL_ERROR, + METHOD_RSSI); rssi_trackers.erase(address); } } @@ -1558,7 +1553,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { address, event_view.GetConnectionHandle())); } else { log::warn("Read remote transmit power level fail"); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( + distance_measurement_callbacks_->OnDistanceMeasurementStopped( address, REASON_INTERNAL_ERROR, METHOD_RSSI); rssi_trackers.erase(address); } @@ -1570,24 +1565,24 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { auto complete_view = LeSetTransmitPowerReportingEnableCompleteView::Create(view); if (!complete_view.IsValid()) { log::warn("Invalid LeSetTransmitPowerReportingEnableComplete event"); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - address, REASON_INTERNAL_ERROR, METHOD_RSSI); + distance_measurement_callbacks_->OnDistanceMeasurementStopped(address, REASON_INTERNAL_ERROR, + METHOD_RSSI); rssi_trackers.erase(address); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(complete_view.GetStatus()); log::warn("Received LeSetTransmitPowerReportingEnableComplete with error code {}", error_code); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - address, REASON_INTERNAL_ERROR, METHOD_RSSI); + distance_measurement_callbacks_->OnDistanceMeasurementStopped(address, REASON_INTERNAL_ERROR, + METHOD_RSSI); rssi_trackers.erase(address); return; } if (rssi_trackers.find(address) == rssi_trackers.end()) { log::warn("Can't find rssi tracker for {}", address); - distance_measurement_callbacks_->OnDistanceMeasurementStartFail( - address, REASON_INTERNAL_ERROR, METHOD_RSSI); + distance_measurement_callbacks_->OnDistanceMeasurementStopped(address, REASON_INTERNAL_ERROR, + METHOD_RSSI); rssi_trackers.erase(address); } else { log::info("Track rssi for address {}", address); diff --git a/system/gd/hci/distance_measurement_manager.h b/system/gd/hci/distance_measurement_manager.h index 03103200b89..70739c39e40 100644 --- a/system/gd/hci/distance_measurement_manager.h +++ b/system/gd/hci/distance_measurement_manager.h @@ -53,8 +53,6 @@ class DistanceMeasurementCallbacks { public: virtual ~DistanceMeasurementCallbacks() = default; virtual void OnDistanceMeasurementStarted(Address address, DistanceMeasurementMethod method) = 0; - virtual void OnDistanceMeasurementStartFail(Address address, DistanceMeasurementErrorCode reason, - DistanceMeasurementMethod method) = 0; virtual void OnDistanceMeasurementStopped(Address address, DistanceMeasurementErrorCode reason, DistanceMeasurementMethod method) = 0; virtual void OnDistanceMeasurementResult(Address address, uint32_t centimeter, diff --git a/system/gd/hci/distance_measurement_manager_mock.h b/system/gd/hci/distance_measurement_manager_mock.h index e062f1e3136..0f71c51c336 100644 --- a/system/gd/hci/distance_measurement_manager_mock.h +++ b/system/gd/hci/distance_measurement_manager_mock.h @@ -32,8 +32,6 @@ namespace testing { class MockDistanceMeasurementCallbacks : public DistanceMeasurementCallbacks { MOCK_METHOD(void, OnDistanceMeasurementStarted, (Address, DistanceMeasurementMethod)); - MOCK_METHOD(void, OnDistanceMeasurementStartFail, - (Address, DistanceMeasurementErrorCode, DistanceMeasurementMethod)); MOCK_METHOD(void, OnDistanceMeasurementStopped, (Address, DistanceMeasurementErrorCode, DistanceMeasurementMethod)); MOCK_METHOD(void, OnDistanceMeasurementResult, diff --git a/system/include/hardware/distance_measurement_interface.h b/system/include/hardware/distance_measurement_interface.h index 01367a557db..2f24dbf9a2f 100644 --- a/system/include/hardware/distance_measurement_interface.h +++ b/system/include/hardware/distance_measurement_interface.h @@ -27,8 +27,6 @@ class DistanceMeasurementCallbacks { public: virtual ~DistanceMeasurementCallbacks() = default; virtual void OnDistanceMeasurementStarted(RawAddress address, uint8_t method) = 0; - virtual void OnDistanceMeasurementStartFail(RawAddress address, uint8_t reason, - uint8_t method) = 0; virtual void OnDistanceMeasurementStopped(RawAddress address, uint8_t reason, uint8_t method) = 0; virtual void OnDistanceMeasurementResult(RawAddress address, uint32_t centimeter, uint32_t error_centimeter, int azimuth_angle, diff --git a/system/main/shim/distance_measurement_manager.cc b/system/main/shim/distance_measurement_manager.cc index 53bc0c02118..aa5373f7f72 100644 --- a/system/main/shim/distance_measurement_manager.cc +++ b/system/main/shim/distance_measurement_manager.cc @@ -105,15 +105,6 @@ public: static_cast(method))); } - void OnDistanceMeasurementStartFail(bluetooth::hci::Address address, - DistanceMeasurementErrorCode reason, - DistanceMeasurementMethod method) override { - do_in_jni_thread(base::BindOnce(&::DistanceMeasurementCallbacks::OnDistanceMeasurementStartFail, - base::Unretained(distance_measurement_callbacks_), - bluetooth::ToRawAddress(address), static_cast(reason), - static_cast(method))); - } - void OnDistanceMeasurementStopped(bluetooth::hci::Address address, DistanceMeasurementErrorCode reason, DistanceMeasurementMethod method) override { -- GitLab From da7a2ee0193e727c6c38da10dcae097672f2fb00 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Tue, 1 Oct 2024 20:47:29 +0000 Subject: [PATCH 330/875] Remove leaudio_broadcast_monitor_source_sync_status flag Bug: 307406671 Test: m com.android.btservices Change-Id: Ie39e579a9b3c8e0dceee2e28c0bddf89d73ca97e --- .../bass_client/BassClientService.java | 25 +++------ .../bass_client/BassClientStateMachine.java | 20 +++---- .../bass_client/BassClientServiceTest.java | 42 +++----------- .../BassClientStateMachineTest.java | 2 - framework/api/system-current.txt | 8 +-- .../BluetoothLeBroadcastAssistant.java | 4 -- .../BluetoothLeBroadcastMetadata.java | 6 -- framework/lint-baseline.xml | 55 ------------------- 8 files changed, 28 insertions(+), 134 deletions(-) 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 c58c652bb6c..11d69dbd9e3 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -25,7 +25,6 @@ import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask; import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState; import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment; import static com.android.bluetooth.flags.Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine; -import static com.android.bluetooth.flags.Flags.leaudioBroadcastMonitorSourceSyncStatus; import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper; import static com.android.bluetooth.flags.Flags.leaudioSortScansToSyncByFails; @@ -390,12 +389,8 @@ public class BassClientService extends ProfileService { + " same syncHandle=" + syncHandle + ", before syncLost"); - if (leaudioBroadcastMonitorSourceSyncStatus()) { - log( - "Notify broadcast source lost, broadcast id: " - + oldBroadcastId); - mCallbacks.notifySourceLost(oldBroadcastId); - } + log("Notify broadcast source lost, broadcast id: " + oldBroadcastId); + mCallbacks.notifySourceLost(oldBroadcastId); clearAllDataForSyncHandle(syncHandle); mCachedBroadcasts.remove(oldBroadcastId); } @@ -2203,10 +2198,8 @@ public class BassClientService extends ProfileService { mCachedBroadcasts.remove(broadcastId); } } - if (leaudioBroadcastMonitorSourceSyncStatus()) { - log("Notify broadcast source lost, broadcast id: " + broadcastId); - mCallbacks.notifySourceLost(broadcastId); - } + log("Notify broadcast source lost, broadcast id: " + broadcastId); + mCallbacks.notifySourceLost(broadcastId); } } } @@ -2359,12 +2352,10 @@ public class BassClientService extends ProfileService { } } metaData.setEncrypted(encrypted); - if (leaudioBroadcastMonitorSourceSyncStatus()) { - // update the rssi value - ScanResult scanRes = getCachedBroadcast(result.getBroadcastId()); - if (scanRes != null) { - metaData.setRssi(scanRes.getRssi()); - } + // update the rssi value + ScanResult scanRes = getCachedBroadcast(result.getBroadcastId()); + if (scanRes != null) { + metaData.setRssi(scanRes.getRssi()); } return metaData.build(); } diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index 333d8532d5b..ebb272d073b 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -789,12 +789,10 @@ public class BassClientStateMachine extends StateMachine { } } metaData.setEncrypted(encrypted); - if (Flags.leaudioBroadcastMonitorSourceSyncStatus()) { - // update the rssi value - ScanResult scanRes = mService.getCachedBroadcast(result.getBroadcastId()); - if (scanRes != null) { - metaData.setRssi(scanRes.getRssi()); - } + // update the rssi value + ScanResult scanRes = mService.getCachedBroadcast(result.getBroadcastId()); + if (scanRes != null) { + metaData.setRssi(scanRes.getRssi()); } return metaData.build(); } @@ -1482,12 +1480,10 @@ public class BassClientStateMachine extends StateMachine { + " leaudioBroadcastExtractPeriodicScannerFromStateMachine flag"); } log("OnSyncLost" + syncHandle); - if (Flags.leaudioBroadcastMonitorSourceSyncStatus()) { - int broadcastId = mService.getBroadcastIdForSyncHandle(syncHandle); - if (broadcastId != BassConstants.INVALID_BROADCAST_ID) { - log("Notify broadcast source lost, broadcast id: " + broadcastId); - mService.getCallbacks().notifySourceLost(broadcastId); - } + int broadcastId = mService.getBroadcastIdForSyncHandle(syncHandle); + if (broadcastId != BassConstants.INVALID_BROADCAST_ID) { + log("Notify broadcast source lost, broadcast id: " + broadcastId); + mService.getCallbacks().notifySourceLost(broadcastId); } cancelActiveSync(syncHandle); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 246677b6ed1..dbc9d741dcf 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -4554,10 +4554,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void onPeriodicAdvertisingReport_withoutBaseData_cancelActiveSync() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -4648,10 +4645,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void onPeriodicAdvertisingReport_wrongBaseData_cancelActiveSync() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -4751,10 +4745,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void onPeriodicAdvertisingReport_updateBase() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -4788,10 +4779,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void onPeriodicAdvertisingReport_updateBaseAfterWrongBaseData() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -4935,10 +4923,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void notifySourceFound_once_updateRssi() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -4995,7 +4980,6 @@ public class BassClientServiceTest { @Test @EnableFlags({ Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS, Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE }) public void notifySourceFound_without_public_announcement() { @@ -5102,10 +5086,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void notifySourceFound_periodic_after_big() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -5159,7 +5140,6 @@ public class BassClientServiceTest { @Test @EnableFlags({ Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS, Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE }) public void notifySourceFound_periodic_after_wrong_periodic() { @@ -5251,10 +5231,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void notifySourceFound_alreadySynced_clearFlag() { // Scan prepareConnectedDeviceGroup(); @@ -5322,10 +5299,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, - Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) public void onSyncLost_notifySourceLostAndCancelSync() { prepareConnectedDeviceGroup(); startSearchingForSources(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index 70b50063dd8..813820e102a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -2224,7 +2224,6 @@ public class BassClientStateMachineTest { public void periodicAdvertisingCallbackOnSyncLost_notifySourceLost() { mSetFlagsRule.disableFlags( Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE); - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS); PeriodicAdvertisingCallback cb = mBassClientStateMachine.mLocalPeriodicAdvCallback; BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); int syncHandle = 1; @@ -2240,7 +2239,6 @@ public class BassClientStateMachineTest { public void periodicAdvertisingCallbackOnBigInfoAdvertisingReport_updateRssi() { mSetFlagsRule.disableFlags( Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE); - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS); PeriodicAdvertisingCallback cb = mBassClientStateMachine.mLocalPeriodicAdvCallback; BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); int testRssi = -40; diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 8fb6d6940a4..b0d2f78d71d 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -612,7 +612,7 @@ package android.bluetooth { method public void onSourceAddFailed(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothLeBroadcastMetadata, int); method public void onSourceAdded(@NonNull android.bluetooth.BluetoothDevice, int, int); method public void onSourceFound(@NonNull android.bluetooth.BluetoothLeBroadcastMetadata); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status") public default void onSourceLost(int); + method public default void onSourceLost(int); method public void onSourceModified(@NonNull android.bluetooth.BluetoothDevice, int, int); method public void onSourceModifyFailed(@NonNull android.bluetooth.BluetoothDevice, int, int); method public void onSourceRemoveFailed(@NonNull android.bluetooth.BluetoothDevice, int, int); @@ -646,7 +646,7 @@ package android.bluetooth { method public int getPaSyncInterval(); method @IntRange(from=0, to=16777215) public int getPresentationDelayMicros(); method @Nullable public android.bluetooth.BluetoothLeAudioContentMetadata getPublicBroadcastMetadata(); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status") @IntRange(from=0xffffff81, to=127) public int getRssi(); + method @IntRange(from=0xffffff81, to=127) public int getRssi(); method public int getSourceAddressType(); method public int getSourceAdvertisingSid(); method @NonNull public android.bluetooth.BluetoothDevice getSourceDevice(); @@ -659,7 +659,7 @@ package android.bluetooth { field public static final int AUDIO_CONFIG_QUALITY_STANDARD = 1; // 0x1 field @NonNull public static final android.os.Parcelable.Creator CREATOR; field public static final int PA_SYNC_INTERVAL_UNKNOWN = 65535; // 0xffff - field @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status") public static final int RSSI_UNKNOWN = 127; // 0x7f + field public static final int RSSI_UNKNOWN = 127; // 0x7f } public static final class BluetoothLeBroadcastMetadata.Builder { @@ -677,7 +677,7 @@ package android.bluetooth { method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPresentationDelayMicros(@IntRange(from=0, to=16777215) int); method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPublicBroadcast(boolean); method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPublicBroadcastMetadata(@Nullable android.bluetooth.BluetoothLeAudioContentMetadata); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status") @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setRssi(@IntRange(from=0xffffff81, to=127) int); + method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setRssi(@IntRange(from=0xffffff81, to=127) int); method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setSourceAdvertisingSid(int); method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setSourceDevice(@NonNull android.bluetooth.BluetoothDevice, int); } diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java index ecebdf85a1c..b802943b497 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java @@ -21,7 +21,6 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.BLUETOOTH_SCAN; import android.annotation.CallbackExecutor; -import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -41,8 +40,6 @@ import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; -import com.android.bluetooth.flags.Flags; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -454,7 +451,6 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au * @param broadcastId broadcast ID as defined in the BASS specification * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS) @SystemApi default void onSourceLost(int broadcastId) {} } diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java index e49b3bd08d5..bfaca06612c 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java @@ -16,7 +16,6 @@ package android.bluetooth; -import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; @@ -25,8 +24,6 @@ import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import com.android.bluetooth.flags.Flags; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -359,7 +356,6 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable { * * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS) @SystemApi public static final int RSSI_UNKNOWN = 0x7F; @@ -373,7 +369,6 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable { * @return the RSSI {@link #RSSI_UNKNOWN} if unknown * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS) @SystemApi public @IntRange(from = -127, to = 127) int getRssi() { return mRssi; @@ -751,7 +746,6 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable { * @throws IllegalArgumentException if rssi is not in the range [-127, 127]. * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS) @SystemApi @NonNull public Builder setRssi(@IntRange(from = -127, to = 127) int rssi) { diff --git a/framework/lint-baseline.xml b/framework/lint-baseline.xml index e0cbba3180a..99d358bfd3f 100644 --- a/framework/lint-baseline.xml +++ b/framework/lint-baseline.xml @@ -34,61 +34,6 @@ column="16"/> - - - - - - - - - - - - - - - - - - - - Date: Tue, 15 Oct 2024 16:22:09 -0700 Subject: [PATCH 331/875] l2c_link.cc: Remove unnecessary log There is one verbose log that floods logcat and has yet to be helpful in debugging. Remove this log. Bug: 373721455 Test: m com.android.btservices Flag: EXEMPT log only Change-Id: I862cbfd2bc51deab34a1b6d5dfa3e5c6bc24a8ef --- system/stack/l2cap/l2c_link.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/system/stack/l2cap/l2c_link.cc b/system/stack/l2cap/l2c_link.cc index baf9d4c2dd3..b7521ab6776 100644 --- a/system/stack/l2cap/l2c_link.cc +++ b/system/stack/l2cap/l2c_link.cc @@ -1241,9 +1241,6 @@ tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) { return NULL; } - log::verbose("RR scan pri={}, lcid=0x{:04x}, q_cout={}", p_ccb->ccb_priority, - p_ccb->local_cid, fixed_queue_length(p_ccb->xmit_hold_q)); - /* store the next serving channel */ /* this channel is the last channel of its priority group */ if ((p_ccb->p_next_ccb == NULL) || (p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority)) { -- GitLab From f572ba83bb9f0b7f8fe7b7c5905c25f1be87c855 Mon Sep 17 00:00:00 2001 From: Bhakthavatsala Raghavendra Date: Wed, 16 Oct 2024 00:05:35 +0000 Subject: [PATCH 332/875] Add flag to set LE data length to max on le coc connection Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.set_max_data_length_for_lecoc Bug: 373726267 Bug: 315241296 Change-Id: I8ec41c91dd21c77da88016c587e83b33cf727c04 --- flags/sockets.aconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/flags/sockets.aconfig b/flags/sockets.aconfig index d45406ac5ae..d0ba2d2a5f4 100644 --- a/flags/sockets.aconfig +++ b/flags/sockets.aconfig @@ -35,3 +35,12 @@ flag { is_exported: true } +flag { + name: "set_max_data_length_for_lecoc" + namespace: "bluetooth" + description: "set le data length to max on le coc connection to achieve better data rate" + bug: "373726267" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 39037b8d6fce66daf3318b127e46400c8cdcd4ef Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 15 Oct 2024 16:14:31 -0700 Subject: [PATCH 333/875] btif_a2dp_source: Remove unused APIs Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I059fb39e5a92bd75a166b0325373d7f0533054b6 --- system/btif/include/btif_a2dp_source.h | 13 ------------- system/btif/src/btif_a2dp_source.cc | 19 ++----------------- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/system/btif/include/btif_a2dp_source.h b/system/btif/include/btif_a2dp_source.h index 0e32a3bde69..4062a5413ee 100644 --- a/system/btif/include/btif_a2dp_source.h +++ b/system/btif/include/btif_a2dp_source.h @@ -34,11 +34,6 @@ // module. bool btif_a2dp_source_init(void); -// Startup the A2DP Source module. -// This function should be called by the BTIF state machine after -// btif_a2dp_source_init() to prepare to start streaming. -bool btif_a2dp_source_startup(void); - // Start the A2DP Source session. // This function should be called by the BTIF state machine after // btif_a2dp_source_startup() to start the streaming session for |peer_address|. @@ -70,14 +65,6 @@ void btif_a2dp_source_shutdown(std::promise); // cleanup. void btif_a2dp_source_cleanup(void); -// Check whether the A2DP Source media task is running. -// Returns true if the A2DP Source media task is running, otherwise false. -bool btif_a2dp_source_media_task_is_running(void); - -// Check whether the A2DP Source media task is shutting down. -// Returns true if the A2DP Source media task is shutting down. -bool btif_a2dp_source_media_task_is_shutting_down(void); - // Return true if the A2DP Source module is streaming. bool btif_a2dp_source_is_streaming(void); diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 4f216ef1bd0..e4b197845a5 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -233,12 +233,12 @@ static BtifA2dpSource btif_a2dp_source_cb; static uint8_t btif_a2dp_source_dynamic_audio_buffer_size = MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ; static void btif_a2dp_source_init_delayed(void); +static bool btif_a2dp_source_startup(void); static void btif_a2dp_source_startup_delayed(void); static void btif_a2dp_source_start_session_delayed(const RawAddress& peer_address, std::promise start_session_promise); static void btif_a2dp_source_end_session_delayed(const RawAddress& peer_address); static void btif_a2dp_source_shutdown_delayed(std::promise); -static void btif_a2dp_source_cleanup_delayed(void); static void btif_a2dp_source_audio_tx_start_event(void); static void btif_a2dp_source_audio_tx_stop_event(void); static void btif_a2dp_source_audio_tx_flush_event(void); @@ -388,7 +388,7 @@ static void btif_a2dp_source_init_delayed(void) { btif_av_is_a2dp_offload_enabled()); } -bool btif_a2dp_source_startup(void) { +static bool btif_a2dp_source_startup(void) { log::info("state={}", btif_a2dp_source_cb.StateStr()); if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateOff) { @@ -555,25 +555,10 @@ void btif_a2dp_source_cleanup(void) { std::promise shutdown_complete_promise; btif_a2dp_source_shutdown(std::move(shutdown_complete_promise)); - btif_a2dp_source_thread.DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_cleanup_delayed)); - // Exit the thread btif_a2dp_source_thread.ShutDown(); } -static void btif_a2dp_source_cleanup_delayed(void) { - log::info("state={}", btif_a2dp_source_cb.StateStr()); - // Nothing to do -} - -bool btif_a2dp_source_media_task_is_running(void) { - return btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning; -} - -bool btif_a2dp_source_media_task_is_shutting_down(void) { - return btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown; -} - // This runs on worker thread bool btif_a2dp_source_is_streaming(void) { return btif_a2dp_source_cb.media_alarm.IsScheduled(); } -- GitLab From a15f4f1404730563362571898ef74f6552bf3a57 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 15 Oct 2024 17:38:57 -0700 Subject: [PATCH 334/875] Gracefully handle IBluetoothAudioProviderFactory::openProvider failure openProvider sometimes returns the ok() status but a null IBluetoothAudioProvider instance. Gracefully handle this case and treat it as a regular failure. Bug: 372309179 Bug: 341856622 Test: m com.android.btservices Flag: EXEMPT, minor bug fix Change-Id: I90988e36a62336d64396e4fd14700ca48a11b80b --- system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc index fdfdceccc19..42af94d9a7b 100644 --- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc @@ -197,7 +197,7 @@ void BluetoothAudioClientInterface::FetchAudioProvider() { toString(transport_->GetSessionType()), capabilities_.size()); aidl_retval = provider_factory->openProvider(transport_->GetSessionType(), &provider_); - if (!aidl_retval.isOk()) { + if (!aidl_retval.isOk() || provider_ == nullptr) { log::error("BluetoothAudioHal::openProvider failure: {}, retry number {}", aidl_retval.getDescription(), retry_no + 1); } else { -- GitLab From c1ad6fd065443f60f4fc046b5ee0bf56322525a0 Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Wed, 2 Oct 2024 20:08:20 +0800 Subject: [PATCH 335/875] btif_sock_rfc: Cancel ongoing SDP on socket closed When a socket is closed while the SDP is still ongoing, btif socket slot would be cleaned up but BTA Jv would not, which makes all later RFCOMM connection fail. The issue usually persists until the SDP completes, but we also observed that the SDP complete event could never happen. This patch shall mitigate the issue. Bug: 331018524 Bug: 370916753 Test: atest BumbleBluetoothTests:android.bluetooth.RfcommTest#clientConnectToOpenServerSocketBondedInsecurePrematureClosure; Passed with flag enabled and failed with flag disabled Flag: rfcomm_cancel_ongoing_sdp_on_close Change-Id: If2bdc0f0d3b5f9cfc48073f1788241fc296582de --- system/bta/include/bta_jv_api.h | 13 +++++++++++++ system/bta/jv/bta_jv_act.cc | 22 ++++++++++++++++++++++ system/bta/jv/bta_jv_api.cc | 16 ++++++++++++++++ system/bta/jv/bta_jv_int.h | 1 + system/btif/src/btif_sock_rfc.cc | 5 +++++ system/test/mock/mock_bta_jv_api.cc | 1 + 6 files changed, 58 insertions(+) diff --git a/system/bta/include/bta_jv_api.h b/system/bta/include/bta_jv_api.h index 4bf5cbe490a..f43bb9ed753 100644 --- a/system/bta/include/bta_jv_api.h +++ b/system/bta/include/bta_jv_api.h @@ -512,6 +512,19 @@ tBTA_JV_STATUS BTA_JvFreeChannel(uint16_t channel, tBTA_JV_CONN_TYPE conn_type); tBTA_JV_STATUS BTA_JvStartDiscovery(const RawAddress& bd_addr, uint16_t num_uuid, const bluetooth::Uuid* p_uuid_list, uint32_t rfcomm_slot_id); +/******************************************************************************* + * + * Function BTA_JvCancelDiscovery + * + * Description This function cancels the ongoing service discovery and make + * sure the tBTA_JV_DM_CBACK callback function will be called + * with a BTA_JV_DISCOVERY_COMP_EVT. + * + * Returns void + * + ******************************************************************************/ +void BTA_JvCancelDiscovery(uint32_t rfcomm_slot_id); + /******************************************************************************* * * Function BTA_JvCreateRecordByUser diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc index 647e7b2a5b0..852204ed617 100644 --- a/system/bta/jv/bta_jv_act.cc +++ b/system/bta/jv/bta_jv_act.cc @@ -916,6 +916,28 @@ void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid, } } +void bta_jv_cancel_discovery(uint32_t rfcomm_slot_id) { + if (!bta_jv_cb.sdp_cb.sdp_active) { + log::error("Canceling discovery but discovery is not active"); + return; + } + if (!get_legacy_stack_sdp_api()->service.SDP_CancelServiceSearch(p_bta_jv_cfg->p_sdp_db)) { + log::error("Failed to cancel discovery, clean up the control block anyway"); + bta_jv_cb.sdp_cb = {}; + /* Send complete event right away as we might not receive callback from stack */ + if (bta_jv_cb.p_dm_cback) { + tBTA_JV bta_jv = { + .status = tBTA_JV_STATUS::FAILURE, + }; + bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, rfcomm_slot_id); + } else { + log::warn("No callback set for discovery complete event"); + } + } else { + log::info("Canceled discovery"); + } +} + /* Create an SDP record with the given attributes */ void bta_jv_create_record(uint32_t rfcomm_slot_id) { tBTA_JV_CREATE_RECORD evt_data; diff --git a/system/bta/jv/bta_jv_api.cc b/system/bta/jv/bta_jv_api.cc index 63456511b15..1b5e715384b 100644 --- a/system/bta/jv/bta_jv_api.cc +++ b/system/bta/jv/bta_jv_api.cc @@ -166,6 +166,22 @@ tBTA_JV_STATUS BTA_JvStartDiscovery(const RawAddress& bd_addr, uint16_t num_uuid return tBTA_JV_STATUS::SUCCESS; } +/******************************************************************************* + * + * Function BTA_JvCancelDiscovery + * + * Description This function cancels the ongoing service discovery and make + * sure the tBTA_JV_DM_CBACK callback function will be called + * with a BTA_JV_DISCOVERY_COMP_EVT. + * + * Returns void + * + ******************************************************************************/ +void BTA_JvCancelDiscovery(uint32_t rfcomm_slot_id) { + log::verbose("rfcomm_slot_id:{}", rfcomm_slot_id); + do_in_main_thread(Bind(&bta_jv_cancel_discovery, rfcomm_slot_id)); +} + /******************************************************************************* * * Function BTA_JvCreateRecord diff --git a/system/bta/jv/bta_jv_int.h b/system/bta/jv/bta_jv_int.h index bffa2b029f5..f7aa7d106fb 100644 --- a/system/bta/jv/bta_jv_int.h +++ b/system/bta/jv/bta_jv_int.h @@ -148,6 +148,7 @@ void bta_jv_get_channel_id(tBTA_JV_CONN_TYPE type, int32_t channel, uint32_t l2c void bta_jv_free_scn(tBTA_JV_CONN_TYPE type, uint16_t scn); void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid, bluetooth::Uuid* uuid_list, uint32_t rfcomm_slot_id); +void bta_jv_cancel_discovery(uint32_t rfcomm_slot_id); void bta_jv_create_record(uint32_t rfcomm_slot_id); void bta_jv_delete_record(uint32_t handle); void bta_jv_l2cap_connect(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, uint16_t remote_psm, diff --git a/system/btif/src/btif_sock_rfc.cc b/system/btif/src/btif_sock_rfc.cc index 2f5d60415bb..a7fb56dd5eb 100644 --- a/system/btif/src/btif_sock_rfc.cc +++ b/system/btif/src/btif_sock_rfc.cc @@ -19,6 +19,7 @@ #define LOG_TAG "bt_btif_sock_rfcomm" #include +#include #include #include #include @@ -963,6 +964,10 @@ void btsock_rfc_signaled(int /* fd */, int flags, uint32_t id) { // Clean up if there's no data pending. int size = 0; if (need_close || ioctl(slot->fd, FIONREAD, &size) != 0 || !size) { + if (com::android::bluetooth::flags::rfcomm_cancel_ongoing_sdp_on_close() && + slot->f.doing_sdp_request) { + BTA_JvCancelDiscovery(slot->id); + } cleanup_rfc_slot(slot); } } diff --git a/system/test/mock/mock_bta_jv_api.cc b/system/test/mock/mock_bta_jv_api.cc index d8362c129b5..cf7fd4645e4 100644 --- a/system/test/mock/mock_bta_jv_api.cc +++ b/system/test/mock/mock_bta_jv_api.cc @@ -106,6 +106,7 @@ tBTA_JV_STATUS BTA_JvStartDiscovery(const RawAddress& /* bd_addr */, uint16_t /* inc_func_call_count(__func__); return tBTA_JV_STATUS::SUCCESS; } +void BTA_JvCancelDiscovery(uint32_t /* rfcomm_slot_id */) { inc_func_call_count(__func__); } uint16_t BTA_JvRfcommGetPortHdl(uint32_t /* handle */) { inc_func_call_count(__func__); return 0; -- GitLab From 21f04ce776aef70cfde5c3ba75bf68f4d2d1fffe Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Mon, 14 Oct 2024 04:36:49 +0000 Subject: [PATCH 336/875] Limit tGATT_IF range This commit restricts the range of tGATT_IF values to 1-248, reserving 249-255 for special use cases. This change ensures consistency and avoids potential conflicts. Additionally, the commit addresses issues found while checking all the tGATT_IF usages. Bug: 348559823 Bug: 273561907 Test: atest BumbleBluetoothTests Change-Id: I0b1eb3b1e8736661ea0b9024257c9e7a9c20ad35 --- system/bta/dm/bta_dm_gatt_client.cc | 6 +-- system/internal_include/bt_target.h | 5 -- system/stack/gatt/gatt_api.cc | 59 +++++++++++++----------- system/stack/gatt/gatt_int.h | 2 +- system/stack/gatt/gatt_main.cc | 4 +- system/stack/gatt/gatt_sr.cc | 6 +-- system/stack/gatt/gatt_utils.cc | 11 +++-- system/stack/include/btm_ble_api_types.h | 8 ++++ system/stack/l2cap/l2c_ble.cc | 3 +- 9 files changed, 57 insertions(+), 47 deletions(-) diff --git a/system/bta/dm/bta_dm_gatt_client.cc b/system/bta/dm/bta_dm_gatt_client.cc index 63ef540afa2..189b367e9c9 100644 --- a/system/bta/dm/bta_dm_gatt_client.cc +++ b/system/bta/dm/bta_dm_gatt_client.cc @@ -54,7 +54,7 @@ gatt_interface_t default_gatt_interface = { [](tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct) { gatt_history_.Push(base::StringPrintf( "%-32s bd_addr:%s client_if:%hu is_direct:%c", "GATTC_CancelOpen", - ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, + ADDRESS_TO_LOGGABLE_CSTR(remote_bda), static_cast(client_if), (is_direct) ? 'T' : 'F')); BTA_GATTC_CancelOpen(client_if, remote_bda, is_direct); }, @@ -101,8 +101,8 @@ gatt_interface_t default_gatt_interface = { tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, uint16_t preferred_mtu) { gatt_history_.Push(base::StringPrintf( "%-32s bd_addr:%s client_if:%hu type:0x%x opportunistic:%c", "GATTC_Open", - ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, connection_type, - (opportunistic) ? 'T' : 'F')); + ADDRESS_TO_LOGGABLE_CSTR(remote_bda), static_cast(client_if), + connection_type, (opportunistic) ? 'T' : 'F')); BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type, BT_TRANSPORT_LE, opportunistic, LE_PHY_1M, preferred_mtu); }, diff --git a/system/internal_include/bt_target.h b/system/internal_include/bt_target.h index 24e1cb32e0d..7aeb11a24f0 100644 --- a/system/internal_include/bt_target.h +++ b/system/internal_include/bt_target.h @@ -349,11 +349,6 @@ #define GATT_MAX_APPS 32 /* note: 2 apps used internally GATT and GAP */ #endif -/* connection manager doesn't generate it's own IDs. Instead, all GATT clients - * use their gatt_if to identify against conection manager. When stack tries to - * create l2cap connection, it will use this fixed ID. */ -#define CONN_MGR_ID_L2CAP (GATT_MAX_APPS + 10) - /* This value is used for static allocation of resources. The actual maximum at * runtime is controlled by a system property. */ #ifndef GATT_MAX_PHY_CHANNEL diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index af0dd7a9e22..d9d7f051d95 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -1267,6 +1267,22 @@ tGATT_IF GATT_Register(const Uuid& app_uuid128, const std::string& name, tGATT_C 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(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) { @@ -1281,39 +1297,28 @@ static tGATT_IF GATT_Register_Dynamic(const Uuid& app_uuid128, const std::string eatt_support = true; } - if (gatt_cb.cl_rcb_map.size() >= GATT_CL_RCB_MAX) { + if (gatt_cb.cl_rcb_map.size() >= GATT_IF_MAX) { log::error("Unable to register GATT client, MAX client reached: {}", gatt_cb.cl_rcb_map.size()); return 0; } - uint8_t i_gatt_if = gatt_cb.next_gatt_if; - for (int i = 0; i < GATT_CL_RCB_MAX; i++) { - if (gatt_cb.cl_rcb_map.find(static_cast(i_gatt_if)) == gatt_cb.cl_rcb_map.end()) { - gatt_cb.cl_rcb_map.emplace(i_gatt_if, std::make_unique()); - tGATT_REG* p_reg = gatt_cb.cl_rcb_map[i_gatt_if].get(); - p_reg->app_uuid128 = app_uuid128; - 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(), p_reg->gatt_if, eatt_support); - - gatt_cb.next_gatt_if = (tGATT_IF)(i_gatt_if + 1); - if (gatt_cb.next_gatt_if == 0) { - gatt_cb.next_gatt_if = 1; - } - return p_reg->gatt_if; - } - i_gatt_if++; - if (i_gatt_if == 0) { - i_gatt_if = 1; - } + tGATT_IF gatt_if = GATT_FindNextFreeClRcbId(); + if (gatt_if == GATT_IF_INVALID) { + return gatt_if; } - log::error("Unable to register GATT client, MAX client reached: {}", gatt_cb.cl_rcb_map.size()); - return 0; + auto [it, ret] = gatt_cb.cl_rcb_map.emplace(gatt_if, std::make_unique()); + tGATT_REG* p_reg = it->second.get(); + p_reg->app_uuid128 = app_uuid128; + p_reg->gatt_if = 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(), + p_reg->gatt_if, eatt_support); + + return gatt_if; } /******************************************************************************* diff --git a/system/stack/gatt/gatt_int.h b/system/stack/gatt/gatt_int.h index 10689e39faa..485c7f6a344 100644 --- a/system/stack/gatt/gatt_int.h +++ b/system/stack/gatt/gatt_int.h @@ -415,7 +415,7 @@ typedef struct { fixed_queue_t* srv_chg_clt_q; /* service change clients queue */ tGATT_REG cl_rcb[GATT_MAX_APPS]; - tGATT_IF next_gatt_if; /* potential next gatt if, should be greater than 0 */ + tGATT_IF last_gatt_if; /* last used gatt_if, used to find the next gatt_if easily */ std::unordered_map> cl_rcb_map; /* list of connection link control blocks. diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index 8be24bff58b..bc559a5715c 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -118,8 +118,8 @@ void gatt_init(void) { connection_manager::reset(true); memset(&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG)); - // To catch a potential OOB. - gatt_cb.next_gatt_if = 40; + // To catch a potential OOB, 40>31 is used, any valid value (1 to GATT_IF_MAX) is okay. + gatt_cb.last_gatt_if = static_cast(40); gatt_cb.sign_op_queue = fixed_queue_new(SIZE_MAX); gatt_cb.srv_chg_clt_q = fixed_queue_new(SIZE_MAX); diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index cfd48fbeb48..7e12f30e7da 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -371,7 +371,7 @@ tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if, uint32_t ******************************************************************************/ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, uint8_t* p_data) { - uint8_t *p = p_data, flag, i = 0; + uint8_t *p = p_data, flag; uint32_t trans_id = 0; tGATT_IF gatt_if; tCONN_ID conn_id; @@ -406,7 +406,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, 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 = i; + 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; @@ -414,7 +414,7 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, prep_cnt_it = tcb.prep_cnt_map.erase(prep_cnt_it); } } else { - for (i = 0; i < GATT_MAX_APPS; i++) { + 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); diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index 57dbb6e71aa..72083acb500 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -1529,7 +1529,6 @@ tGATT_READ_MULTI* gatt_sr_get_read_multi(tGATT_TCB& tcb, uint16_t cid) { ******************************************************************************/ void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if, bool is_inc, bool is_reset_first) { - uint8_t idx = ((uint8_t)gatt_if) - 1; tGATT_SR_CMD* sr_cmd_p; if (cid == tcb.att_lcid) { @@ -1549,9 +1548,9 @@ void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if, bo if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) { if (is_inc) { - sr_cmd_p->cback_cnt_map[idx]++; + sr_cmd_p->cback_cnt_map[gatt_if]++; } else { - auto cback_cnt_it = sr_cmd_p->cback_cnt_map.find(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); @@ -1559,6 +1558,8 @@ void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if, bo } } } else { + uint8_t idx = ((uint8_t)gatt_if) - 1; + if (is_inc) { sr_cmd_p->cback_cnt[idx]++; } else { @@ -1980,9 +1981,9 @@ tCONN_ID gatt_create_conn_id(tTCB_IDX tcb_idx, tGATT_IF gatt_if) { return (tcb_idx << 8) | gatt_if; } -tTCB_IDX gatt_get_tcb_idx(tCONN_ID conn_id) { return (uint8_t)(conn_id >> 8); } +tTCB_IDX gatt_get_tcb_idx(tCONN_ID conn_id) { return static_cast(conn_id >> 8); } -tGATT_IF gatt_get_gatt_if(tCONN_ID conn_id) { return (tGATT_IF)conn_id; } +tGATT_IF gatt_get_gatt_if(tCONN_ID conn_id) { return static_cast(conn_id); } uint16_t gatt_get_mtu_pref(const tGATT_REG* p_reg, const RawAddress& bda) { auto mtu_pref = p_reg->mtu_prefs.find(bda); diff --git a/system/stack/include/btm_ble_api_types.h b/system/stack/include/btm_ble_api_types.h index 70b9a4f0fa5..db5ae7a0292 100644 --- a/system/stack/include/btm_ble_api_types.h +++ b/system/stack/include/btm_ble_api_types.h @@ -358,6 +358,14 @@ typedef uint16_t tCONN_ID; typedef uint8_t tGATT_IF; typedef uint8_t tTCB_IDX; +inline constexpr tGATT_IF GATT_IF_INVALID = static_cast(0); +// 0xF1 ~ 0xFF are reserved for special use cases. +inline constexpr tGATT_IF GATT_IF_MAX = static_cast(0xf8); +/* connection manager doesn't generate its own IDs. Instead, all GATT clients + * use their gatt_if to identify against connection manager. When stack tries to + * create l2cap connection, it will use this fixed ID. */ +inline constexpr tGATT_IF CONN_MGR_ID_L2CAP = static_cast(0xf9); + typedef enum : uint8_t { BTM_BLE_DIRECT_CONNECTION = 0x00, BTM_BLE_BKG_CONNECT_ALLOW_LIST = 0x01, diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index 8c6ff8af0bc..a00e0d17f46 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -48,6 +48,7 @@ #include "stack/include/acl_api.h" #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" +#include "stack/include/btm_ble_api_types.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_log_history.h" #include "stack/include/btm_status.h" @@ -924,7 +925,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { } } -/** This function is to initate a direct connection. Returns true if connection +/** This function is to initiate a direct connection. Returns true if connection * initiated, false otherwise. */ bool l2cble_create_conn(tL2C_LCB* p_lcb) { if (!connection_manager::create_le_connection(CONN_MGR_ID_L2CAP, p_lcb->remote_bd_addr)) { -- GitLab From f8e9c6ad92a6c20fbe1a25e655f81cfdeee7a4d0 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Wed, 16 Oct 2024 05:53:13 +0000 Subject: [PATCH 337/875] Fix NPE Flag: EXEMPT, strict null check Bug: 370880377 Test: atest BluetoothOppBtEnablingActivityTest Change-Id: I2ec2ca864a87ebe51da9fd8c328faded0b6231a2 --- .../bluetooth/opp/BluetoothOppBtEnablingActivity.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java index dac2dfd0e08..c1c1251f236 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java @@ -152,9 +152,9 @@ public class BluetoothOppBtEnablingActivity extends AlertActivity { }; private void cancelSendingProgress() { - BluetoothOppManager mOppManager = BluetoothOppManager.getInstance(this); - if (mOppManager.mSendingFlag) { - mOppManager.mSendingFlag = false; + BluetoothOppManager oppManager = BluetoothOppManager.getInstance(this); + if (oppManager != null && oppManager.mSendingFlag) { + oppManager.mSendingFlag = false; } finish(); } -- GitLab From cb076efb9980e8eac0de94bbccd9d41658e9298d Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Thu, 12 Sep 2024 13:23:09 +0000 Subject: [PATCH 338/875] Ignore unrelated cancel bond Flag: com.android.bluetooth.flags.ignore_unrelated_cancel_bond Test: mmm packages/modules/Bluetooth Bug: 366150975 Bug: 365168197 Change-Id: Ife13070e3d32f9869abb0a54cdbce173eb096045 --- .../bluetooth/pairing/PairingTest.java | 58 +++++++++++++++++++ system/btif/src/btif_dm.cc | 6 ++ 2 files changed, 64 insertions(+) diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java index c53dd71130e..c67be9e1bf8 100644 --- a/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java +++ b/framework/tests/bumble/src/android/bluetooth/pairing/PairingTest.java @@ -233,6 +233,64 @@ public class PairingTest { BluetoothDevice.ACTION_BOND_STATE_CHANGED, BluetoothDevice.ACTION_PAIRING_REQUEST); } + /** + * Test a simple BR/EDR just works pairing flow in the follow steps: + * + *

      + *
    1. 1. Bumble resets, enables inquiry and page scan, and sets I/O cap to no display no + * input + *
    2. 2. Android tries to create bond via MAC address, emitting bonding intent + *
    3. 3. Android confirms the pairing via pairing request intent + *
    4. 4. Android cancel the pairing of unrelated device. verify current pairing is continued + * and success. + *
    5. 5. Bumble confirms the pairing internally (optional, added only for test confirmation) + *
    6. 6. Android verifies bonded intent + *
    + */ + @Test + @RequiresFlagsEnabled({Flags.FLAG_IGNORE_UNRELATED_CANCEL_BOND}) + public void testBrEdrPairing_cancelBond_forUnrelatedDevice() { + registerIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, BluetoothDevice.ACTION_PAIRING_REQUEST); + + StreamObserver pairingEventAnswerObserver = + mBumble.security() + .withDeadlineAfter(BOND_INTENT_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS) + .onPairing(mPairingEventStreamObserver); + + assertThat(mBumbleDevice.createBond()).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_PAIRING_REQUEST), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra( + BluetoothDevice.EXTRA_PAIRING_VARIANT, + BluetoothDevice.PAIRING_VARIANT_CONSENT)); + // cancel bonding for unrelated device and verify current pairing continued and success. + BluetoothDevice fakeUnintendedDevice = sAdapter.getRemoteDevice("51:F7:A8:75:17:01"); + assertThat(fakeUnintendedDevice.cancelBondProcess()).isTrue(); + mBumbleDevice.setPairingConfirmation(true); + + PairingEvent pairingEvent = mPairingEventStreamObserver.iterator().next(); + assertThat(pairingEvent.hasJustWorks()).isTrue(); + pairingEventAnswerObserver.onNext( + PairingEventAnswer.newBuilder().setEvent(pairingEvent).setConfirm(true).build()); + + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + + verifyNoMoreInteractions(mReceiver); + + unregisterIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, BluetoothDevice.ACTION_PAIRING_REQUEST); + } + /** * Test a simple BR/EDR just works pairing flow in the follow steps: * diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index a57ad767811..1a31a778a00 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -2503,6 +2503,12 @@ void btif_dm_cancel_bond(const RawAddress bd_addr) { ** 2. special handling for HID devices */ if (is_bonding_or_sdp()) { + if (com::android::bluetooth::flags::ignore_unrelated_cancel_bond() && + (pairing_cb.bd_addr != bd_addr)) { + log::warn("Ignoring bond cancel for unrelated device: {} pairing: {}", bd_addr, + pairing_cb.bd_addr); + return; + } if (pairing_cb.is_ssp) { if (pairing_cb.is_le_only) { BTA_DmBleSecurityGrant(bd_addr, tBTA_DM_BLE_SEC_GRANT::BTA_DM_SEC_PAIR_NOT_SPT); -- GitLab From dc039dbd7da86e7b3e5ea197b5c9849a2482b116 Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Wed, 16 Oct 2024 18:26:34 +0000 Subject: [PATCH 339/875] Flags: Creation of flag for HCI Vendor Specific Extension Bug: 315241296 Test: mma -j32 Flag: com.android.bluetooth.flags.hci_vendor_specific_extension Change-Id: Ib34c930503647e49b5020a3249123029ca4dc731 --- flags/vsc.aconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flags/vsc.aconfig b/flags/vsc.aconfig index fcf8352e941..bd67729689a 100644 --- a/flags/vsc.aconfig +++ b/flags/vsc.aconfig @@ -1,2 +1,10 @@ package: "com.android.bluetooth.flags" container: "com.android.btservices" + +flag { + name: "hci_vendor_specific_extension" + is_exported: true + namespace: "bluetooth" + description: "Vendor-specific Commands/Events extension" + bug: "360925496" +} -- GitLab From c60e011aefebc10da15210da2d8c237ae031de98 Mon Sep 17 00:00:00 2001 From: IHLHO KIM Date: Tue, 15 Oct 2024 01:55:07 +0000 Subject: [PATCH 340/875] Fix wrong parameter order of btm_send_hci_set_scan_params Bug: 323308862 Change-Id: Ie2c0f417e1a697101b0c876a71b6957d179f24aa Test: m -j Flag: EXEMPT, trivial and obvious fix --- system/stack/btm/btm_ble_gap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc index fb0a6c1cedf..9b86ae9eca5 100644 --- a/system/stack/btm/btm_ble_gap.cc +++ b/system/stack/btm/btm_ble_gap.cc @@ -570,7 +570,7 @@ tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration, tBTM_INQ_RESULTS_CB* p_ ? BTM_BLE_SCAN_MODE_ACTI : btm_cb.ble_ctr_cb.inq_var.scan_type; btm_send_hci_set_scan_params(btm_cb.ble_ctr_cb.inq_var.scan_type, (uint16_t)ll_scan_interval, - (uint8_t)scan_phy, (uint16_t)ll_scan_window, + (uint8_t)ll_scan_window, (uint16_t)scan_phy, btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, BTM_BLE_DEFAULT_SFP); -- GitLab From 0a87c513528e7e5e76b0f684fce09e8f45de3c28 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 16 Oct 2024 15:26:24 -0700 Subject: [PATCH 341/875] Utils: remove obsolete & not used method Bug: 311772251 Flag: Exempt refactor - dead code removal and single use method inline Test: atest BluetoothInstrumentationTests Change-Id: I95363f5230f6368d6f33e745a0580eb52a019cca --- .../app/src/com/android/bluetooth/Utils.java | 94 +------------------ .../src/com/android/bluetooth/UtilsTest.java | 68 -------------- 2 files changed, 4 insertions(+), 158 deletions(-) diff --git a/android/app/src/com/android/bluetooth/Utils.java b/android/app/src/com/android/bluetooth/Utils.java index 8c55dd5a903..38bc6db3a91 100644 --- a/android/app/src/com/android/bluetooth/Utils.java +++ b/android/app/src/com/android/bluetooth/Utils.java @@ -78,8 +78,6 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -118,26 +116,8 @@ public final class Utils { /** Thread pool to handle background and outgoing blocking task */ public static final ExecutorService BackgroundExecutor = Executors.newSingleThreadExecutor(); - /* - * Special character - * - * (See "What is a phone number?" doc) - * 'p' --- GSM pause character, same as comma - * 'n' --- GSM wild character - * 'w' --- GSM wait character - */ - public static final char PAUSE = ','; - public static final char WAIT = ';'; public static final String PAIRING_UI_PROPERTY = "bluetooth.pairing_ui_package.name"; - private static boolean isPause(char c) { - return c == 'p' || c == 'P'; - } - - private static boolean isToneWait(char c) { - return c == 'w' || c == 'W'; - } - /** * Check if dual mode audio is enabled. This is set via the system property * persist.bluetooth.enable_dual_mode_audio. @@ -322,12 +302,6 @@ public final class Utils { return byteArrayToLong(valueBuf, 0); } - public static short byteArrayToShort(byte[] valueBuf) { - ByteBuffer converter = ByteBuffer.wrap(valueBuf); - converter.order(ByteOrder.nativeOrder()); - return converter.getShort(); - } - public static int byteArrayToInt(byte[] valueBuf, int offset) { ByteBuffer converter = ByteBuffer.wrap(valueBuf); converter.order(ByteOrder.nativeOrder()); @@ -422,66 +396,6 @@ public final class Utils { return puuids; } - public static String debugGetAdapterStateString(int state) { - switch (state) { - case BluetoothAdapter.STATE_OFF: - return "STATE_OFF"; - case BluetoothAdapter.STATE_ON: - return "STATE_ON"; - case BluetoothAdapter.STATE_TURNING_ON: - return "STATE_TURNING_ON"; - case BluetoothAdapter.STATE_TURNING_OFF: - return "STATE_TURNING_OFF"; - default: - return "UNKNOWN"; - } - } - - public static String ellipsize(String s) { - // Only ellipsize release builds - if (!Build.TYPE.equals("user")) { - return s; - } - if (s == null) { - return null; - } - if (s.length() < 3) { - return s; - } - return s.charAt(0) + "⋯" + s.charAt(s.length() - 1); - } - - public static void copyStream(InputStream is, OutputStream os, int bufferSize) - throws IOException { - if (is != null && os != null) { - byte[] buffer = new byte[bufferSize]; - int bytesRead = 0; - while ((bytesRead = is.read(buffer)) >= 0) { - os.write(buffer, 0, bytesRead); - } - } - } - - public static void safeCloseStream(InputStream is) { - if (is != null) { - try { - is.close(); - } catch (Throwable t) { - Log.d(TAG, "Error closing stream", t); - } - } - } - - public static void safeCloseStream(OutputStream os) { - if (os != null) { - try { - os.close(); - } catch (Throwable t) { - Log.d(TAG, "Error closing stream", t); - } - } - } - static int sSystemUiUid = USER_HANDLE_NULL.getIdentifier(); public static void setSystemUiUid(int uid) { @@ -1162,10 +1076,10 @@ public final class Utils { for (int i = 0; i < len; i++) { char c = phoneNumber.charAt(i); - if (isPause(c)) { - c = PAUSE; - } else if (isToneWait(c)) { - c = WAIT; + if (c == 'p' || c == 'P') { + c = ','; + } else if (c == 'w' || c == 'W') { + c = ';'; } ret.append(c); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java index 3bb77ce585f..9c0661af5e6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java @@ -63,13 +63,6 @@ public class UtilsTest { @Rule public Expect expect = Expect.create(); - @Test - public void byteArrayToShort() { - byte[] valueBuf = new byte[] {0x01, 0x02}; - short s = Utils.byteArrayToShort(valueBuf); - assertThat(s).isEqualTo(0x0201); - } - @Test public void byteArrayToLong() { byte[] valueBuf = @@ -204,67 +197,6 @@ public class UtilsTest { Utils.checkCallerIsSystemOrActiveUser(tag); } - @Test - public void testCopyStream() throws Exception { - byte[] data = new byte[] {1, 2, 3, 4, 5, 6, 7, 8}; - ByteArrayInputStream in = new ByteArrayInputStream(data); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - int bufferSize = 4; - - Utils.copyStream(in, out, bufferSize); - - assertThat(out.toByteArray()).isEqualTo(data); - } - - @Test - public void debugGetAdapterStateString() { - assertThat(Utils.debugGetAdapterStateString(BluetoothAdapter.STATE_OFF)) - .isEqualTo("STATE_OFF"); - assertThat(Utils.debugGetAdapterStateString(BluetoothAdapter.STATE_ON)) - .isEqualTo("STATE_ON"); - assertThat(Utils.debugGetAdapterStateString(BluetoothAdapter.STATE_TURNING_ON)) - .isEqualTo("STATE_TURNING_ON"); - assertThat(Utils.debugGetAdapterStateString(BluetoothAdapter.STATE_TURNING_OFF)) - .isEqualTo("STATE_TURNING_OFF"); - assertThat(Utils.debugGetAdapterStateString(-124)).isEqualTo("UNKNOWN"); - } - - @Test - public void ellipsize() { - if (!Build.TYPE.equals("user")) { - // Only ellipsize release builds - String input = "a_long_string"; - assertThat(Utils.ellipsize(input)).isEqualTo(input); - return; - } - - assertThat(Utils.ellipsize("ab")).isEqualTo("ab"); - assertThat(Utils.ellipsize("abc")).isEqualTo("a⋯c"); - assertThat(Utils.ellipsize(null)).isEqualTo(null); - } - - @Test - public void safeCloseStream_inputStream_doesNotCrash() throws Exception { - InputStream is = mock(InputStream.class); - Utils.safeCloseStream(is); - verify(is).close(); - - Mockito.clearInvocations(is); - doThrow(new IOException()).when(is).close(); - Utils.safeCloseStream(is); - } - - @Test - public void safeCloseStream_outputStream_doesNotCrash() throws Exception { - OutputStream os = mock(OutputStream.class); - Utils.safeCloseStream(os); - verify(os).close(); - - Mockito.clearInvocations(os); - doThrow(new IOException()).when(os).close(); - Utils.safeCloseStream(os); - } - @Test public void truncateUtf8_toZeroLength_isEmpty() { assertThat(Utils.truncateStringForUtf8Storage("abc", 0)).isEmpty(); -- GitLab From fa2e4e26a963822da1dcb0f71f974de9aa286990 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 15 Oct 2024 15:51:20 -0700 Subject: [PATCH 342/875] Battery Profile: rm impossible null handler Use final & injected dependency Update test to TestLooper & truth Split test to actionable smaller test Force test to use disconnecting state Bug: 367133232 Fix: 367133232 Test: atest BluetoothInstrumentationTests:BatteryServiceTest Test: atest BluetoothInstrumentationTests:BatteryStateMachineTest Flag: Exempt refactor no-op Change-Id: Ia0187a77934262303dbf34d2f63f3cc64dc1ecaa --- .../android/bluetooth/bas/BatteryService.java | 135 +++---- .../bluetooth/bas/BatteryStateMachine.java | 337 ++++++---------- .../bluetooth/bas/BatteryServiceTest.java | 277 +++++-------- .../bas/BatteryStateMachineTest.java | 376 +++++++----------- 4 files changed, 402 insertions(+), 723 deletions(-) diff --git a/android/app/src/com/android/bluetooth/bas/BatteryService.java b/android/app/src/com/android/bluetooth/bas/BatteryService.java index ef9537eb9dd..4fd8e190d47 100644 --- a/android/app/src/com/android/bluetooth/bas/BatteryService.java +++ b/android/app/src/com/android/bluetooth/bas/BatteryService.java @@ -16,10 +16,11 @@ package com.android.bluetooth.bas; +import static java.util.Objects.requireNonNull; + import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; -import android.content.Context; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -31,30 +32,45 @@ 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.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; /** A profile service that connects to the Battery service (BAS) of BLE devices */ public class BatteryService extends ProfileService { - private static final String TAG = "BatteryService"; + private static final String TAG = BatteryService.class.getSimpleName(); // Timeout for state machine thread join, to prevent potential ANR. private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1_000; private static BatteryService sBatteryService; - private AdapterService mAdapterService; - private DatabaseManager mDatabaseManager; - private HandlerThread mStateMachinesThread; - private Handler mHandler; + + private final AdapterService mAdapterService; + private final DatabaseManager mDatabaseManager; + private final HandlerThread mStateMachinesThread; + private final Handler mHandler; + + @GuardedBy("mStateMachines") private final Map mStateMachines = new HashMap<>(); - public BatteryService(Context ctx) { - super(ctx); + public BatteryService(AdapterService adapterService) { + this(adapterService, Looper.getMainLooper()); + } + + @VisibleForTesting + BatteryService(AdapterService adapterService, Looper looper) { + super(requireNonNull(adapterService)); + mAdapterService = adapterService; + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); + mHandler = new Handler(requireNonNull(looper)); + + mStateMachinesThread = new HandlerThread("BatteryService.StateMachines"); + mStateMachinesThread.start(); + setBatteryService(this); } public static boolean isEnabled() { @@ -66,38 +82,9 @@ public class BatteryService extends ProfileService { return null; } - @Override - public void start() { - Log.d(TAG, "start()"); - if (sBatteryService != null) { - throw new IllegalStateException("start() called twice"); - } - - mAdapterService = - Objects.requireNonNull( - AdapterService.getAdapterService(), - "AdapterService cannot be null when BatteryService starts"); - mDatabaseManager = - Objects.requireNonNull( - mAdapterService.getDatabase(), - "DatabaseManager cannot be null when BatteryService starts"); - - mHandler = new Handler(Looper.getMainLooper()); - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("BatteryService.StateMachines"); - mStateMachinesThread.start(); - - setBatteryService(this); - } - @Override public void stop() { Log.d(TAG, "stop()"); - if (sBatteryService == null) { - Log.w(TAG, "stop() called before start()"); - return; - } - setBatteryService(null); // Destroy state machines and stop handler thread @@ -109,23 +96,14 @@ public class BatteryService extends ProfileService { mStateMachines.clear(); } - if (mStateMachinesThread != null) { - try { - mStateMachinesThread.quitSafely(); - mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); - mStateMachinesThread = null; - } catch (InterruptedException e) { - // Do not rethrow as we are shutting down anyway - } - } - - // Unregister Handler and stop all queued messages. - if (mHandler != null) { - mHandler.removeCallbacksAndMessages(null); - mHandler = null; + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway } - mAdapterService = null; + mHandler.removeCallbacksAndMessages(null); } @Override @@ -178,7 +156,7 @@ public class BatteryService extends ProfileService { Log.e(TAG, "Cannot connect to " + device + " : no state machine"); return false; } - sm.sendMessage(BatteryStateMachine.CONNECT); + sm.sendMessage(BatteryStateMachine.MESSAGE_CONNECT); } return true; @@ -208,7 +186,7 @@ public class BatteryService extends ProfileService { synchronized (mStateMachines) { BatteryStateMachine sm = getOrCreateStateMachine(device); if (sm != null) { - sm.sendMessage(BatteryStateMachine.DISCONNECT); + sm.sendMessage(BatteryStateMachine.MESSAGE_DISCONNECT); } } @@ -231,12 +209,8 @@ public class BatteryService extends ProfileService { /** * Check whether it can connect to a peer device. The check considers a number of factors during * the evaluation. - * - * @param device the peer device to connect to - * @return true if connection is allowed, otherwise false */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean canConnect(BluetoothDevice device) { + boolean canConnect(BluetoothDevice device) { // Check connectionPolicy and accept or reject the connection. int connectionPolicy = getConnectionPolicy(device); int bondState = mAdapterService.getBondState(device); @@ -255,10 +229,8 @@ public class BatteryService extends ProfileService { } /** Called when the connection state of a state machine is changed */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void handleConnectionStateChanged(BatteryStateMachine sm, int fromState, int toState) { - BluetoothDevice device = sm.getDevice(); - if ((sm == null) || (fromState == toState)) { + void handleConnectionStateChanged(BluetoothDevice device, int fromState, int toState) { + if (fromState == toState) { Log.e( TAG, "connectionStateChanged: unexpected invocation. device=" @@ -366,16 +338,11 @@ public class BatteryService extends ProfileService { } /** Called when the battery level of the device is notified. */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void handleBatteryChanged(BluetoothDevice device, int batteryLevel) { + void handleBatteryChanged(BluetoothDevice device, int batteryLevel) { mAdapterService.setBatteryLevel(device, batteryLevel, /* isBas= */ true); } private BatteryStateMachine getOrCreateStateMachine(BluetoothDevice device) { - if (device == null) { - Log.e(TAG, "getOrCreateGatt failed: device cannot be null"); - return null; - } synchronized (mStateMachines) { BatteryStateMachine sm = mStateMachines.get(device); if (sm != null) { @@ -383,7 +350,7 @@ public class BatteryService extends ProfileService { } Log.d(TAG, "Creating a new state machine for " + device); - sm = BatteryStateMachine.make(device, this, mStateMachinesThread.getLooper()); + sm = new BatteryStateMachine(this, device, mStateMachinesThread.getLooper()); mStateMachines.put(device, sm); return sm; } @@ -394,16 +361,8 @@ public class BatteryService extends ProfileService { mHandler.post(() -> bondStateChanged(device, toState)); } - /** - * Remove state machine if the bonding for a device is removed - * - * @param device the device whose bonding state has changed - * @param bondState the new bond state for the device. Possible values are: {@link - * BluetoothDevice#BOND_NONE}, {@link BluetoothDevice#BOND_BONDING}, {@link - * BluetoothDevice#BOND_BONDED}, {@link BluetoothDevice#ERROR}. - */ - @VisibleForTesting - void bondStateChanged(BluetoothDevice device, int bondState) { + /** Remove state machine if the bonding for a device is removed */ + private void bondStateChanged(BluetoothDevice device, int bondState) { Log.d(TAG, "Bond state changed for device: " + device + " state: " + bondState); // Remove state machine if the bonding for a device is removed if (bondState != BluetoothDevice.BOND_NONE) { @@ -423,16 +382,10 @@ public class BatteryService extends ProfileService { } private void removeStateMachine(BluetoothDevice device) { - if (device == null) { - Log.e(TAG, "removeStateMachine failed: device cannot be null"); - return; - } synchronized (mStateMachines) { BatteryStateMachine sm = mStateMachines.remove(device); if (sm == null) { - Log.w( - TAG, - "removeStateMachine: device " + device + " does not have a state machine"); + Log.w(TAG, "removeStateMachine: " + device + " does not have a state machine"); return; } Log.i(TAG, "removeGatt: removing bluetooth gatt for device: " + device); @@ -444,8 +397,10 @@ public class BatteryService extends ProfileService { @Override public void dump(StringBuilder sb) { super.dump(sb); - for (BatteryStateMachine sm : mStateMachines.values()) { - sm.dump(sb); + synchronized (mStateMachines) { + for (BatteryStateMachine sm : mStateMachines.values()) { + sm.dump(sb); + } } } } diff --git a/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java b/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java index 3995db07782..3038c5ee192 100644 --- a/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java +++ b/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java @@ -20,6 +20,9 @@ import static android.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN; import static android.bluetooth.BluetoothDevice.PHY_LE_1M_MASK; import static android.bluetooth.BluetoothDevice.PHY_LE_2M_MASK; import static android.bluetooth.BluetoothDevice.TRANSPORT_LE; +import static android.bluetooth.BluetoothProfile.getConnectionStateName; + +import static java.util.Objects.requireNonNull; import android.annotation.SuppressLint; import android.bluetooth.BluetoothDevice; @@ -41,13 +44,13 @@ import com.android.internal.util.StateMachine; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; -import java.lang.ref.WeakReference; +import java.time.Duration; import java.util.Scanner; import java.util.UUID; /** It manages Battery service of a BLE device */ public class BatteryStateMachine extends StateMachine { - private static final String TAG = "BatteryStateMachine"; + private static final String TAG = BatteryStateMachine.class.getSimpleName(); static final UUID GATT_BATTERY_SERVICE_UUID = UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb"); @@ -56,13 +59,12 @@ public class BatteryStateMachine extends StateMachine { static final UUID CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); - static final int CONNECT = 1; - static final int DISCONNECT = 2; - static final int CONNECTION_STATE_CHANGED = 3; - private static final int CONNECT_TIMEOUT = 201; + static final int MESSAGE_CONNECT = 1; + static final int MESSAGE_DISCONNECT = 2; + @VisibleForTesting static final int MESSAGE_CONNECTION_STATE_CHANGED = 3; + private static final int MESSAGE_CONNECT_TIMEOUT = 201; - // NOTE: the value is not "final" - it is modified in the unit tests - @VisibleForTesting static int sConnectTimeoutMs = 30000; // 30s + @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(30); private Disconnected mDisconnected; private Connecting mConnecting; @@ -70,16 +72,16 @@ public class BatteryStateMachine extends StateMachine { private Disconnecting mDisconnecting; private int mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; - WeakReference mServiceRef; + private final BatteryService mService; BluetoothGatt mBluetoothGatt; - GattCallback mGattCallback; + private final GattCallback mGattCallback = new GattCallback(); final BluetoothDevice mDevice; - BatteryStateMachine(BluetoothDevice device, BatteryService service, Looper looper) { + BatteryStateMachine(BatteryService service, BluetoothDevice device, Looper looper) { super(TAG, looper); + mService = requireNonNull(service); mDevice = device; - mServiceRef = new WeakReference<>(service); mDisconnected = new Disconnected(); mConnecting = new Connecting(); @@ -92,13 +94,7 @@ public class BatteryStateMachine extends StateMachine { addState(mConnected); setInitialState(mDisconnected); - } - - static BatteryStateMachine make(BluetoothDevice device, BatteryService service, Looper looper) { - Log.i(TAG, "make for device " + device); - BatteryStateMachine sm = new BatteryStateMachine(device, service, looper); - sm.start(); - return sm; + start(); } /** Quits the state machine */ @@ -114,7 +110,6 @@ public class BatteryStateMachine extends StateMachine { if (mBluetoothGatt != null) { mBluetoothGatt.close(); mBluetoothGatt = null; - mGattCallback = null; } } @@ -127,35 +122,13 @@ public class BatteryStateMachine extends StateMachine { } private static String messageWhatToString(int what) { - switch (what) { - case CONNECT: - return "CONNECT"; - case DISCONNECT: - return "DISCONNECT"; - case CONNECTION_STATE_CHANGED: - return "CONNECTION_STATE_CHANGED"; - case CONNECT_TIMEOUT: - return "CONNECT_TIMEOUT"; - default: - break; - } - return Integer.toString(what); - } - - private static String profileStateToString(int state) { - switch (state) { - case BluetoothProfile.STATE_DISCONNECTED: - return "DISCONNECTED"; - case BluetoothProfile.STATE_CONNECTING: - return "CONNECTING"; - case BluetoothProfile.STATE_CONNECTED: - return "CONNECTED"; - case BluetoothProfile.STATE_DISCONNECTING: - return "DISCONNECTING"; - default: - break; - } - return Integer.toString(state); + return switch (what) { + case MESSAGE_CONNECT -> "CONNECT"; + case MESSAGE_DISCONNECT -> "DISCONNECT"; + case MESSAGE_CONNECTION_STATE_CHANGED -> "CONNECTION_STATE_CHANGED"; + case MESSAGE_CONNECT_TIMEOUT -> "CONNECT_TIMEOUT"; + default -> Integer.toString(what); + }; } /** Dumps battery state machine state. */ @@ -181,59 +154,37 @@ public class BatteryStateMachine extends StateMachine { @BluetoothProfile.BtProfileState int getConnectionState() { String currentState = getCurrentState().getName(); - switch (currentState) { - case "Disconnected": - return BluetoothProfile.STATE_DISCONNECTED; - case "Connecting": - return BluetoothProfile.STATE_CONNECTING; - case "Connected": - return BluetoothProfile.STATE_CONNECTED; - case "Disconnecting": - return BluetoothProfile.STATE_DISCONNECTING; - default: + return switch (currentState) { + case "Disconnected" -> BluetoothProfile.STATE_DISCONNECTED; + case "Connecting" -> BluetoothProfile.STATE_CONNECTING; + case "Connected" -> BluetoothProfile.STATE_CONNECTED; + case "Disconnecting" -> BluetoothProfile.STATE_DISCONNECTING; + default -> { Log.e(TAG, "Bad currentState: " + currentState); - return BluetoothProfile.STATE_DISCONNECTED; - } + yield BluetoothProfile.STATE_DISCONNECTED; + } + }; } - void dispatchConnectionStateChanged(int fromState, int toState) { + void dispatchConnectionStateChanged(int toState) { log( - "Connection state " + "Connection state change " + mDevice + ": " - + profileStateToString(fromState) + + getConnectionStateName(mLastConnectionState) + "->" - + profileStateToString(toState)); + + getConnectionStateName(toState)); - BatteryService service = mServiceRef.get(); - if (service != null) { - service.handleConnectionStateChanged(this, fromState, toState); - } + mService.handleConnectionStateChanged(mDevice, mLastConnectionState, toState); } - /** - * Connects to the GATT server of the device. - * - * @return {@code true} if it successfully connects to the GATT server. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + // Allow test to abstract the unmockable mBluetoothGatt + @VisibleForTesting @SuppressLint("AndroidFrameworkRequiresPermission") // We should call internal gatt interface - public boolean connectGatt() { - BatteryService service = mServiceRef.get(); - if (service == null) { - return false; - } - - if (mGattCallback == null) { - mGattCallback = new GattCallback(); - } - if (mBluetoothGatt != null) { - Log.w(TAG, "Trying connectGatt with existing BluetoothGatt instance."); - mBluetoothGatt.close(); - } + boolean connectGatt() { mBluetoothGatt = mDevice.connectGatt( - service, + mService, /* autoConnect= */ false, mGattCallback, TRANSPORT_LE, @@ -243,6 +194,20 @@ public class BatteryStateMachine extends StateMachine { return mBluetoothGatt != null; } + // Allow test to abstract the unmockable BluetoothGatt + @VisibleForTesting + @SuppressLint("AndroidFrameworkRequiresPermission") // We should call internal gatt interface + void disconnectGatt() { + mBluetoothGatt.disconnect(); + } + + // Allow test to abstract the unmockable BluetoothGatt + @VisibleForTesting + @SuppressLint("AndroidFrameworkRequiresPermission") // We should call internal gatt interface + void discoverServicesGatt() { + mBluetoothGatt.discoverServices(); + } + @VisibleForTesting void updateBatteryLevel(byte[] value) { if (value.length == 0) { @@ -250,23 +215,12 @@ public class BatteryStateMachine extends StateMachine { } int batteryLevel = value[0] & 0xFF; - BatteryService service = mServiceRef.get(); - if (service != null) { - service.handleBatteryChanged(mDevice, batteryLevel); - } + mService.handleBatteryChanged(mDevice, batteryLevel); } @VisibleForTesting void resetBatteryLevel() { - BatteryService service = mServiceRef.get(); - if (service != null) { - service.handleBatteryChanged(mDevice, BATTERY_LEVEL_UNKNOWN); - } - } - - @Override - protected void log(String msg) { - super.log(msg); + mService.handleBatteryChanged(mDevice, BATTERY_LEVEL_UNKNOWN); } static void log(String tag, String msg) { @@ -288,26 +242,26 @@ public class BatteryStateMachine extends StateMachine { if (mLastConnectionState != BluetoothProfile.STATE_DISCONNECTED) { // Don't broadcast during startup - dispatchConnectionStateChanged( - mLastConnectionState, BluetoothProfile.STATE_DISCONNECTED); + dispatchConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTED); } + mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; } @Override public void exit() { log(TAG, "Exit (" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; } @Override public boolean processMessage(Message message) { log(TAG, "Process message(" + mDevice + "): " + messageWhatToString(message.what)); - BatteryService service = mServiceRef.get(); switch (message.what) { - case CONNECT: + case MESSAGE_CONNECT -> { log(TAG, "Connecting to " + mDevice); - if (service != null && service.canConnect(mDevice)) { + if (!mService.canConnect(mDevice)) { + Log.w(TAG, "Battery connecting request rejected: " + mDevice); + } else { if (connectGatt()) { transitionTo(mConnecting); } else { @@ -317,34 +271,15 @@ public class BatteryStateMachine extends StateMachine { + "GATT connection rejection: " + mDevice); } - } else { - // Reject the request and stay in Disconnected state - Log.w(TAG, "Battery connecting request rejected: " + mDevice); } - break; - case DISCONNECT: - Log.w(TAG, "DISCONNECT ignored: " + mDevice); - break; - case CONNECTION_STATE_CHANGED: - processConnectionEvent(message.arg1); - break; - default: + } + default -> { + Log.e(TAG, "Unexpected message: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } - - // in Disconnected state - private void processConnectionEvent(int state) { - switch (state) { - case BluetoothGatt.STATE_DISCONNECTED: - Log.w(TAG, "Ignore Battery DISCONNECTED event: " + mDevice); - break; - default: - Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); - break; - } - } } @VisibleForTesting @@ -354,13 +289,13 @@ public class BatteryStateMachine extends StateMachine { @Override public void enter() { log(TAG, "Enter (" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - dispatchConnectionStateChanged(mLastConnectionState, BluetoothProfile.STATE_CONNECTING); + dispatchConnectionStateChanged(BluetoothProfile.STATE_CONNECTING); + mLastConnectionState = BluetoothProfile.STATE_CONNECTING; } @Override public void exit() { log(TAG, "Exit (" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; } @Override @@ -368,25 +303,17 @@ public class BatteryStateMachine extends StateMachine { log(TAG, "process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - Log.w(TAG, "CONNECT ignored: " + mDevice); - break; - case CONNECT_TIMEOUT: - Log.e(TAG, "Connection timeout unexpected: " + mDevice); - break; - case DISCONNECT: + case MESSAGE_DISCONNECT -> { log(TAG, "Connection canceled to " + mDevice); - if (mBluetoothGatt != null) { - mBluetoothGatt.disconnect(); - } + disconnectGatt(); // As we're not yet connected we don't need to wait for callbacks. transitionTo(mDisconnected); - break; - case CONNECTION_STATE_CHANGED: - processConnectionEvent(message.arg1); - break; - default: + } + case MESSAGE_CONNECTION_STATE_CHANGED -> processConnectionEvent(message.arg1); + default -> { + Log.e(TAG, "Unexpected message: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } @@ -394,16 +321,12 @@ public class BatteryStateMachine extends StateMachine { // in Connecting state private void processConnectionEvent(int state) { switch (state) { - case BluetoothGatt.STATE_DISCONNECTED: + case BluetoothProfile.STATE_DISCONNECTED -> { Log.w(TAG, "Device disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case BluetoothGatt.STATE_CONNECTED: - transitionTo(mConnected); - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; + } + case BluetoothProfile.STATE_CONNECTED -> transitionTo(mConnected); + default -> Log.e(TAG, "Incorrect state: " + state); } } } @@ -415,16 +338,15 @@ public class BatteryStateMachine extends StateMachine { @Override public void enter() { log(TAG, "Enter (" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - dispatchConnectionStateChanged( - mLastConnectionState, BluetoothProfile.STATE_DISCONNECTING); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + dispatchConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTING); + mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; } @Override public void exit() { log(TAG, "Exit (" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override @@ -432,23 +354,17 @@ public class BatteryStateMachine extends StateMachine { log(TAG, "Process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { - // TODO: Check if connect while disconnecting is okay. - // It is related to CONNECT_TIMEOUT as well. - case CONNECT: - Log.w(TAG, "CONNECT ignored: " + mDevice); - break; - case DISCONNECT: - Log.w(TAG, "DISCONNECT ignored: " + mDevice); - break; - case CONNECT_TIMEOUT: - Log.w(TAG, "Connection timeout: " + mDevice); + case MESSAGE_CONNECT_TIMEOUT -> { + Log.w(TAG, "Disconnection timeout: " + mDevice); transitionTo(mDisconnected); - break; - case CONNECTION_STATE_CHANGED: + } + case MESSAGE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(message.arg1); - break; - default: + } + default -> { + Log.e(TAG, "Unexpected message: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } @@ -456,24 +372,21 @@ public class BatteryStateMachine extends StateMachine { // in Disconnecting state private void processConnectionEvent(int state) { switch (state) { - case BluetoothGatt.STATE_DISCONNECTED: + case BluetoothProfile.STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case BluetoothGatt.STATE_CONNECTED: - { - // Reject the connection and stay in Disconnecting state - Log.w(TAG, "Incoming Battery connected request rejected: " + mDevice); - if (mBluetoothGatt != null) { - mBluetoothGatt.disconnect(); - } else { - transitionTo(mDisconnected); - } - break; - } - default: + } + case BluetoothProfile.STATE_CONNECTED -> { + // TODO: Check if connect while disconnecting is okay. It is related to + // MESSAGE_CONNECT_TIMEOUT as well. + + // Reject the connection and stay in Disconnecting state + Log.w(TAG, "Incoming Battery connected request rejected: " + mDevice); + disconnectGatt(); + } + default -> { Log.e(TAG, "Incorrect state: " + state); - break; + } } } } @@ -485,11 +398,10 @@ public class BatteryStateMachine extends StateMachine { @Override public void enter() { log(TAG, "Enter (" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - dispatchConnectionStateChanged(mLastConnectionState, BluetoothProfile.STATE_CONNECTED); + dispatchConnectionStateChanged(BluetoothProfile.STATE_CONNECTED); + mLastConnectionState = BluetoothProfile.STATE_CONNECTED; - if (mBluetoothGatt != null) { - mBluetoothGatt.discoverServices(); - } + discoverServicesGatt(); } @Override @@ -497,7 +409,6 @@ public class BatteryStateMachine extends StateMachine { log(TAG, "Exit (" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); // Reset the battery level only after connected resetBatteryLevel(); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; } @Override @@ -505,23 +416,18 @@ public class BatteryStateMachine extends StateMachine { log(TAG, "Process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - Log.w(TAG, "CONNECT ignored: " + mDevice); - break; - case DISCONNECT: + case MESSAGE_DISCONNECT -> { log(TAG, "Disconnecting from " + mDevice); - if (mBluetoothGatt != null) { - mBluetoothGatt.disconnect(); - transitionTo(mDisconnecting); - } else { - transitionTo(mDisconnected); - } - break; - case CONNECTION_STATE_CHANGED: + disconnectGatt(); + transitionTo(mDisconnecting); + } + case MESSAGE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(message.arg1); - break; - default: + } + default -> { + Log.e(TAG, "Unexpected message: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } @@ -529,16 +435,13 @@ public class BatteryStateMachine extends StateMachine { // in Connected state private void processConnectionEvent(int state) { switch (state) { - case BluetoothGatt.STATE_DISCONNECTED: + case BluetoothProfile.STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected from " + mDevice); transitionTo(mDisconnected); - break; - case BluetoothGatt.STATE_CONNECTED: - Log.w(TAG, "Ignore CONNECTED event: " + mDevice); - break; - default: + } + default -> { Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state); - break; + } } } } @@ -546,7 +449,7 @@ public class BatteryStateMachine extends StateMachine { final class GattCallback extends BluetoothGattCallback { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - sendMessage(CONNECTION_STATE_CHANGED, newState); + sendMessage(MESSAGE_CONNECTION_STATE_CHANGED, newState); } @Override diff --git a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java index ddb36153ff8..97354f95d24 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java @@ -16,27 +16,33 @@ package com.android.bluetooth.bas; +import static android.bluetooth.BluetoothDevice.BOND_BONDED; +import static android.bluetooth.BluetoothDevice.BOND_BONDING; +import static android.bluetooth.BluetoothDevice.BOND_NONE; +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 com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; -import android.content.Context; -import android.os.Looper; import android.os.ParcelUuid; +import android.os.test.TestLooper; -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.LargeTest; +import androidx.test.filters.MediumTest; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -46,239 +52,136 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import java.util.concurrent.TimeoutException; +import java.util.List; -@LargeTest +@MediumTest @RunWith(JUnit4.class) public class BatteryServiceTest { - private BluetoothAdapter mAdapter; - private Context mTargetContext; - private BatteryService mService; - private BluetoothDevice mDevice; - private static final int CONNECTION_TIMEOUT_MS = 1000; + @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; - @Rule public final MockitoRule mockito = MockitoJUnit.rule(); + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 78); + + private BatteryService mService; + private TestLooper mLooper; @Before - public void setUp() throws Exception { - mTargetContext = InstrumentationRegistry.getTargetContext(); - if (Looper.myLooper() == null) { - Looper.prepare(); - } + public void setUp() { + mLooper = new TestLooper(); - TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); + doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService).getBondState(any()); - mAdapter = BluetoothAdapter.getDefaultAdapter(); - - startService(); - - // Override the timeout value to speed up the test - BatteryStateMachine.sConnectTimeoutMs = CONNECTION_TIMEOUT_MS; // 1s - - // Get a device for testing - mDevice = TestUtils.getTestDevice(mAdapter, 0); - doReturn(BluetoothDevice.BOND_BONDED) - .when(mAdapterService) - .getBondState(any(BluetoothDevice.class)); + mService = new BatteryService(mAdapterService, mLooper.getLooper()); + mService.setAvailable(true); } @After - public void tearDown() throws Exception { - stopService(); - TestUtils.clearAdapterService(mAdapterService); - } - - private void startService() throws TimeoutException { - mService = new BatteryService(mTargetContext); - mService.start(); - mService.setAvailable(true); + public void tearDown() { + // To prevent double stop + if (BatteryService.getBatteryService() != null) { + mService.stop(); + } + assertThat(BatteryService.getBatteryService()).isNull(); } - private void stopService() throws TimeoutException { - mService.stop(); - mService = BatteryService.getBatteryService(); - Assert.assertNull(mService); + @Test + public void getBatteryService() { + assertThat(BatteryService.getBatteryService()).isEqualTo(mService); } - /** Test get Battery Service */ @Test - public void testGetBatteryService() { - Assert.assertEquals(mService, BatteryService.getBatteryService()); + public void setConnectionPolicy() { + assertThat(mService.setConnectionPolicy(mDevice, CONNECTION_POLICY_FORBIDDEN)).isTrue(); } - /** Test get/set policy for BluetoothDevice */ @Test - public void testGetSetPolicy() { - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.BATTERY)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - Assert.assertEquals( - "Initial device policy", - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - mService.getConnectionPolicy(mDevice)); - - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.BATTERY)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - Assert.assertEquals( - "Setting device policy to POLICY_FORBIDDEN", - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - mService.getConnectionPolicy(mDevice)); - - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.BATTERY)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - Assert.assertEquals( - "Setting device policy to POLICY_ALLOWED", - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - mService.getConnectionPolicy(mDevice)); + public void getConnectionPolicy() { + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.getConnectionPolicy(mDevice)).isEqualTo(policy); + } } - /** Test if getProfileConnectionPolicy works after the service is stopped. */ @Test - public void testGetPolicyAfterStopped() { - mService.stop(); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.BATTERY)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - Assert.assertEquals( - "Initial device policy", - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - mService.getConnectionPolicy(mDevice)); + public void canConnect_whenNotBonded_returnFalse() { + int badPolicyValue = 1024; + int badBondState = 42; + for (int bondState : List.of(BOND_NONE, BOND_BONDING, badBondState)) { + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED, + badPolicyValue)) { + doReturn(bondState).when(mAdapterService).getBondState(any()); + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.canConnect(mDevice)).isEqualTo(false); + } + } } - /** Test okToConnect method using various test cases */ @Test - public void testCanConnect() { + public void canConnect_whenBonded() { int badPolicyValue = 1024; - int badBondState = 42; - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testCanConnectCase(mDevice, BluetoothDevice.BOND_NONE, badPolicyValue, false); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testCanConnectCase(mDevice, BluetoothDevice.BOND_BONDING, badPolicyValue, false); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - true); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testCanConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - true); - testCanConnectCase(mDevice, BluetoothDevice.BOND_BONDED, badPolicyValue, false); - testCanConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, false); - testCanConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, false); - testCanConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_ALLOWED, false); - testCanConnectCase(mDevice, badBondState, badPolicyValue, false); + doReturn(BOND_BONDED).when(mAdapterService).getBondState(any()); + + for (int policy : List.of(CONNECTION_POLICY_FORBIDDEN, badPolicyValue)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.canConnect(mDevice)).isEqualTo(false); + } + for (int policy : List.of(CONNECTION_POLICY_UNKNOWN, CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.canConnect(mDevice)).isEqualTo(true); + } } - /** Test that an outgoing connection to device */ @Test - public void testConnectAndDump() { - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.BATTERY)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - // Return Battery UUID + public void connectAndDump_doesNotCrash() { + doReturn(CONNECTION_POLICY_ALLOWED) + .when(mDatabaseManager) + .getProfileConnectionPolicy(any(), anyInt()); + doReturn(new ParcelUuid[] {BluetoothUuid.BATTERY}) .when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - // Send a connect request - Assert.assertTrue("Connect expected to succeed", mService.connect(mDevice)); - // Test dump() is not crashed. + assertThat(mService.connect(mDevice)).isTrue(); + mService.dump(new StringBuilder()); } - /** Test that an outgoing connection to device with POLICY_FORBIDDEN is rejected */ @Test - public void testForbiddenPolicy_FailsToConnect() { - // Set the device policy to POLICY_FORBIDDEN so connect() should fail - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.BATTERY)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - - // Send a connect request - Assert.assertFalse("Connect expected to fail", mService.connect(mDevice)); + public void connect_whenForbiddenPolicy_FailsToConnect() { + doReturn(CONNECTION_POLICY_FORBIDDEN) + .when(mDatabaseManager) + .getProfileConnectionPolicy(any(), anyInt()); + + assertThat(mService.connect(mDevice)).isFalse(); } @Test public void getConnectionState_whenNoDevicesAreConnected_returnsDisconnectedState() { - Assert.assertEquals( - mService.getConnectionState(mDevice), BluetoothProfile.STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); } @Test public void getDevices_whenNoDevicesAreConnected_returnsEmptyList() { - Assert.assertTrue(mService.getDevices().isEmpty()); + assertThat(mService.getDevices()).isEmpty(); } @Test public void getDevicesMatchingConnectionStates() { - when(mAdapterService.getBondedDevices()).thenReturn(new BluetoothDevice[] {mDevice}); - int states[] = new int[] {BluetoothProfile.STATE_DISCONNECTED}; - - Assert.assertTrue(mService.getDevicesMatchingConnectionStates(states).contains(mDevice)); - } - - @Test - public void setConnectionPolicy() { - Assert.assertTrue( - mService.setConnectionPolicy( - mDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)); - } + doReturn(new BluetoothDevice[] {mDevice}).when(mAdapterService).getBondedDevices(); + int[] states = new int[] {STATE_DISCONNECTED}; - /** - * Helper function to test okToConnect() method - * - * @param device test device - * @param bondState bond state value, could be invalid - * @param policy value, could be invalid - * @param expected expected result from okToConnect() - */ - private void testCanConnectCase( - BluetoothDevice device, int bondState, int policy, boolean expected) { - doReturn(bondState).when(mAdapterService).getBondState(device); - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.BATTERY)) - .thenReturn(policy); - Assert.assertEquals(expected, mService.canConnect(device)); + assertThat(mService.getDevicesMatchingConnectionStates(states)).containsExactly(mDevice); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java index e35b68ec801..2a3bc53c944 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java @@ -17,36 +17,32 @@ package com.android.bluetooth.bas; import static android.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN; -import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; + +import static com.android.bluetooth.bas.BatteryStateMachine.MESSAGE_CONNECT; +import static com.android.bluetooth.bas.BatteryStateMachine.MESSAGE_CONNECTION_STATE_CHANGED; +import static com.android.bluetooth.bas.BatteryStateMachine.MESSAGE_DISCONNECT; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.after; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.timeout; +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.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothProfile; -import android.os.HandlerThread; import android.os.Looper; +import android.os.test.TestLooper; -import androidx.test.filters.LargeTest; +import androidx.test.filters.SmallTest; import com.android.bluetooth.TestUtils; -import com.android.bluetooth.btservice.AdapterService; -import org.hamcrest.core.IsInstanceOf; -import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -56,221 +52,166 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -@LargeTest +@SmallTest @RunWith(JUnit4.class) public class BatteryStateMachineTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); - private BluetoothAdapter mAdapter; - private HandlerThread mHandlerThread; - private StubBatteryStateMachine mBatteryStateMachine; - private static final int CONNECTION_TIMEOUT_MS = 1_000; - private static final int TIMEOUT_MS = 2_000; - private static final int WAIT_MS = 1_000; - - private BluetoothDevice mTestDevice; - @Mock private AdapterService mAdapterService; @Mock private BatteryService mBatteryService; - @Before - public void setUp() throws Exception { - TestUtils.setAdapterService(mAdapterService); + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 93); + + private TestLooper mLooper; + private FakeBatteryStateMachine mBatteryStateMachine; - mAdapter = BluetoothAdapter.getDefaultAdapter(); + @Before + public void setUp() { + doReturn(true).when(mBatteryService).canConnect(any()); - // Get a device for testing - mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); + mLooper = new TestLooper(); - // Set up thread and looper - mHandlerThread = new HandlerThread("BatteryStateMachineTestHandlerThread"); - mHandlerThread.start(); mBatteryStateMachine = - new StubBatteryStateMachine( - mTestDevice, mBatteryService, mHandlerThread.getLooper()); - // Override the timeout value to speed up the test - mBatteryStateMachine.sConnectTimeoutMs = CONNECTION_TIMEOUT_MS; - mBatteryStateMachine.start(); + new FakeBatteryStateMachine(mBatteryService, mDevice, mLooper.getLooper()); + mBatteryStateMachine.mShouldAllowGatt = true; } - @After - public void tearDown() throws Exception { - mBatteryStateMachine.doQuit(); - mHandlerThread.quit(); - TestUtils.clearAdapterService(mAdapterService); - reset(mBatteryService); + @Test + public void initialState_isDisconnected() { + assertThat(mBatteryStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } - /** Test that default state is disconnected */ @Test - public void testDefaultDisconnectedState() { - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mBatteryStateMachine.getConnectionState()); - } + public void connect_whenNotAllowed_stayDisconnected() { + doReturn(false).when(mBatteryService).canConnect(any()); + + sendAndDispatchMessage(MESSAGE_CONNECT); - /** - * Allow/disallow connection to any device. - * - * @param allow if true, connection is allowed - */ - private void allowConnection(boolean allow) { - when(mBatteryService.canConnect(any(BluetoothDevice.class))).thenReturn(allow); + verify(mBatteryService, never()).handleConnectionStateChanged(any(), anyInt(), anyInt()); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Disconnected.class); } - private void allowConnectGatt(boolean allow) { - mBatteryStateMachine.mShouldAllowGatt = allow; + @Test + public void connect_whenGattCanNotConnect_stayDisconnected() { + mBatteryStateMachine.mShouldAllowGatt = false; + + sendAndDispatchMessage(MESSAGE_CONNECT); + + verify(mBatteryService, never()).handleConnectionStateChanged(any(), anyInt(), anyInt()); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Disconnected.class); } - /** Test that an incoming connection with policy forbidding connection is rejected */ @Test - public void testOkToConnectFails() { - allowConnection(false); - allowConnectGatt(true); + public void connect_successCase_isConnected() { + sendAndDispatchMessage(MESSAGE_CONNECT); - // Inject an event for when incoming connection is requested - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECT); + verify(mBatteryService) + .handleConnectionStateChanged(any(), eq(STATE_DISCONNECTED), eq(STATE_CONNECTING)); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Connecting.class); - verify(mBatteryService, after(WAIT_MS).never()) - .handleConnectionStateChanged(any(BatteryStateMachine.class), anyInt(), anyInt()); + sendAndDispatchMessage(MESSAGE_CONNECTION_STATE_CHANGED, STATE_CONNECTED); - // Check that we are in Disconnected state - Assert.assertThat( - mBatteryStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BatteryStateMachine.Disconnected.class)); + verify(mBatteryService) + .handleConnectionStateChanged(any(), eq(STATE_CONNECTING), eq(STATE_CONNECTED)); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Connected.class); } @Test - public void testFailToConnectGatt() { - allowConnection(true); - allowConnectGatt(false); + public void disconnect_whenConnecting_isDisconnected() { + sendAndDispatchMessage(MESSAGE_CONNECT); - // Inject an event for when incoming connection is requested - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECT); + verify(mBatteryService) + .handleConnectionStateChanged(any(), eq(STATE_DISCONNECTED), eq(STATE_CONNECTING)); - verify(mBatteryService, after(WAIT_MS).never()) - .handleConnectionStateChanged(any(BatteryStateMachine.class), anyInt(), anyInt()); + sendAndDispatchMessage(MESSAGE_DISCONNECT); - // Check that we are in Disconnected state - Assert.assertThat( - mBatteryStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BatteryStateMachine.Disconnected.class)); - assertNull(mBatteryStateMachine.mBluetoothGatt); + verify(mBatteryService) + .handleConnectionStateChanged(any(), eq(STATE_CONNECTING), eq(STATE_DISCONNECTED)); } - @Test - public void testSuccessfullyConnected() { - allowConnection(true); - allowConnectGatt(true); - - // Inject an event for when incoming connection is requested - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECT); - - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleConnectionStateChanged( - any(BatteryStateMachine.class), - eq(BluetoothProfile.STATE_DISCONNECTED), - eq(BluetoothProfile.STATE_CONNECTING)); - - Assert.assertThat( - mBatteryStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BatteryStateMachine.Connecting.class)); - - assertNotNull(mBatteryStateMachine.mGattCallback); - mBatteryStateMachine.notifyConnectionStateChanged( - GATT_SUCCESS, BluetoothProfile.STATE_CONNECTED); - - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleConnectionStateChanged( - any(BatteryStateMachine.class), - eq(BluetoothProfile.STATE_CONNECTING), - eq(BluetoothProfile.STATE_CONNECTED)); - - Assert.assertThat( - mBatteryStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BatteryStateMachine.Connected.class)); + private void goToStateConnected() { + sendAndDispatchMessage(MESSAGE_CONNECT); + sendAndDispatchMessage(MESSAGE_CONNECTION_STATE_CHANGED, STATE_CONNECTED); } @Test - public void testDisconnectBeforeConnected() { - allowConnection(true); - allowConnectGatt(true); + public void connect_whenConnected_doNothing() { + goToStateConnected(); - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECT); + sendAndDispatchMessage(MESSAGE_CONNECT); - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleConnectionStateChanged( - any(BatteryStateMachine.class), - eq(BluetoothProfile.STATE_DISCONNECTED), - eq(BluetoothProfile.STATE_CONNECTING)); - - mBatteryStateMachine.sendMessage(BatteryStateMachine.DISCONNECT); - - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleConnectionStateChanged( - any(BatteryStateMachine.class), - eq(BluetoothProfile.STATE_CONNECTING), - eq(BluetoothProfile.STATE_DISCONNECTED)); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Connected.class); } @Test - public void testConnectedStateChanges() { - allowConnection(true); - allowConnectGatt(true); + public void disconnect_whenConnected_isDisconnected() { + goToStateConnected(); - // Connected -> CONNECT - reconnect(); + sendAndDispatchMessage(MESSAGE_DISCONNECT); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Disconnecting.class); - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECT); + sendAndDispatchMessage(MESSAGE_CONNECTION_STATE_CHANGED, STATE_DISCONNECTED); assertThat(mBatteryStateMachine.getCurrentState()) - .isInstanceOf(BatteryStateMachine.Connected.class); - - // Connected -> DISCONNECT - reconnect(); + .isInstanceOf(BatteryStateMachine.Disconnected.class); + } - mBatteryStateMachine.sendMessage(BatteryStateMachine.DISCONNECT); + @Test + public void disconnectWithTimeout_whenConnected_isDisconnected() { + goToStateConnected(); - TestUtils.waitForLooperToFinishScheduledTask(mBatteryStateMachine.getHandler().getLooper()); + sendAndDispatchMessage(MESSAGE_DISCONNECT); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Disconnecting.class); - mBatteryStateMachine.notifyConnectionStateChanged( - GATT_SUCCESS, BluetoothProfile.STATE_DISCONNECTED); + mLooper.moveTimeForward(BatteryStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); assertThat(mBatteryStateMachine.getCurrentState()) .isInstanceOf(BatteryStateMachine.Disconnected.class); + } - // Connected -> STATE_DISCONNECTED - reconnect(); - - mBatteryStateMachine.sendMessage( - BatteryStateMachine.CONNECTION_STATE_CHANGED, BluetoothGatt.STATE_DISCONNECTED); + @Test + public void disconnectNotification_whenConnected_isDisconnected() { + goToStateConnected(); - TestUtils.waitForLooperToFinishScheduledTask(mBatteryStateMachine.getHandler().getLooper()); + sendAndDispatchMessage(MESSAGE_CONNECTION_STATE_CHANGED, STATE_DISCONNECTED); - mBatteryStateMachine.notifyConnectionStateChanged( - GATT_SUCCESS, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Disconnected.class); + } - // Connected -> STATE_CONNECTED - reconnect(); + @Test + public void connectNotification_whenConnected_stayConnected() { + goToStateConnected(); - mBatteryStateMachine.sendMessage( - BatteryStateMachine.CONNECTION_STATE_CHANGED, BluetoothGatt.STATE_CONNECTED); + sendAndDispatchMessage(MESSAGE_CONNECTION_STATE_CHANGED, STATE_CONNECTED); assertThat(mBatteryStateMachine.getCurrentState()) .isInstanceOf(BatteryStateMachine.Connected.class); + } - // Connected -> ILLEGAL_STATE - reconnect(); + @Test + public void unknownStateNotification_whenConnected_stayConnected() { + goToStateConnected(); - int badState = -1; - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECTION_STATE_CHANGED, badState); + sendAndDispatchMessage(MESSAGE_CONNECTION_STATE_CHANGED, -1); assertThat(mBatteryStateMachine.getCurrentState()) .isInstanceOf(BatteryStateMachine.Connected.class); + } - // Connected -> NOT_HANDLED - reconnect(); + @Test + public void unknownMessage_whenConnected_stayConnected() { + goToStateConnected(); - int notHandled = -1; - mBatteryStateMachine.sendMessage(notHandled); + sendAndDispatchMessage(12312); assertThat(mBatteryStateMachine.getCurrentState()) .isInstanceOf(BatteryStateMachine.Connected.class); @@ -278,97 +219,74 @@ public class BatteryStateMachineTest { @Test public void testBatteryLevelChanged() { - allowConnection(true); - allowConnectGatt(true); - mBatteryStateMachine.updateBatteryLevel(new byte[] {(byte) 0x30}); - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleBatteryChanged(any(BluetoothDevice.class), eq(0x30)); + verify(mBatteryService).handleBatteryChanged(any(BluetoothDevice.class), eq(0x30)); } @Test public void testEmptyBatteryLevelIgnored() { - allowConnection(true); - allowConnectGatt(true); - mBatteryStateMachine.updateBatteryLevel(new byte[0]); - verify(mBatteryService, after(WAIT_MS).never()) - .handleBatteryChanged(any(BluetoothDevice.class), anyInt()); + verify(mBatteryService, never()).handleBatteryChanged(any(), anyInt()); } @Test public void testDisconnectResetBatteryLevel() { - allowConnection(true); - allowConnectGatt(true); - - // Inject an event for when incoming connection is requested - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECT); - - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleConnectionStateChanged( - any(BatteryStateMachine.class), - eq(BluetoothProfile.STATE_DISCONNECTED), - eq(BluetoothProfile.STATE_CONNECTING)); - - Assert.assertThat( - mBatteryStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BatteryStateMachine.Connecting.class)); - - mBatteryStateMachine.notifyConnectionStateChanged( - GATT_SUCCESS, BluetoothProfile.STATE_CONNECTED); - - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleConnectionStateChanged( - any(BatteryStateMachine.class), - eq(BluetoothProfile.STATE_CONNECTING), - eq(BluetoothProfile.STATE_CONNECTED)); - - Assert.assertThat( - mBatteryStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BatteryStateMachine.Connected.class)); - // update the battery level - mBatteryStateMachine.updateBatteryLevel(new byte[] {(byte) 0x30}); - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleBatteryChanged(any(BluetoothDevice.class), eq(0x30)); + sendAndDispatchMessage(MESSAGE_CONNECT); - // Disconnect should reset the battery level - mBatteryStateMachine.sendMessage(BatteryStateMachine.DISCONNECT); - verify(mBatteryService, timeout(TIMEOUT_MS)) - .handleBatteryChanged(any(BluetoothDevice.class), eq(BATTERY_LEVEL_UNKNOWN)); - } + verify(mBatteryService) + .handleConnectionStateChanged(any(), eq(STATE_DISCONNECTED), eq(STATE_CONNECTING)); - private void reconnect() { - // Inject an event for when incoming connection is requested - mBatteryStateMachine.sendMessage(BatteryStateMachine.CONNECT); + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Connecting.class); + + sendAndDispatchMessage(MESSAGE_CONNECTION_STATE_CHANGED, STATE_CONNECTED); + + verify(mBatteryService) + .handleConnectionStateChanged(any(), eq(STATE_CONNECTING), eq(STATE_CONNECTED)); + + assertThat(mBatteryStateMachine.getCurrentState()) + .isInstanceOf(BatteryStateMachine.Connected.class); + + mBatteryStateMachine.updateBatteryLevel(new byte[] {(byte) 0x30}); + verify(mBatteryService).handleBatteryChanged(any(), eq(0x30)); - TestUtils.waitForLooperToFinishScheduledTask(mBatteryStateMachine.getHandler().getLooper()); + sendAndDispatchMessage(MESSAGE_DISCONNECT); + verify(mBatteryService).handleBatteryChanged(any(), eq(BATTERY_LEVEL_UNKNOWN)); + } - mBatteryStateMachine.notifyConnectionStateChanged( - GATT_SUCCESS, BluetoothProfile.STATE_CONNECTED); + private void sendAndDispatchMessage(int what, int arg1) { + mBatteryStateMachine.sendMessage(what, arg1); + mLooper.dispatchAll(); + } - TestUtils.waitForLooperToFinishScheduledTask(mBatteryStateMachine.getHandler().getLooper()); + private void sendAndDispatchMessage(int what) { + mBatteryStateMachine.sendMessage(what); + mLooper.dispatchAll(); } - // It simulates GATT connection for testing. - private static class StubBatteryStateMachine extends BatteryStateMachine { + // Simulates GATT connection for testing. + private static class FakeBatteryStateMachine extends BatteryStateMachine { boolean mShouldAllowGatt = true; - StubBatteryStateMachine(BluetoothDevice device, BatteryService service, Looper looper) { - super(device, service, looper); + FakeBatteryStateMachine(BatteryService service, BluetoothDevice device, Looper looper) { + super(service, device, looper); } @Override - public boolean connectGatt() { - mGattCallback = new GattCallback(); + boolean connectGatt() { return mShouldAllowGatt; } - public void notifyConnectionStateChanged(int status, int newState) { - if (mGattCallback != null) { - mGattCallback.onConnectionStateChange(mBluetoothGatt, status, newState); - } + @Override + void disconnectGatt() { + // Do nothing as there is no BluetoothGatt available during test + } + + @Override + void discoverServicesGatt() { + // Do nothing as there is no BluetoothGatt available during test } } } -- GitLab From fc5f60773b7077c38df161e735c40feb5ba37118 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 16 Oct 2024 17:55:30 -0700 Subject: [PATCH 343/875] Flags 24Q3: Remove a2dp_async_allow_low_latency Bug: 339368380 Flag: com.android.bluetooth.flags.a2dp_async_allow_low_latency Test: m com.android.btservices Change-Id: Ie52a718d3a3203f75767eb69f63bd7fe5b22ec43 --- flags/a2dp.aconfig | 10 ---------- system/btif/src/bluetooth.cc | 8 ++------ 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/flags/a2dp.aconfig b/flags/a2dp.aconfig index 195573beea6..2026a474461 100644 --- a/flags/a2dp.aconfig +++ b/flags/a2dp.aconfig @@ -31,16 +31,6 @@ flag { } } -flag { - name: "a2dp_async_allow_low_latency" - namespace: "bluetooth" - description: "Make allow_low_latency run on main thread" - bug : "339368380" - metadata { - purpose: PURPOSE_BUGFIX - } -} - flag { name: "a2dp_ignore_started_when_responder" namespace: "bluetooth" diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 786c7e11ed5..b8ee97ec091 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -1118,12 +1118,8 @@ static int set_dynamic_audio_buffer_size(int codec, int size) { static bool allow_low_latency_audio(bool allowed, const RawAddress& /* address */) { log::info("{}", allowed); - if (com::android::bluetooth::flags::a2dp_async_allow_low_latency()) { - do_in_main_thread( - base::BindOnce(bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed, allowed)); - } else { - bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed(allowed); - } + do_in_main_thread( + base::BindOnce(bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed, allowed)); return true; } -- GitLab From 392e1aff1d28c7eaac16edd837ac0c499b5130a7 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 16 Oct 2024 18:07:34 -0700 Subject: [PATCH 344/875] btif_a2dp_source: Run a2dp::set_audio_low_latency_mode_allowed on bt_a2dp_source_worker_thread a2dp::cleanup is run from bt_a2dp_source_worker_thread and executing a2dp::set_audio_low_latency_mode_allowed on a different thread will open a potential data race. Bug: 329537023 Test: m com.android.btservices Flag: EXEMPT, minor bugfix Change-Id: I164532c642b26a8cd73d14d6acc4a9e102298896 --- system/btif/include/btif_a2dp_source.h | 3 +++ system/btif/src/bluetooth.cc | 5 ++--- system/btif/src/btif_a2dp_source.cc | 8 ++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/system/btif/include/btif_a2dp_source.h b/system/btif/include/btif_a2dp_source.h index 4062a5413ee..bea43944507 100644 --- a/system/btif/include/btif_a2dp_source.h +++ b/system/btif/include/btif_a2dp_source.h @@ -56,6 +56,9 @@ bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address, // streaming session for |peer_address|. bool btif_a2dp_source_end_session(const RawAddress& peer_address); +// Update allowed low latency modes for the active session. +void btif_a2dp_source_allow_low_latency_audio(bool allowed); + // Shutdown the A2DP Source module. // This function should be called by the BTIF state machine to stop streaming. void btif_a2dp_source_shutdown(std::promise); diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index b8ee97ec091..f246ca1be87 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -62,6 +62,7 @@ #include "bta/include/bta_vc_api.h" #include "btif/avrcp/avrcp_service.h" #include "btif/include/btif_a2dp.h" +#include "btif/include/btif_a2dp_source.h" #include "btif/include/btif_api.h" #include "btif/include/btif_av.h" #include "btif/include/btif_bqr.h" @@ -1117,9 +1118,7 @@ static int set_dynamic_audio_buffer_size(int codec, int size) { } static bool allow_low_latency_audio(bool allowed, const RawAddress& /* address */) { - log::info("{}", allowed); - do_in_main_thread( - base::BindOnce(bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed, allowed)); + btif_a2dp_source_allow_low_latency_audio(allowed); return true; } diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index e4b197845a5..61dedb5bf37 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -515,6 +515,14 @@ static void btif_a2dp_source_end_session_delayed(const RawAddress& peer_address) } } +void btif_a2dp_source_allow_low_latency_audio(bool allowed) { + log::info("allowed={}", allowed); + + btif_a2dp_source_thread.DoInThread( + FROM_HERE, + base::BindOnce(bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed, allowed)); +} + void btif_a2dp_source_shutdown(std::promise shutdown_complete_promise) { log::info("state={}", btif_a2dp_source_cb.StateStr()); -- GitLab From 9999a7d9f210dc7dd961dcba91c0c18928018c56 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 16 Oct 2024 19:01:19 -0700 Subject: [PATCH 345/875] Framework: unify callback execution Bug: 373976275 Fix: 373976275 Test: m Bluetooth Flag: Exempt refactor Change-Id: If79f1b9f4f42fef19173e6493e657bc695da8304 --- .../android/bluetooth/BluetoothAdapter.java | 36 ++++++------- .../BluetoothCsipSetCoordinator.java | 4 +- .../android/bluetooth/BluetoothHidDevice.java | 51 ++++--------------- .../bluetooth/BluetoothLeCallControl.java | 46 ++++------------- .../java/android/bluetooth/BluetoothPan.java | 5 +- .../android/bluetooth/BluetoothUtils.java | 19 +++++++ .../bluetooth/BluetoothVolumeControl.java | 4 +- .../android/bluetooth/CallbackWrapper.java | 4 +- .../le/DistanceMeasurementSession.java | 20 ++------ 9 files changed, 69 insertions(+), 120 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 22b6251e7f2..ce8b74f74f6 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -24,6 +24,8 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.BLUETOOTH_SCAN; import static android.Manifest.permission.LOCAL_MAC_ADDRESS; import static android.Manifest.permission.MODIFY_PHONE_STATE; +import static android.bluetooth.BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import static java.util.Objects.requireNonNull; @@ -937,7 +939,8 @@ public final class BluetoothAdapter { for (Pair pair : list) { OnMetadataChangedListener listener = pair.first; Executor executor = pair.second; - executor.execute( + executeFromBinder( + executor, () -> { listener.onMetadataChanged(device, key, value); }); @@ -1016,18 +1019,13 @@ public final class BluetoothAdapter { mExecutor = null; mCallback = null; } - final long identity = Binder.clearCallingIdentity(); - try { - if (info == null) { - executor.execute( - () -> - callback.onBluetoothActivityEnergyInfoError( - BluetoothStatusCodes.FEATURE_NOT_SUPPORTED)); - } else { - executor.execute(() -> callback.onBluetoothActivityEnergyInfoAvailable(info)); - } - } finally { - Binder.restoreCallingIdentity(identity); + if (info == null) { + executeFromBinder( + executor, + () -> callback.onBluetoothActivityEnergyInfoError(FEATURE_NOT_SUPPORTED)); + } else { + executeFromBinder( + executor, () -> callback.onBluetoothActivityEnergyInfoAvailable(info)); } } @@ -1045,12 +1043,8 @@ public final class BluetoothAdapter { mExecutor = null; mCallback = null; } - final long identity = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onBluetoothActivityEnergyInfoError(errorCode)); - } finally { - Binder.restoreCallingIdentity(identity); - } + executeFromBinder( + executor, () -> callback.onBluetoothActivityEnergyInfoError(errorCode)); } } @@ -3969,11 +3963,11 @@ public final class BluetoothAdapter { } public void onOobData(@Transport int transport, @NonNull OobData oobData) { - mExecutor.execute(() -> mCallback.onOobData(transport, oobData)); + executeFromBinder(mExecutor, () -> mCallback.onOobData(transport, oobData)); } public void onError(@OobError int errorCode) { - mExecutor.execute(() -> mCallback.onError(errorCode)); + executeFromBinder(mExecutor, () -> mCallback.onError(errorCode)); } } diff --git a/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java b/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java index f9732393021..7ea5a520c92 100644 --- a/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java +++ b/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java @@ -19,6 +19,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import android.annotation.CallbackExecutor; import android.annotation.IntDef; @@ -105,7 +106,8 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto @Override @RequiresNoPermission public void onGroupLockSet(int groupId, int opStatus, boolean isLocked) { - mExecutor.execute(() -> mCallback.onGroupLockSet(groupId, opStatus, isLocked)); + executeFromBinder( + mExecutor, () -> mCallback.onGroupLockSet(groupId, opStatus, isLocked)); } } ; diff --git a/framework/java/android/bluetooth/BluetoothHidDevice.java b/framework/java/android/bluetooth/BluetoothHidDevice.java index 43e1aa8b2ab..207cab3ca84 100644 --- a/framework/java/android/bluetooth/BluetoothHidDevice.java +++ b/framework/java/android/bluetooth/BluetoothHidDevice.java @@ -18,6 +18,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import android.annotation.NonNull; import android.annotation.RequiresNoPermission; @@ -368,78 +369,44 @@ public final class BluetoothHidDevice implements BluetoothProfile { @Override public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) { Attributable.setAttributionSource(pluggedDevice, mAttributionSource); - final long token = clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onAppStatusChanged(pluggedDevice, registered)); - } finally { - restoreCallingIdentity(token); - } + executeFromBinder( + mExecutor, () -> mCallback.onAppStatusChanged(pluggedDevice, registered)); } @Override public void onConnectionStateChanged(BluetoothDevice device, int state) { Attributable.setAttributionSource(device, mAttributionSource); - final long token = clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onConnectionStateChanged(device, state)); - } finally { - restoreCallingIdentity(token); - } + executeFromBinder(mExecutor, () -> mCallback.onConnectionStateChanged(device, state)); } @Override public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) { Attributable.setAttributionSource(device, mAttributionSource); - final long token = clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onGetReport(device, type, id, bufferSize)); - } finally { - restoreCallingIdentity(token); - } + executeFromBinder(mExecutor, () -> mCallback.onGetReport(device, type, id, bufferSize)); } @Override public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) { Attributable.setAttributionSource(device, mAttributionSource); - final long token = clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onSetReport(device, type, id, data)); - } finally { - restoreCallingIdentity(token); - } + executeFromBinder(mExecutor, () -> mCallback.onSetReport(device, type, id, data)); } @Override public void onSetProtocol(BluetoothDevice device, byte protocol) { Attributable.setAttributionSource(device, mAttributionSource); - final long token = clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onSetProtocol(device, protocol)); - } finally { - restoreCallingIdentity(token); - } + executeFromBinder(mExecutor, () -> mCallback.onSetProtocol(device, protocol)); } @Override public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) { Attributable.setAttributionSource(device, mAttributionSource); - final long token = clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onInterruptData(device, reportId, data)); - } finally { - restoreCallingIdentity(token); - } + executeFromBinder(mExecutor, () -> mCallback.onInterruptData(device, reportId, data)); } @Override public void onVirtualCableUnplug(BluetoothDevice device) { Attributable.setAttributionSource(device, mAttributionSource); - final long token = clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onVirtualCableUnplug(device)); - } finally { - restoreCallingIdentity(token); - } + executeFromBinder(mExecutor, () -> mCallback.onVirtualCableUnplug(device)); } } diff --git a/framework/java/android/bluetooth/BluetoothLeCallControl.java b/framework/java/android/bluetooth/BluetoothLeCallControl.java index 9f1c31e88ec..9da2f90e82f 100644 --- a/framework/java/android/bluetooth/BluetoothLeCallControl.java +++ b/framework/java/android/bluetooth/BluetoothLeCallControl.java @@ -19,6 +19,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import android.annotation.IntDef; import android.annotation.NonNull; @@ -29,7 +30,6 @@ import android.annotation.SuppressLint; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; @@ -306,52 +306,29 @@ public final class BluetoothLeCallControl implements BluetoothProfile { @Override public void onAcceptCall(int requestId, ParcelUuid uuid) { - final long identityToken = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onAcceptCall(requestId, uuid.getUuid())); - } finally { - Binder.restoreCallingIdentity(identityToken); - } + executeFromBinder(mExecutor, () -> mCallback.onAcceptCall(requestId, uuid.getUuid())); } @Override public void onTerminateCall(int requestId, ParcelUuid uuid) { - final long identityToken = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onTerminateCall(requestId, uuid.getUuid())); - } finally { - Binder.restoreCallingIdentity(identityToken); - } + executeFromBinder( + mExecutor, () -> mCallback.onTerminateCall(requestId, uuid.getUuid())); } @Override public void onHoldCall(int requestId, ParcelUuid uuid) { - final long identityToken = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onHoldCall(requestId, uuid.getUuid())); - } finally { - Binder.restoreCallingIdentity(identityToken); - } + executeFromBinder(mExecutor, () -> mCallback.onHoldCall(requestId, uuid.getUuid())); } @Override public void onUnholdCall(int requestId, ParcelUuid uuid) { - final long identityToken = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onUnholdCall(requestId, uuid.getUuid())); - } finally { - Binder.restoreCallingIdentity(identityToken); - } + executeFromBinder(mExecutor, () -> mCallback.onUnholdCall(requestId, uuid.getUuid())); } @Override public void onPlaceCall(int requestId, ParcelUuid uuid, String uri) { - final long identityToken = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onPlaceCall(requestId, uuid.getUuid(), uri)); - } finally { - Binder.restoreCallingIdentity(identityToken); - } + executeFromBinder( + mExecutor, () -> mCallback.onPlaceCall(requestId, uuid.getUuid(), uri)); } @Override @@ -361,12 +338,7 @@ public final class BluetoothLeCallControl implements BluetoothProfile { uuids.add(parcelUuid.getUuid()); } - final long identityToken = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onJoinCalls(requestId, uuids)); - } finally { - Binder.restoreCallingIdentity(identityToken); - } + executeFromBinder(mExecutor, () -> mCallback.onJoinCalls(requestId, uuids)); } } ; diff --git a/framework/java/android/bluetooth/BluetoothPan.java b/framework/java/android/bluetooth/BluetoothPan.java index dab8c22ed2f..95702abd48f 100644 --- a/framework/java/android/bluetooth/BluetoothPan.java +++ b/framework/java/android/bluetooth/BluetoothPan.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.TETHER_PRIVILEGED; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import android.annotation.IntDef; import android.annotation.NonNull; @@ -552,13 +553,13 @@ public final class BluetoothPan implements BluetoothProfile { @Override @RequiresNoPermission public void onAvailable(String iface) { - executor.execute(() -> callback.onAvailable(iface)); + executeFromBinder(executor, () -> callback.onAvailable(iface)); } @Override @RequiresNoPermission public void onUnavailable() { - executor.execute(() -> callback.onUnavailable()); + executeFromBinder(executor, () -> callback.onUnavailable()); } }; try { diff --git a/framework/java/android/bluetooth/BluetoothUtils.java b/framework/java/android/bluetooth/BluetoothUtils.java index 4504c6bd36f..19a9057b557 100644 --- a/framework/java/android/bluetooth/BluetoothUtils.java +++ b/framework/java/android/bluetooth/BluetoothUtils.java @@ -19,6 +19,7 @@ package android.bluetooth; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresNoPermission; +import android.os.Binder; import android.os.Parcel; import android.os.UserHandle; import android.util.Log; @@ -26,6 +27,7 @@ import android.util.Log; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.Executor; /** @hide */ public final class BluetoothUtils { @@ -324,4 +326,21 @@ public final class BluetoothUtils { public static void writeStringToParcel(@NonNull Parcel out, @Nullable String str) { out.writeString(str); } + + /** + * Execute the callback without UID / PID information + * + * @hide + */ + public static void executeFromBinder(@NonNull Executor executor, @NonNull Runnable callback) { + executor.execute( + () -> { + final long identity = Binder.clearCallingIdentity(); + try { + callback.run(); + } finally { + Binder.restoreCallingIdentity(identity); + } + }); + } } diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index d14bcb1ca57..4faa1f0cea9 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -19,6 +19,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; @@ -176,7 +177,8 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose private void forEach(Consumer consumer) { synchronized (mCallbackMap) { mCallbackMap.forEach( - (callback, executor) -> executor.execute(() -> consumer.accept(callback))); + (callback, executor) -> + executeFromBinder(executor, () -> consumer.accept(callback))); } } diff --git a/framework/java/android/bluetooth/CallbackWrapper.java b/framework/java/android/bluetooth/CallbackWrapper.java index 820b3c97ee7..89db88621d0 100644 --- a/framework/java/android/bluetooth/CallbackWrapper.java +++ b/framework/java/android/bluetooth/CallbackWrapper.java @@ -18,6 +18,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import static java.util.Objects.requireNonNull; @@ -78,7 +79,8 @@ public class CallbackWrapper { public void forEach(Consumer consumer) { synchronized (mCallbackExecutorMap) { mCallbackExecutorMap.forEach( - (callback, executor) -> executor.execute(() -> consumer.accept(callback))); + (callback, executor) -> + executeFromBinder(executor, () -> consumer.accept(callback))); } } diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java index ee433a8e37f..d91fbade2c4 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java @@ -18,6 +18,7 @@ package android.bluetooth.le; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.executeFromBinder; import static java.util.Objects.requireNonNull; @@ -30,7 +31,6 @@ import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.IBluetoothGatt; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.content.AttributionSource; -import android.os.Binder; import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; @@ -117,32 +117,22 @@ public final class DistanceMeasurementSession { /** @hide */ void onStarted() { - executeCallback(() -> mCallback.onStarted(this)); + executeFromBinder(mExecutor, () -> mCallback.onStarted(this)); } /** @hide */ void onStartFail(int reason) { - executeCallback(() -> mCallback.onStartFail(reason)); + executeFromBinder(mExecutor, () -> mCallback.onStartFail(reason)); } /** @hide */ void onStopped(int reason) { - executeCallback(() -> mCallback.onStopped(this, reason)); + executeFromBinder(mExecutor, () -> mCallback.onStopped(this, reason)); } /** @hide */ void onResult(@NonNull BluetoothDevice device, @NonNull DistanceMeasurementResult result) { - executeCallback(() -> mCallback.onResult(device, result)); - } - - /** @hide */ - private void executeCallback(@NonNull Runnable runnable) { - final long identity = Binder.clearCallingIdentity(); - try { - mExecutor.execute(runnable); - } finally { - Binder.restoreCallingIdentity(identity); - } + executeFromBinder(mExecutor, () -> mCallback.onResult(device, result)); } /** -- GitLab From ea30605b2d3ffbc311d87c7dc61fc70a4dbfb409 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Fri, 16 Aug 2024 16:28:20 +0800 Subject: [PATCH 346/875] Continue removing unused DIS server from srvc_eng These code is unused, so remove them. Bug: 357011645 Test: m -j Flag: EXEMPT, dead code removal Change-Id: Ifd0e51817cf98b1f8783ad1af72ba03538429590 --- system/stack/srvc/srvc_dis.cc | 25 ----- system/stack/srvc/srvc_dis_int.h | 5 - system/stack/srvc/srvc_eng.cc | 127 +----------------------- system/test/mock/mock_stack_srvc_dis.cc | 14 --- 4 files changed, 2 insertions(+), 169 deletions(-) diff --git a/system/stack/srvc/srvc_dis.cc b/system/stack/srvc/srvc_dis.cc index 58f6befd11e..b5434cad909 100644 --- a/system/stack/srvc/srvc_dis.cc +++ b/system/stack/srvc/srvc_dis.cc @@ -70,31 +70,6 @@ static tDIS_ATTR_MASK dis_uuid_to_attr(uint16_t uuid) { }; } -/******************************************************************************* - * dis_valid_handle_range - * - * validate a handle to be a DIS attribute handle or not. - ******************************************************************************/ -bool dis_valid_handle_range(uint16_t /* handle */) { return false; } -/******************************************************************************* - * dis_write_attr_value - * - * Process write DIS attribute request. - ******************************************************************************/ -uint8_t dis_write_attr_value(tGATT_WRITE_REQ* /* p_data */, tGATT_STATUS* p_status) { - *p_status = GATT_WRITE_NOT_PERMIT; - return SRVC_ACT_RSP; -} -/******************************************************************************* - * DIS Attributes Database Server Request callback - ******************************************************************************/ -uint8_t dis_read_attr_value(uint8_t /* clcb_idx */, uint16_t /* handle */, - tGATT_VALUE* /* p_value */, bool /* is_long */, - tGATT_STATUS* p_status) { - *p_status = GATT_NOT_FOUND; - return SRVC_ACT_RSP; -} - /******************************************************************************* * * Function dis_gatt_c_read_dis_value_cmpl diff --git a/system/stack/srvc/srvc_dis_int.h b/system/stack/srvc/srvc_dis_int.h index dae3071bc15..607162a1021 100644 --- a/system/stack/srvc/srvc_dis_int.h +++ b/system/stack/srvc/srvc_dis_int.h @@ -45,11 +45,6 @@ typedef struct { /* Global GATT data */ extern tDIS_CB dis_cb; -bool dis_valid_handle_range(uint16_t handle); -uint8_t dis_read_attr_value(uint8_t clcb_idx, uint16_t handle, tGATT_VALUE* p_value, bool is_long, - tGATT_STATUS* p_status); -uint8_t dis_write_attr_value(tGATT_WRITE_REQ* p_data, tGATT_STATUS* p_status); - void dis_c_cmpl_cback(tSRVC_CLCB* p_clcb, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE* p_data); diff --git a/system/stack/srvc/srvc_eng.cc b/system/stack/srvc/srvc_eng.cc index c1d877dd8ea..92fb80cf718 100644 --- a/system/stack/srvc/srvc_eng.cc +++ b/system/stack/srvc/srvc_eng.cc @@ -27,11 +27,8 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" -using base::StringPrintf; using namespace bluetooth; -static void srvc_eng_s_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, - tGATTS_DATA* p_data); static void srvc_eng_connect_cback(tGATT_IF /* gatt_if */, const RawAddress& bda, tCONN_ID conn_id, bool connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport); @@ -43,7 +40,7 @@ static tGATT_CBACK srvc_gatt_cback = { .p_cmpl_cb = srvc_eng_c_cmpl_cback, .p_disc_res_cb = nullptr, .p_disc_cmpl_cb = nullptr, - .p_req_cb = srvc_eng_s_request_cback, + .p_req_cb = nullptr, .p_enc_cmpl_cb = nullptr, .p_congestion_cb = nullptr, .p_phy_update_cb = nullptr, @@ -103,27 +100,6 @@ tSRVC_CLCB* srvc_eng_find_clcb_by_conn_id(tCONN_ID conn_id) { return NULL; } -/******************************************************************************* - * - * Function srvc_eng_find_clcb_by_conn_id - * - * Description The function searches all LCBs with macthing connection ID. - * - * Returns Pointer to the found link conenction control block. - * - ******************************************************************************/ -static uint8_t srvc_eng_find_clcb_idx_by_conn_id(tCONN_ID conn_id) { - uint8_t i_clcb; - tSRVC_CLCB* p_clcb = NULL; - - for (i_clcb = 0, p_clcb = srvc_eng_cb.clcb; i_clcb < SRVC_MAX_APPS; i_clcb++, p_clcb++) { - if (p_clcb->in_use && p_clcb->connected && p_clcb->conn_id == conn_id) { - return i_clcb; - } - } - - return SRVC_MAX_APPS; -} /******************************************************************************* * * Function srvc_eng_clcb_alloc @@ -175,105 +151,6 @@ static bool srvc_eng_clcb_dealloc(tCONN_ID conn_id) { } return false; } -/******************************************************************************* - * Service Engine Server Attributes Database Read/Read Blob Request process - ******************************************************************************/ -static uint8_t srvc_eng_process_read_req(uint8_t clcb_idx, tGATT_READ_REQ* p_data, - tGATTS_RSP* p_rsp, tGATT_STATUS* p_status) { - tGATT_STATUS status = GATT_NOT_FOUND; - uint8_t act = SRVC_ACT_RSP; - - if (p_data->is_long) { - p_rsp->attr_value.offset = p_data->offset; - } - - p_rsp->attr_value.handle = p_data->handle; - - if (dis_valid_handle_range(p_data->handle)) { - act = dis_read_attr_value(clcb_idx, p_data->handle, &p_rsp->attr_value, p_data->is_long, - p_status); - } else { - *p_status = status; - } - return act; -} -/******************************************************************************* - * Service Engine Server Attributes Database write Request process - ******************************************************************************/ -static uint8_t srvc_eng_process_write_req(uint8_t /* clcb_idx */, tGATT_WRITE_REQ* p_data, - tGATTS_RSP* /* p_rsp */, tGATT_STATUS* p_status) { - uint8_t act = SRVC_ACT_RSP; - - if (dis_valid_handle_range(p_data->handle)) { - act = dis_write_attr_value(p_data, p_status); - } else { - *p_status = GATT_NOT_FOUND; - } - - return act; -} - -/******************************************************************************* - * - * Function srvc_eng_s_request_cback - * - * Description GATT DIS attribute access request callback. - * - * Returns void. - * - ******************************************************************************/ -static void srvc_eng_s_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, - tGATTS_DATA* p_data) { - tGATT_STATUS status = GATT_INVALID_PDU; - tGATTS_RSP rsp_msg; - uint8_t act = SRVC_ACT_IGNORE; - uint8_t clcb_idx = srvc_eng_find_clcb_idx_by_conn_id(conn_id); - if (clcb_idx == SRVC_MAX_APPS) { - log::error("Can't find clcb, id:{}", conn_id); - return; - } - - log::verbose("srvc_eng_s_request_cback : recv type (0x{:02x})", type); - - memset(&rsp_msg, 0, sizeof(tGATTS_RSP)); - - srvc_eng_cb.clcb[clcb_idx].trans_id = trans_id; - - switch (type) { - case GATTS_REQ_TYPE_READ_CHARACTERISTIC: - case GATTS_REQ_TYPE_READ_DESCRIPTOR: - act = srvc_eng_process_read_req(clcb_idx, &p_data->read_req, &rsp_msg, &status); - break; - - case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC: - case GATTS_REQ_TYPE_WRITE_DESCRIPTOR: - act = srvc_eng_process_write_req(clcb_idx, &p_data->write_req, &rsp_msg, &status); - if (!p_data->write_req.need_rsp) { - act = SRVC_ACT_IGNORE; - } - break; - - case GATTS_REQ_TYPE_WRITE_EXEC: - log::verbose("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD"); - break; - - case GATTS_REQ_TYPE_MTU: - log::verbose("Get MTU exchange new mtu size: {}", p_data->mtu); - break; - - default: - log::verbose("Unknown/unexpected LE GAP ATT request: 0x{:02x}", type); - break; - } - - srvc_eng_cb.clcb[clcb_idx].trans_id = 0; - - if (act == SRVC_ACT_RSP) { - if (GATTS_SendRsp(conn_id, trans_id, status, &rsp_msg) != GATT_SUCCESS) { - log::warn("Unable to send GATT server respond conn_id:{}", conn_id); - } - } -} /******************************************************************************* * @@ -381,7 +258,7 @@ void srvc_eng_release_channel(tCONN_ID conn_id) { ******************************************************************************/ tGATT_STATUS srvc_eng_init(void) { if (srvc_eng_cb.enabled) { - log::error("DIS already initialized"); + log::verbose("DIS already initialized"); } else { memset(&srvc_eng_cb, 0, sizeof(tSRVC_ENG_CB)); diff --git a/system/test/mock/mock_stack_srvc_dis.cc b/system/test/mock/mock_stack_srvc_dis.cc index abd467c3a90..fc301ea0a11 100644 --- a/system/test/mock/mock_stack_srvc_dis.cc +++ b/system/test/mock/mock_stack_srvc_dis.cc @@ -38,20 +38,6 @@ bool dis_gatt_c_read_dis_req(uint16_t /* conn_id */) { inc_func_call_count(__func__); return false; } -bool dis_valid_handle_range(uint16_t /* handle */) { - inc_func_call_count(__func__); - return false; -} -uint8_t dis_read_attr_value(uint8_t /* clcb_idx */, uint16_t /* handle */, - tGATT_VALUE* /* p_value */, bool /* is_long */, - tGATT_STATUS* /* p_status */) { - inc_func_call_count(__func__); - return 0; -} -uint8_t dis_write_attr_value(tGATT_WRITE_REQ* /* p_data */, tGATT_STATUS* /* p_status */) { - inc_func_call_count(__func__); - return 0; -} void dis_c_cmpl_cback(tSRVC_CLCB* /* p_clcb */, tGATTC_OPTYPE /* op */, tGATT_STATUS /* status */, tGATT_CL_COMPLETE* /* p_data */) { inc_func_call_count(__func__); -- GitLab From d87f7e1f502b5e58e98106bdaf7ca52f626d4ee3 Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Mon, 14 Oct 2024 14:21:54 +0900 Subject: [PATCH 347/875] Clear storage on bluetooth factory reset This CL makes BT factory reset removes all files/directories under - /data/misc/bluedroid/ - /data/misc/bluetooth/ Bug: 359583862 Bug: 373284699 Test: atest AdapterServiceTest Test: Manual, clicked 'Reset Bluetooth & Wifi' and checked the cache/hash files are deleted. Change-Id: I969ae986e1afd32e91528424dc27a3016a0e8b58 --- .../bluetooth/btservice/AdapterService.java | 52 +++++++++++++++++++ .../btservice/AdapterServiceTest.java | 40 ++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 17ce026d796..63cce4ab094 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -171,6 +171,12 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.time.Duration; import java.util.ArrayDeque; import java.util.ArrayList; @@ -5880,6 +5886,10 @@ public class AdapterService extends Service { mBtCompanionManager.factoryReset(); } + if (Flags.gattClearCacheOnFactoryReset()) { + clearStorage(); + } + return mNativeInterface.factoryReset(); } @@ -6970,4 +6980,46 @@ public class AdapterService extends Service { mPhonePolicy.onUuidsDiscovered(device, uuids); } } + + /** Clear storage */ + void clearStorage() { + deleteDirectoryContents("/data/misc/bluedroid/"); + deleteDirectoryContents("/data/misc/bluetooth/"); + } + + private void deleteDirectoryContents(String dirPath) { + Path directoryPath = Paths.get(dirPath); + try { + Files.walkFileTree( + directoryPath, + new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException ex) + throws IOException { + if (ex != null) { + Log.e(TAG, "Error happened while removing contents. ", ex); + } + + if (!dir.equals(directoryPath)) { + try { + Files.delete(dir); + } catch (Exception e) { + Log.e(TAG, "Error happened while removing directory: ", e); + } + } + return FileVisitResult.CONTINUE; + } + }); + Log.i(TAG, "deleteDirectoryContents() completed. Path: " + dirPath); + } catch (Exception e) { + Log.e(TAG, "Error happened while removing contents: ", e); + } + } } 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 df83babd3ea..f2eb42d671d 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 @@ -101,6 +101,9 @@ import platform.test.runner.parameterized.Parameters; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.List; @@ -1033,4 +1036,41 @@ public class AdapterServiceTest { mAdapterService.dump(fd, writer, new String[] {"--proto-bin"}); mAdapterService.dump(fd, writer, new String[] {"random", "arguments"}); } + + @Test + @EnableFlags(Flags.FLAG_GATT_CLEAR_CACHE_ON_FACTORY_RESET) + public void testClearStorage() throws Exception { + // clearStorage should remove all files under /data/misc/bluetooth/ && /data/misc/bluedroid/ + final Path testCachePath = Paths.get("/data/misc/bluetooth/gatt_cache_a475b9a23d72"); + final Path testHashPath = + Paths.get("/data/misc/bluetooth/gatt_hash_400D017CB2563A6FB62A2DC4C2AEFD6F"); + final Path randomFileUnderBluedroidPath = + Paths.get("/data/misc/bluedroid/random_test_file.txt"); + final Path randomFileUnderBluetoothPath = + Paths.get("/data/misc/bluetooth/random_test_file.txt"); + + try { + Files.createFile(testCachePath); + Files.createFile(testHashPath); + Files.createFile(randomFileUnderBluedroidPath); + Files.createFile(randomFileUnderBluetoothPath); + + assertThat(Files.exists(testCachePath)).isTrue(); + assertThat(Files.exists(testHashPath)).isTrue(); + assertThat(Files.exists(randomFileUnderBluedroidPath)).isTrue(); + assertThat(Files.exists(randomFileUnderBluetoothPath)).isTrue(); + + mAdapterService.clearStorage(); + + assertThat(Files.exists(testCachePath)).isFalse(); + assertThat(Files.exists(testHashPath)).isFalse(); + assertThat(Files.exists(randomFileUnderBluedroidPath)).isFalse(); + assertThat(Files.exists(randomFileUnderBluetoothPath)).isFalse(); + } finally { + Files.deleteIfExists(testCachePath); + Files.deleteIfExists(testHashPath); + Files.deleteIfExists(randomFileUnderBluedroidPath); + Files.deleteIfExists(randomFileUnderBluetoothPath); + } + } } -- GitLab From 192cbdb6fc7696bbc154a77a770359710db5e12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 17 Oct 2024 12:46:27 +0000 Subject: [PATCH 348/875] has_client.cc: fix possible null pointer dereference in `Disconnect` device could be null (not connected to profile) Bug: 373981915 Flag: com.android.bluetooth.flags.hap_connect_only_requested_device Test: atest --host --no-bazel-mode bluetooth_has_test Change-Id: I2a48e58616b242252f41c1b5622f99b3ecf295c8 --- system/bta/has/has_client.cc | 5 +++++ system/bta/has/has_client_test.cc | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 6992211a4f0..de671e9dfaa 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -222,6 +222,11 @@ public: if (com::android::bluetooth::flags::hap_connect_only_requested_device()) { auto device = std::find_if(devices_.begin(), devices_.end(), HasDevice::MatchAddress(address)); + if (device == devices_.end()) { + log::warn("Device not connected to profile{}", address); + return; + } + auto conn_id = device->conn_id; auto is_connecting_actively = device->is_connecting_actively; diff --git a/system/bta/has/has_client_test.cc b/system/bta/has/has_client_test.cc index 6ca1067116a..b0656e41b5b 100644 --- a/system/bta/has/has_client_test.cc +++ b/system/bta/has/has_client_test.cc @@ -1195,7 +1195,20 @@ TEST_F(HasClientTest, test_connect_after_remove) { Mock::VerifyAndClearExpectations(&callbacks); } +TEST_F(HasClientTest, + test_disconnect_non_connected_without_hap_connect_only_requested_device_flag) { + com::android::bluetooth::flags::provider_->hap_connect_only_requested_device(false); + const RawAddress test_address = GetTestAddress(1); + + /* Override the default action to prevent us sendind the connected event */ + EXPECT_CALL(gatt_interface, Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, _)) + .WillOnce(Return()); + HasClient::Get()->Connect(test_address); + TestDisconnect(test_address, GATT_INVALID_CONN_ID); +} + TEST_F(HasClientTest, test_disconnect_non_connected) { + com::android::bluetooth::flags::provider_->hap_connect_only_requested_device(true); const RawAddress test_address = GetTestAddress(1); /* Override the default action to prevent us sendind the connected event */ -- GitLab From 9c855f57e1b88a2c73bdba4059e2ea325cfbc4c6 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 11 Oct 2024 17:15:23 +0000 Subject: [PATCH 349/875] Uses states to manage the measurement conflicting finely. Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 368617974 Test: m com.android.btservices Change-Id: Ia8b8551e87faf8f6f07fb6c4f6851280629dcf88 --- system/gd/hci/distance_measurement_manager.cc | 171 +++++++++++++++--- 1 file changed, 141 insertions(+), 30 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index b5761e7afa3..2f791ef4f59 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -142,12 +142,26 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { std::unique_ptr repeating_alarm; }; + // TODO: use state machine to manage the tracker. + enum class CsTrackerState : uint8_t { + UNSPECIFIED = 0x00, + STOPPED = 1 << 0, + INIT = 1 << 1, + RAS_CONNECTED = 1 << 2, + WAIT_FOR_CONFIG_COMPLETE = 1 << 3, + WAIT_FOR_SECURITY_ENABLED = 1 << 4, + WAIT_FOR_PROCEDURE_ENABLED = 1 << 5, + STARTED = 1 << 6, + }; + struct CsTracker { + CsTrackerState state = CsTrackerState::STOPPED; Address address; hci::Role local_hci_role = hci::Role::CENTRAL; uint16_t procedure_counter = 0; CsRole role = CsRole::INITIATOR; bool local_start = false; // If the CS was started by the local device. + // TODO: clean up, replace the measurement_ongoing with STOPPED bool measurement_ongoing = false; bool ras_connected = false; bool setup_complete = false; @@ -315,6 +329,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (it->second.repeating_alarm == nullptr) { it->second.repeating_alarm = std::make_unique(handler_); } + it->second.state = CsTrackerState::INIT; it->second.interval_ms = interval; it->second.local_start = true; it->second.measurement_ongoing = true; @@ -382,8 +397,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::warn("Can't find CS tracker for {}", address); } else if (it->second.measurement_ongoing) { it->second.repeating_alarm->Cancel(); - reset_tracker_on_stopped(it->second); send_le_cs_procedure_enable(connection_handle, Enable::DISABLED); + // does not depend on the 'disable' command result. + reset_tracker_on_stopped(it->second); } } break; } @@ -407,6 +423,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } it->second.ras_connected = true; + it->second.state = CsTrackerState::RAS_CONNECTED; if (ranging_hal_->IsBound()) { ranging_hal_->OpenSession(connection_handle, att_handle, vendor_specific_data); @@ -465,6 +482,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { cs_responder_trackers_[connection_handle] = CsTracker(); it = cs_responder_trackers_.find(connection_handle); } + it->second.state = CsTrackerState::RAS_CONNECTED; it->second.address = identity_address; it->second.local_start = false; it->second.local_hci_role = local_hci_role; @@ -567,6 +585,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } void send_le_cs_security_enable(uint16_t connection_handle) { + if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) { + log::warn("no cs tracker found for {}", connection_handle); + } + cs_requester_trackers_[connection_handle].state = CsTrackerState::WAIT_FOR_SECURITY_ENABLED; hci_layer_->EnqueueCommand( LeCsSecurityEnableBuilder::Create(connection_handle), handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); @@ -581,6 +603,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } void send_le_cs_create_config(uint16_t connection_handle, uint8_t config_id) { + if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) { + log::warn("no cs tracker found for {}", connection_handle); + } + cs_requester_trackers_[connection_handle].state = CsTrackerState::WAIT_FOR_CONFIG_COMPLETE; auto channel_vector = common::FromHexString("1FFFFFFFFFFFFC7FFFFC"); // use all 72 Channel std::array channel_map; std::copy(channel_vector->begin(), channel_vector->end(), channel_map.begin()); @@ -609,6 +635,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; } void handle_cs_setup_failure(uint16_t connection_handle, DistanceMeasurementErrorCode errorCode) { @@ -636,12 +663,21 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } - if (!it->second.measurement_ongoing) { - log::error("safe guard, error state, no local measurement request."); - if (it->second.repeating_alarm) { - it->second.repeating_alarm->Cancel(); + if (enable == Enable::ENABLED) { + if (it->second.state == CsTrackerState::STOPPED) { + log::error("safe guard, error state, no local measurement request."); + if (it->second.repeating_alarm) { + it->second.repeating_alarm->Cancel(); + } + return; + } + it->second.state = CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED; + } else { // Enable::DISABLE + if (it->second.state != CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED && + it->second.state != CsTrackerState::STARTED) { + log::info("no procedure disable command needed for state {}.", (int)it->second.state); + return; } - return; } hci_layer_->EnqueueCommand( @@ -754,11 +790,17 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); return; } - auto it = cs_requester_trackers_.find(connection_handle); - if (it != cs_requester_trackers_.end() && it->second.measurement_ongoing && - !it->second.config_set) { - it->second.config_set = true; - send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), it->second.config_id); + auto req_it = cs_requester_trackers_.find(connection_handle); + if (req_it != cs_requester_trackers_.end() && req_it->second.measurement_ongoing && + !req_it->second.config_set) { + req_it->second.config_set = true; + send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), + req_it->second.config_id); + } + auto res_it = cs_responder_trackers_.find(connection_handle); + if (res_it != cs_responder_trackers_.end() && + res_it->second.state == CsTrackerState::WAIT_FOR_SECURITY_ENABLED) { + res_it->second.state = CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED; } } @@ -775,7 +817,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } uint8_t config_id = event_view.GetConfigId(); - CsTracker* live_tracker = get_live_tracker(connection_handle, config_id); + check_and_handle_conflict(connection_handle, config_id, + CsTrackerState::WAIT_FOR_CONFIG_COMPLETE); + uint8_t valid_requester_states = static_cast(CsTrackerState::WAIT_FOR_CONFIG_COMPLETE); + // any state, as the remote can start over at any time. + uint8_t valid_responder_states = static_cast(CsTrackerState::UNSPECIFIED); + + CsTracker* live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states, + valid_responder_states); if (live_tracker == nullptr) { log::warn("Can't find cs tracker for connection_handle {}", connection_handle); return; @@ -794,6 +843,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { // send the cmd from the BLE central only. send_le_cs_security_enable(connection_handle); } + // TODO: else set a timeout alarm to make sure the remote would trigger the cmd. + if (!live_tracker->local_start) { + live_tracker->state = CsTrackerState::WAIT_FOR_SECURITY_ENABLED; + } } void on_cs_set_procedure_parameters(CommandCompleteView view) { @@ -826,24 +879,53 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } - CsTracker* get_live_tracker(uint16_t connection_handle, uint8_t config_id) { - // suppose the config_id is unique, otherwise, no way to know if the event from controller - // is from local(requester) or remote(responder). + CsTracker* get_live_tracker(uint16_t connection_handle, uint8_t config_id, + uint8_t valid_requester_states, uint8_t valid_responder_states) { // CAVEAT: if the remote is sending request with the same config id, the behavior is undefined. - auto it = cs_requester_trackers_.find(connection_handle); - if (it != cs_requester_trackers_.end() && it->second.measurement_ongoing && - it->second.config_id == config_id) { - return &(it->second); + auto req_it = cs_requester_trackers_.find(connection_handle); + if (req_it != cs_requester_trackers_.end() && req_it->second.state != CsTrackerState::STOPPED && + req_it->second.config_id == config_id && + (valid_requester_states & static_cast(req_it->second.state)) != 0) { + return &cs_requester_trackers_[connection_handle]; } - // take it as responder any way - if (cs_responder_trackers_.find(connection_handle) != cs_responder_trackers_.end()) { + + auto res_it = cs_responder_trackers_.find(connection_handle); + if (res_it != cs_responder_trackers_.end() && + (res_it->second.config_id == kInvalidConfigId || res_it->second.config_id == config_id) && + (valid_responder_states == static_cast(CsTrackerState::UNSPECIFIED) || + (valid_responder_states & static_cast(res_it->second.state)) != 0)) { return &cs_responder_trackers_[connection_handle]; } - - log::error("no event is expected as no any live cs tracker for {}", connection_handle); + log::error("no valid tracker to handle the event."); return nullptr; } + void check_and_handle_conflict(uint16_t connection_handle, uint8_t event_config_id, + CsTrackerState expected_requester_state) { + // If the local and remote were triggering the event at the same time, and the controller + // allows that happen, the things may still get messed; If the spec can differentiate the + // local event or remote event, that would be clearer. + auto it = cs_requester_trackers_.find(connection_handle); + if (it == cs_requester_trackers_.end()) { + return; + } + if (event_config_id != it->second.config_id) { + return; + } + if (it->second.state == expected_requester_state) { + return; + } + log::warn("unexpected request from remote, which is conflict with the local measurement."); + it->second.config_set = false; + if (it->second.state != CsTrackerState::STOPPED) { + stop_distance_measurement(it->second.address, connection_handle, + DistanceMeasurementMethod::METHOD_CS); + // TODO: clean up the stopped callback, it should be called within stop_distance_measurement. + distance_measurement_callbacks_->OnDistanceMeasurementStopped( + it->second.address, REASON_REMOTE_REQUEST, METHOD_CS); + } + } + 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(); @@ -855,13 +937,26 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } uint8_t config_id = event_view.GetConfigId(); - CsTracker* live_tracker = get_live_tracker(connection_handle, config_id); - if (live_tracker == nullptr) { - log::error("no tracker is available for {}", connection_handle); - return; - } + + CsTracker* live_tracker = nullptr; if (event_view.GetState() == Enable::ENABLED) { + check_and_handle_conflict(connection_handle, config_id, + CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED); + uint8_t valid_requester_states = + static_cast(CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED); + uint8_t valid_responder_states = + static_cast(CsTrackerState::STOPPED) | + static_cast(CsTrackerState::INIT) | + static_cast(CsTrackerState::STARTED) | + static_cast(CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED); + 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; + } log::debug("Procedure enabled, {}", event_view.ToString()); + live_tracker->state = CsTrackerState::STARTED; // assign the config_id, as this is may be the 1st time to get it for responder; live_tracker->config_id = config_id; live_tracker->selected_tx_power = event_view.GetSelectedTxPower(); @@ -881,6 +976,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { cs_requester_trackers_[connection_handle].config_set = false; } } else if (event_view.GetState() == Enable::DISABLED) { + uint8_t valid_requester_states = static_cast(CsTrackerState::STARTED); + uint8_t valid_responder_states = static_cast(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; + } reset_tracker_on_stopped(*live_tracker); } // reset the procedure data list. @@ -904,6 +1007,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { SubeventAbortReason subevent_abort_reason; std::vector result_data_structures; CsTracker* live_tracker = nullptr; + uint8_t valid_requester_states = static_cast(CsTrackerState::STARTED); + uint8_t valid_responder_states = static_cast(CsTrackerState::STARTED); if (event.GetSubeventCode() == SubeventCode::LE_CS_SUBEVENT_RESULT) { auto cs_event_result = LeCsSubeventResultView::Create(event); if (!cs_event_result.IsValid()) { @@ -911,7 +1016,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } connection_handle = cs_event_result.GetConnectionHandle(); - live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId()); + live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId(), + valid_requester_states, valid_responder_states); if (live_tracker == nullptr) { log::error("no live tracker is available for {}", connection_handle); return; @@ -943,7 +1049,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } connection_handle = cs_event_result.GetConnectionHandle(); - live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId()); + live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId(), + valid_requester_states, valid_responder_states); procedure_done_status = cs_event_result.GetProcedureDoneStatus(); subevent_done_status = cs_event_result.GetSubeventDoneStatus(); procedure_abort_reason = cs_event_result.GetProcedureAbortReason(); @@ -1066,6 +1173,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::warn("can't find tracker for 0x{:04x}", connection_handle); return; } + if (cs_requester_trackers_[connection_handle].state != CsTrackerState::STARTED) { + log::warn("The measurement for {} is stopped, ignore the remote data.", connection_handle); + return; + } auto& tracker = cs_requester_trackers_[connection_handle]; SegmentationHeader segmentation_header; -- GitLab From cf4bfc9dfeca9ab1e3de93d7b6b0737ec140799a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Thu, 17 Oct 2024 09:56:39 +0000 Subject: [PATCH 350/875] leaudio: Minor cleanup on suspent_timeout_ Add helper functions to start and stop suspend_timeout_ Bug: 372120241 Flag: EXEMPT, mechanical refactor Test: mmm packages/modules/Bluetooth Change-Id: Ie541d871aeed2d364e0d80a4f239f8d1751a4143 --- system/bta/le_audio/client.cc | 72 +++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index e76c7eee2da..41646a0292f 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -365,6 +365,36 @@ public: } } + void StartSuspendTimeout(void) { + StopSuspendTimeout(); + + /* Group should tie in time to get requested status */ + uint64_t timeoutMs = kAudioSuspentKeepIsoAliveTimeoutMs; + timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp, timeoutMs); + + if (stack_config_get_interface()->get_pts_le_audio_disable_ases_before_stopping()) { + timeoutMs += kAudioDisableTimeoutMs; + } + + log::debug("Stream suspend_timeout_ started: {} ms", static_cast(timeoutMs)); + + alarm_set_on_mloop( + suspend_timeout_, timeoutMs, + [](void* data) { + if (instance) { + instance->GroupStop(PTR_TO_INT(data)); + } + }, + INT_TO_PTR(active_group_id_)); + } + + void StopSuspendTimeout(void) { + if (alarm_is_scheduled(suspend_timeout_)) { + log::debug("Cancel suspend timeout"); + alarm_cancel(suspend_timeout_); + } + } + void AseInitialStateReadRequest(LeAudioDevice* leAudioDevice) { int ases_num = leAudioDevice->ases_.size(); void* notify_flag_ptr = NULL; @@ -1292,9 +1322,7 @@ public: sink_monitor_notified_status_ = std::nullopt; log::info("Group id: {}", active_group_id_); - if (alarm_is_scheduled(suspend_timeout_)) { - alarm_cancel(suspend_timeout_); - } + StopSuspendTimeout(); StopAudio(); ClientAudioInterfaceRelease(); @@ -3921,9 +3949,7 @@ public: void Cleanup() { StopVbcCloseTimeout(); - if (alarm_is_scheduled(suspend_timeout_)) { - alarm_cancel(suspend_timeout_); - } + StopSuspendTimeout(); if (active_group_id_ != bluetooth::groups::kGroupUnknown) { /* Bluetooth turned off while streaming */ @@ -4037,27 +4063,7 @@ public: INT_TO_PTR(active_group_id_)); } - /* Group should tie in time to get requested status */ - uint64_t timeoutMs = kAudioSuspentKeepIsoAliveTimeoutMs; - timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp, timeoutMs); - - if (stack_config_get_interface()->get_pts_le_audio_disable_ases_before_stopping()) { - timeoutMs += kAudioDisableTimeoutMs; - } - - log::debug("Stream suspend_timeout_ started: {} ms", static_cast(timeoutMs)); - if (alarm_is_scheduled(suspend_timeout_)) { - alarm_cancel(suspend_timeout_); - } - - alarm_set_on_mloop( - suspend_timeout_, timeoutMs, - [](void* data) { - if (instance) { - instance->GroupStop(PTR_TO_INT(data)); - } - }, - INT_TO_PTR(active_group_id_)); + StartSuspendTimeout(); } void OnLocalAudioSourceSuspend() { @@ -4255,9 +4261,7 @@ public: case AudioState::IDLE: case AudioState::READY_TO_RELEASE: /* Stream is up just restore it */ - if (alarm_is_scheduled(suspend_timeout_)) { - alarm_cancel(suspend_timeout_); - } + StopSuspendTimeout(); ConfirmLocalAudioSourceStreamingRequest(); bluetooth::le_audio::MetricsCollector::Get()->OnStreamStarted( active_group_id_, configuration_context_type_); @@ -4507,9 +4511,7 @@ public: case AudioState::READY_TO_START: case AudioState::READY_TO_RELEASE: /* Stream is up just restore it */ - if (alarm_is_scheduled(suspend_timeout_)) { - alarm_cancel(suspend_timeout_); - } + StopSuspendTimeout(); ConfirmLocalAudioSinkStreamingRequest(); break; case AudioState::RELEASING: @@ -4604,9 +4606,7 @@ public: return false; } - if (alarm_is_scheduled(suspend_timeout_)) { - alarm_cancel(suspend_timeout_); - } + StopSuspendTimeout(); /* Need to reconfigure stream. At this point pre_configuration_context_type shall be set */ -- GitLab From 17bfc0e9e491729105d8c377ea9b85162b6be415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Thu, 17 Oct 2024 15:52:50 +0000 Subject: [PATCH 351/875] test/fake_osi: Improve fake alarms managing With this patch, alarm_is_scheduled() will return based on scheduler alarms and not only based on last scheduled alartm. Also some loging has been added. Bug: 372120241 Flag: TEST_ONLY Test: mmm packages/modules/Bluetooth Change-Id: Id4b77fd0eaf2a771546a99183692fed55988a919 --- system/bta/test/common/fake_osi.h | 1 + system/test/stub/osi.cc | 65 ++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/system/bta/test/common/fake_osi.h b/system/bta/test/common/fake_osi.h index 9eceafaa917..1a9456d628f 100644 --- a/system/bta/test/common/fake_osi.h +++ b/system/bta/test/common/fake_osi.h @@ -21,6 +21,7 @@ #include "osi/include/alarm.h" struct fake_osi_alarm_set_on_mloop { + alarm_t* alarm; uint64_t interval_ms{0}; alarm_callback_t cb{}; void* data{nullptr}; diff --git a/system/test/stub/osi.cc b/system/test/stub/osi.cc index fcfa858a917..17accc1794b 100644 --- a/system/test/stub/osi.cc +++ b/system/test/stub/osi.cc @@ -20,6 +20,7 @@ #include "osi/include/osi.h" +#include #include #include @@ -335,24 +336,70 @@ alarm_t* alarm_new_periodic(const char* name) { inc_func_call_count(__func__); return nullptr; } + +// Callback to last set alarm struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_; + +// Vector of previous osi alarms. Keep it for proper handling alarm_is_scheduler function +static std::vector previous_fake_osi_alarms_; + bool alarm_is_scheduled(const alarm_t* alarm) { inc_func_call_count(__func__); - return fake_osi_alarm_set_on_mloop_.cb != nullptr; + + auto iter = + find_if(previous_fake_osi_alarms_.begin(), previous_fake_osi_alarms_.end(), + [alarm](auto const& a) { + bluetooth::log::debug("iter: {} == {} ?", fmt::ptr(a.alarm), fmt::ptr(alarm)); + return a.alarm == alarm; + }); + if (iter != previous_fake_osi_alarms_.end()) { + return true; + } + + bluetooth::log::debug(" {} == {} ?", fmt::ptr(fake_osi_alarm_set_on_mloop_.alarm), + fmt::ptr(alarm)); + + return fake_osi_alarm_set_on_mloop_.alarm == alarm; } uint64_t alarm_get_remaining_ms(const alarm_t* alarm) { inc_func_call_count(__func__); return 0; } + +static void fake_osi_alarm_clear(alarm_t* alarm) { + if (alarm != nullptr) { + auto iter = find_if(previous_fake_osi_alarms_.begin(), previous_fake_osi_alarms_.end(), + [alarm](auto const& a) { return a.alarm == alarm; }); + if (iter != previous_fake_osi_alarms_.end()) { + bluetooth::log::debug(" clearing alarm {} ", fmt::ptr(iter->alarm)); + previous_fake_osi_alarms_.erase(iter); + return; + } + } + + if (fake_osi_alarm_set_on_mloop_.alarm == alarm || alarm == nullptr) { + bluetooth::log::debug(" clearing alarm {} ", fmt::ptr(alarm)); + fake_osi_alarm_set_on_mloop_.alarm = nullptr; + fake_osi_alarm_set_on_mloop_.interval_ms = 0; + fake_osi_alarm_set_on_mloop_.cb = nullptr; + fake_osi_alarm_set_on_mloop_.data = nullptr; + } +} + void alarm_cancel(alarm_t* alarm) { inc_func_call_count(__func__); - fake_osi_alarm_set_on_mloop_.interval_ms = 0; - fake_osi_alarm_set_on_mloop_.cb = nullptr; - fake_osi_alarm_set_on_mloop_.data = nullptr; + fake_osi_alarm_clear(alarm); +} + +void alarm_cleanup(void) { + previous_fake_osi_alarms_.clear(); + fake_osi_alarm_clear(nullptr); + + inc_func_call_count(__func__); } -void alarm_cleanup(void) { inc_func_call_count(__func__); } void alarm_debug_dump(int fd) { inc_func_call_count(__func__); } void alarm_free(alarm_t* alarm) { + fake_osi_alarm_clear(alarm); uint8_t* ptr = (uint8_t*)alarm; delete[] ptr; inc_func_call_count(__func__); @@ -363,6 +410,14 @@ void alarm_set(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) { inc_func_call_count(__func__); + + if (fake_osi_alarm_set_on_mloop_.alarm != nullptr) { + bluetooth::log::info("Queuing alarm {}", fmt::ptr(fake_osi_alarm_set_on_mloop_.alarm)); + previous_fake_osi_alarms_.push_back(fake_osi_alarm_set_on_mloop_); + } + + bluetooth::log::info("Adding alarm {}", fmt::ptr(alarm)); + fake_osi_alarm_set_on_mloop_.alarm = alarm; fake_osi_alarm_set_on_mloop_.interval_ms = interval_ms; fake_osi_alarm_set_on_mloop_.cb = cb; fake_osi_alarm_set_on_mloop_.data = data; -- GitLab From 83597fe1687932b169a8f4abb57b68ba47fa664b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Thu, 17 Oct 2024 15:55:45 +0000 Subject: [PATCH 352/875] leaudio: Fix race when switching between Sink and Source stream It is possible that Bluetooth stack will close the stream when Audio HAL resumes Local Source just after Suspending Local Sink. It will result in Audio Player being progressing with playing but there is not Audio on the Bluetooth device. Bug: 372120241 Flag: Exempt, regression tested with unit test, new test added Test: atest bluetooth_le_audio_client_test Change-Id: Ic9beb4af61917d9213a77b026779723c5d7b1f7c --- system/bta/le_audio/client.cc | 9 ++- system/bta/le_audio/le_audio_client_test.cc | 78 +++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 41646a0292f..01c2856e99f 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -4221,6 +4221,7 @@ public: if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { if (IsDirectionAvailableForCurrentConfiguration( group, bluetooth::le_audio::types::kLeAudioDirectionSink)) { + StopSuspendTimeout(); StartSendingAudio(active_group_id_); } else { log::warn( @@ -4286,8 +4287,6 @@ public: "r_state: " + ToString(audio_receiver_state_) + ", s_state: " + ToString(audio_sender_state_)); - StartVbcCloseTimeout(); - /* Note: This callback is from audio hal driver. * Bluetooth peer is a Source for Audio Framework. * e.g. Peer is microphone. @@ -4312,6 +4311,11 @@ public: if ((audio_sender_state_ == AudioState::IDLE) || (audio_sender_state_ == AudioState::READY_TO_RELEASE)) { OnAudioSuspend(); + } else { + /* If the local sink direction is used, we want to monitor + * if back channel is actually needed. + */ + StartVbcCloseTimeout(); } log::info("OUT: audio_receiver_state_: {}, audio_sender_state_: {}", @@ -4472,6 +4476,7 @@ public: if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { if (IsDirectionAvailableForCurrentConfiguration( group, bluetooth::le_audio::types::kLeAudioDirectionSource)) { + StopSuspendTimeout(); StartReceivingAudio(active_group_id_); } else { log::warn( diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 333f4e8573b..05a26249ac4 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -1442,6 +1442,7 @@ protected: void SetUp() override { __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); init_message_loop_thread(); + reset_mock_function_count_map(); ON_CALL(controller_, SupportsBleConnectedIsochronousStreamCentral).WillByDefault(Return(true)); ON_CALL(controller_, SupportsBleConnectedIsochronousStreamPeripheral) .WillByDefault(Return(true)); @@ -9914,6 +9915,83 @@ TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) { Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); } +TEST_F(UnicastTest, SwitchBetweenMicrophoneAndSoundEffectScenario) { + const RawAddress test_address0 = GetTestAddress(0); + int group_id = bluetooth::groups::kGroupUnknown; + + /* Scenario: + * 1. User starts Recording - this creates bidiretional CISes + * 2. User stops recording - this starts suspend timeout (500ms) + * 3. Since user touch the screen it generates touch tone - this shall reuse existing CISes when + * it happens 500ms before stop + */ + SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo, + codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt, + default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/, + true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, + 0 /*rank*/); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnConnectionState(ConnectionState::CONNECTED, test_address0)) + .Times(1); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) + .WillOnce(DoAll(SaveArg<1>(&group_id))); + + ConnectLeAudio(test_address0); + ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); + + // Audio sessions are started only when device gets active + EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1); + LeAudioClient::Get()->GroupSetActive(group_id); + SyncOnMainLoop(); + + // When the local audio source resumes we have no knowledge of recording + EXPECT_CALL(mock_state_machine_, + StartStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, _, _)) + .Times(1); + + log::info("Start Microphone recording - bidirectional CISes are expected"); + UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC); + LocalAudioSinkResume(); + + ASSERT_EQ(0, get_func_call_count("alarm_set_on_mloop")); + SyncOnMainLoop(); + + Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); + Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); + Mock::VerifyAndClearExpectations(&mock_state_machine_); + + // Verify Data transfer on one audio source cis + uint8_t cis_count_out = 0; + uint8_t cis_count_in = 1; + TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60); + + log::info("Suspend microphone recording - suspend timeout is not fired"); + LocalAudioSinkSuspend(); + SyncOnMainLoop(); + + // VBC and Suspend + ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop")); + ASSERT_EQ(0, get_func_call_count("alarm_cancel")); + + log::info("Resume local source with touch tone - expect suspend timeout to be canceled"); + + UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION); + LocalAudioSourceResume(); + SyncOnMainLoop(); + + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + + auto group = streaming_groups.at(group_id); + group->PrintDebugState(); + + // Verify Data transfer on one audio source and sink cis + cis_count_out = 1; + cis_count_in = 0; + TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60); +} + /* When a certain context is unavailable and not supported we should stream * as UNSPECIFIED for the backwards compatibility. * Since UNSPECIFIED is available, put the UNSPECIFIED into the metadata instead -- GitLab From 8f824a3eeaccf0ef002f5c93946a6494f5da02a5 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 17 Oct 2024 09:29:38 -0700 Subject: [PATCH 353/875] Remove //vendor external visibility on libbluetooth_hci_pdl Bug: 370993756 Test: m com.android.btservices Flag: EXEMPT, build change Change-Id: Iaa6390d58cd19fa51cab6a7578c4fe2602f36645 --- system/pdl/hci/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/system/pdl/hci/Android.bp b/system/pdl/hci/Android.bp index 482095e00dc..354d500300a 100644 --- a/system/pdl/hci/Android.bp +++ b/system/pdl/hci/Android.bp @@ -47,7 +47,6 @@ cc_library_static { visibility: [ "//hardware/interfaces/bluetooth/aidl/vts", "//packages/modules/Bluetooth/system:__subpackages__", - "//vendor:__subpackages__", ], apex_available: [ "com.android.btservices", -- GitLab From 50ed2fa5b07a44be88cdc9714f1c759176df2ee2 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Tue, 1 Oct 2024 21:57:43 +0000 Subject: [PATCH 354/875] Remove leaudio_broadcast_volume_control_for_connected_devices flag Bug: 307408418 Bug: 329163385 Test: m com.android.btservices Test: atest VolumeControlServiceTest Change-Id: Ifd5aa851c25c433f0a0c7d17e16e62082532de65 --- .../bluetooth/vc/VolumeControlService.java | 106 ++++++++---------- .../vc/VolumeControlServiceTest.java | 48 +++----- framework/api/system-current.txt | 4 +- .../bluetooth/BluetoothVolumeControl.java | 4 - framework/lint-baseline.xml | 11 -- 5 files changed, 64 insertions(+), 109 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index a7de3ae84a4..b2c6669cf5d 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -480,9 +480,6 @@ public class VolumeControlService extends ProfileService { } void setDeviceVolume(BluetoothDevice device, int volume, boolean isGroupOp) { - if (!Flags.leaudioBroadcastVolumeControlForConnectedDevices()) { - return; - } Log.d( TAG, "setDeviceVolume: " + device + ", volume: " + volume + ", isGroupOp: " + isGroupOp); @@ -643,16 +640,14 @@ public class VolumeControlService extends ProfileService { } } - if (Flags.leaudioBroadcastVolumeControlForConnectedDevices()) { - // using tempCallbackList is a hack to keep using 'notifyDevicesVolumeChanged' - // without making any extra modification - RemoteCallbackList tempCallbackList = - new RemoteCallbackList<>(); + // using tempCallbackList is a hack to keep using 'notifyDevicesVolumeChanged' + // without making any extra modification + RemoteCallbackList tempCallbackList = + new RemoteCallbackList<>(); - tempCallbackList.register(callback); - notifyDevicesVolumeChanged(tempCallbackList, getDevices(), Optional.empty()); - tempCallbackList.unregister(callback); - } + tempCallbackList.register(callback); + notifyDevicesVolumeChanged(tempCallbackList, getDevices(), Optional.empty()); + tempCallbackList.unregister(callback); } void registerCallback(IBluetoothVolumeControlCallback callback) { @@ -735,37 +730,33 @@ public class VolumeControlService extends ProfileService { mGroupVolumeCache.put(groupId, volume); mGroupMuteCache.put(groupId, mute); - if (Flags.leaudioBroadcastVolumeControlForConnectedDevices()) { - LeAudioService leAudioService = mFactory.getLeAudioService(); - if (leAudioService != null) { - int currentlyActiveGroupId = leAudioService.getActiveGroupId(); - if (currentlyActiveGroupId == IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID - || groupId != currentlyActiveGroupId) { - if (!Flags.leaudioBroadcastVolumeControlPrimaryGroupOnly()) { - Log.i( - TAG, - "Skip updating to audio system if not updating volume for current" - + " active group"); - return; - } - BassClientService bassClientService = mFactory.getBassClientService(); - if (bassClientService == null - || bassClientService.getSyncedBroadcastSinks().stream() - .map(dev -> leAudioService.getGroupId(dev)) - .noneMatch( - id -> - id == groupId - && leAudioService.isPrimaryGroup(id))) { - Log.i( - TAG, - "Skip updating to audio system if not updating volume for current" - + " active group in unicast or primary group in broadcast"); - return; - } + LeAudioService leAudioService = mFactory.getLeAudioService(); + if (leAudioService != null) { + int currentlyActiveGroupId = leAudioService.getActiveGroupId(); + if (currentlyActiveGroupId == IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID + || groupId != currentlyActiveGroupId) { + if (!Flags.leaudioBroadcastVolumeControlPrimaryGroupOnly()) { + Log.i( + TAG, + "Skip updating to audio system if not updating volume for current" + + " active group"); + return; + } + BassClientService bassClientService = mFactory.getBassClientService(); + if (bassClientService == null + || bassClientService.getSyncedBroadcastSinks().stream() + .map(dev -> leAudioService.getGroupId(dev)) + .noneMatch( + id -> id == groupId && leAudioService.isPrimaryGroup(id))) { + Log.i( + TAG, + "Skip updating to audio system if not updating volume for current" + + " active group in unicast or primary group in broadcast"); + return; } - } else { - Log.w(TAG, "leAudioService not available"); } + } else { + Log.w(TAG, "leAudioService not available"); } int streamType = getBluetoothContextualVolumeStream(); @@ -846,27 +837,24 @@ public class VolumeControlService extends ProfileService { return; } - if (Flags.leaudioBroadcastVolumeControlForConnectedDevices()) { - Log.i(TAG, "handleVolumeControlChanged: " + device + "; volume: " + volume); - if (device == null) { - // notify group devices volume changed - LeAudioService leAudioService = mFactory.getLeAudioService(); - if (leAudioService != null) { - synchronized (mCallbacks) { - notifyDevicesVolumeChanged( - mCallbacks, - leAudioService.getGroupDevices(groupId), - Optional.of(volume)); - } - } else { - Log.w(TAG, "leAudioService not available"); - } - } else { - // notify device volume changed + Log.i(TAG, "handleVolumeControlChanged: " + device + "; volume: " + volume); + if (device == null) { + // notify group devices volume changed + LeAudioService leAudioService = mFactory.getLeAudioService(); + if (leAudioService != null) { synchronized (mCallbacks) { notifyDevicesVolumeChanged( - mCallbacks, Arrays.asList(device), Optional.of(volume)); + mCallbacks, + leAudioService.getGroupDevices(groupId), + Optional.of(volume)); } + } else { + Log.w(TAG, "leAudioService not available"); + } + } else { + // notify device volume changed + synchronized (mCallbacks) { + notifyDevicesVolumeChanged(mCallbacks, Arrays.asList(device), Optional.of(volume)); } } 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 b681a96fb8e..22ec653e36e 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 @@ -88,6 +88,7 @@ public class VolumeControlServiceTest { private static final int MEDIA_MAX_VOL = 25; private static final int CALL_MIN_VOL = 1; private static final int CALL_MAX_VOL = 8; + private static final int TEST_GROUP_ID = 1; private BroadcastReceiver mVolumeControlIntentReceiver; @@ -570,7 +571,7 @@ public class VolumeControlServiceTest { new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); stackEvent.device = null; - stackEvent.valueInt1 = 1; // groupId + stackEvent.valueInt1 = TEST_GROUP_ID; // groupId stackEvent.valueBool1 = false; // isMuted stackEvent.valueBool2 = true; // isAutonomous @@ -591,10 +592,9 @@ public class VolumeControlServiceTest { @Test public void testAutonomousVolumeStateChange() { - // TODO: b/329163385 - This test should be modified to run without having to set the flag to - // a specific value - mSetFlagsRule.disableFlags( - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES); + // Make device Active now. This will trigger setting volume to AF + when(mLeAudioService.getActiveGroupId()).thenReturn(TEST_GROUP_ID); + doReturn(AudioManager.MODE_IN_CALL).when(mAudioManager).getMode(); testVolumeCalculations(AudioManager.STREAM_VOICE_CALL, CALL_MIN_VOL, CALL_MAX_VOL); @@ -605,25 +605,23 @@ public class VolumeControlServiceTest { /** Test if autonomous Mute/Unmute propagates the event to audio manager. */ @Test public void testAutonomousMuteUnmute() { - // TODO: b/329163385 - This test should be modified to run without having to set the flag to - // a specific value - mSetFlagsRule.disableFlags( - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES); int streamType = AudioManager.STREAM_MUSIC; int streamVol = getLeAudioVolume(19, MEDIA_MIN_VOL, MEDIA_MAX_VOL, streamType); doReturn(false).when(mAudioManager).isStreamMute(eq(AudioManager.STREAM_MUSIC)); // Verify that muting LeAudio device, sets the mute state on the audio device + // Make device Active now. This will trigger setting volume to AF + when(mLeAudioService.getActiveGroupId()).thenReturn(TEST_GROUP_ID); - generateVolumeStateChanged(null, 1, streamVol, 0, true, true); + generateVolumeStateChanged(null, TEST_GROUP_ID, streamVol, 0, true, true); verify(mAudioManager) .adjustStreamVolume(eq(streamType), eq(AudioManager.ADJUST_MUTE), anyInt()); doReturn(true).when(mAudioManager).isStreamMute(eq(AudioManager.STREAM_MUSIC)); // Verify that unmuting LeAudio device, unsets the mute state on the audio device - generateVolumeStateChanged(null, 1, streamVol, 0, false, true); + generateVolumeStateChanged(null, TEST_GROUP_ID, streamVol, 0, false, true); verify(mAudioManager) .adjustStreamVolume(eq(streamType), eq(AudioManager.ADJUST_UNMUTE), anyInt()); } @@ -650,10 +648,6 @@ public class VolumeControlServiceTest { /** Test Active Group change */ @Test public void testActiveGroupChange() throws Exception { - // TODO: b/329163385 - This test should be modified to run without having to set the flag to - // a specific value - mSetFlagsRule.disableFlags( - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES); int groupId_1 = 1; int volume_groupId_1 = 6; @@ -666,6 +660,8 @@ public class VolumeControlServiceTest { mServiceBinder.setGroupVolume(groupId_2, volume_groupId_2, mAttributionSource); + // Make device Active now. This will trigger setting volume to AF + when(mLeAudioService.getActiveGroupId()).thenReturn(groupId_1); mServiceBinder.setGroupActive(groupId_1, true, mAttributionSource); // Expected index for STREAM_MUSIC @@ -673,6 +669,8 @@ public class VolumeControlServiceTest { (int) Math.round((double) (volume_groupId_1 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); + // Make device Active now. This will trigger setting volume to AF + when(mLeAudioService.getActiveGroupId()).thenReturn(groupId_2); mServiceBinder.setGroupActive(groupId_2, true, mAttributionSource); expectedVol = @@ -751,10 +749,7 @@ public class VolumeControlServiceTest { /** Test if phone will set volume which is read from the buds */ @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES, - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_PRIMARY_GROUP_ONLY - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_PRIMARY_GROUP_ONLY) public void testConnectedDeviceWithUserPersistFlagSet() throws Exception { int groupId = 1; int volumeDevice = 56; @@ -1118,9 +1113,6 @@ public class VolumeControlServiceTest { @Test public void testServiceBinderSetDeviceVolumeMethods() throws Exception { - mSetFlagsRule.enableFlags( - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES); - int groupId = 1; int groupVolume = 56; int deviceOneVolume = 46; @@ -1269,8 +1261,6 @@ public class VolumeControlServiceTest { @Test public void testServiceBinderRegisterVolumeChangedCallbackWhenDeviceAlreadyConnected() throws Exception { - mSetFlagsRule.enableFlags( - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES); int groupId = 1; int deviceOneVolume = 46; int deviceTwoVolume = 36; @@ -1323,8 +1313,6 @@ public class VolumeControlServiceTest { @Test public void testServiceBinderTestNotifyNewRegisteredCallback() throws Exception { - mSetFlagsRule.enableFlags( - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES); int groupId = 1; int deviceOneVolume = 46; int deviceTwoVolume = 36; @@ -1418,9 +1406,6 @@ public class VolumeControlServiceTest { /** Test Volume Control changed callback. */ @Test public void testVolumeControlChangedCallback() throws Exception { - mSetFlagsRule.enableFlags( - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES); - int groupId = 1; int groupVolume = 56; int deviceOneVolume = 46; @@ -1465,10 +1450,7 @@ public class VolumeControlServiceTest { /** Test Volume Control changed for broadcast primary group. */ @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES, - Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_PRIMARY_GROUP_ONLY - }) + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_PRIMARY_GROUP_ONLY) public void testVolumeControlChangedForBroadcastPrimaryGroup() throws Exception { int groupId = 1; int groupVolume = 30; diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index b0d2f78d71d..f7e87588ba4 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -1124,7 +1124,7 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isVolumeOffsetAvailable(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothVolumeControl.Callback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_volume_control_for_connected_devices") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setDeviceVolume(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int, boolean); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setDeviceVolume(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int, boolean); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolumeOffset(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0xffffff01, to=255) int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolumeOffset(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull android.bluetooth.BluetoothVolumeControl.Callback); @@ -1132,7 +1132,7 @@ package android.bluetooth { } public static interface BluetoothVolumeControl.Callback { - method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_volume_control_for_connected_devices") public default void onDeviceVolumeChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int); + method public default void onDeviceVolumeChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int); method public default void onVolumeOffsetAudioDescriptionChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @NonNull String); method public default void onVolumeOffsetAudioLocationChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=1, to=255) int, @IntRange(from=0xffffff01, to=255) int); method @Deprecated public default void onVolumeOffsetChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0xffffff01, to=255) int); diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index d14bcb1ca57..4fa65ad2883 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -21,7 +21,6 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import android.annotation.CallbackExecutor; -import android.annotation.FlaggedApi; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -39,7 +38,6 @@ import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; -import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.GuardedBy; import java.util.Collections; @@ -156,7 +154,6 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose * @param volume level * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES) @SystemApi default void onDeviceVolumeChanged( @NonNull BluetoothDevice device, @IntRange(from = 0, to = 255) int volume) {} @@ -717,7 +714,6 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose * @throws IllegalArgumentException if volume is not in the range [0, 255]. * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) diff --git a/framework/lint-baseline.xml b/framework/lint-baseline.xml index 99d358bfd3f..566277df29a 100644 --- a/framework/lint-baseline.xml +++ b/framework/lint-baseline.xml @@ -56,17 +56,6 @@ column="18"/>
    - - - - Date: Wed, 16 Oct 2024 16:20:24 -0700 Subject: [PATCH 355/875] HearingAid profile: rm impossible null handler Use final & injected dependency Update test to TestLooper & truth Split test to actionable smaller test Fix: 368527278 Bug: 368527278 Test: atest BluetoothInstrumentationTest:HearingAidServiceTest Test: atest BluetoothInstrumentationTest:HearingAidStateMachineTest Flag: Exempt refactor Change-Id: Id5bf8f6d8daf8057b313905e1a13cb993667f2f3 --- .../hearingaid/HearingAidService.java | 168 +-- .../hearingaid/HearingAidStackEvent.java | 9 +- .../hearingaid/HearingAidStateMachine.java | 375 +++-- .../hearingaid/HearingAidServiceTest.java | 1207 +++++------------ .../HearingAidStateMachineTest.java | 317 ++--- system/include/hardware/bt_hearing_aid.h | 1 + 6 files changed, 668 insertions(+), 1409 deletions(-) diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java index e7d4ed900d1..1cc5a280a3d 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java @@ -18,6 +18,11 @@ package com.android.bluetooth.hearingaid; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +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.BluetoothDevice; @@ -27,7 +32,6 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothHearingAid; import android.content.AttributionSource; -import android.content.Context; import android.content.Intent; import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; @@ -62,38 +66,63 @@ import java.util.concurrent.ConcurrentHashMap; /** Provides Bluetooth HearingAid profile, as a service in the Bluetooth application. */ public class HearingAidService extends ProfileService { - private static final String TAG = "HearingAidService"; + private static final String TAG = HearingAidService.class.getSimpleName(); - // Timeout for state machine thread join, to prevent potential ANR. private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; // Upper limit of all HearingAid devices: Bonded or Connected private static final int MAX_HEARING_AID_STATE_MACHINES = 10; - private static HearingAidService sHearingAidService; - private AdapterService mAdapterService; - private DatabaseManager mDatabaseManager; - private HandlerThread mStateMachinesThread; - private BluetoothDevice mActiveDevice; + private static HearingAidService sHearingAidService; - @VisibleForTesting HearingAidNativeInterface mHearingAidNativeInterface; - @VisibleForTesting AudioManager mAudioManager; + private final AdapterService mAdapterService; + private final DatabaseManager mDatabaseManager; + private final HearingAidNativeInterface mNativeInterface; + private final AudioManager mAudioManager; + private final HandlerThread mStateMachinesThread; + private final Looper mStateMachinesLooper; + private final Handler mHandler; private final Map mStateMachines = new HashMap<>(); private final Map mDeviceHiSyncIdMap = new ConcurrentHashMap<>(); private final Map mDeviceCapabilitiesMap = new HashMap<>(); private final Map mHiSyncIdConnectedMap = new HashMap<>(); - private long mActiveDeviceHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID; - - private Handler mHandler = new Handler(Looper.getMainLooper()); private final AudioManagerOnAudioDevicesAddedCallback mAudioManagerOnAudioDevicesAddedCallback = new AudioManagerOnAudioDevicesAddedCallback(); private final AudioManagerOnAudioDevicesRemovedCallback mAudioManagerOnAudioDevicesRemovedCallback = new AudioManagerOnAudioDevicesRemovedCallback(); - public HearingAidService(Context ctx) { - super(ctx); + private BluetoothDevice mActiveDevice; + private long mActiveDeviceHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID; + + public HearingAidService(AdapterService adapterService) { + this(adapterService, null, HearingAidNativeInterface.getInstance()); + } + + @VisibleForTesting + HearingAidService( + AdapterService adapterService, + Looper looper, + HearingAidNativeInterface nativeInterface) { + super(requireNonNull(adapterService)); + mAdapterService = adapterService; + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); + if (looper == null) { + mHandler = new Handler(requireNonNull(Looper.getMainLooper())); + mStateMachinesThread = new HandlerThread("HearingAidService.StateMachines"); + mStateMachinesThread.start(); + mStateMachinesLooper = mStateMachinesThread.getLooper(); + } else { + mHandler = new Handler(looper); + mStateMachinesThread = null; + mStateMachinesLooper = looper; + } + mNativeInterface = requireNonNull(nativeInterface); + mAudioManager = requireNonNull(getSystemService(AudioManager.class)); + + setHearingAidService(this); + mNativeInterface.init(); } public static boolean isEnabled() { @@ -105,56 +134,11 @@ public class HearingAidService extends ProfileService { return new BluetoothHearingAidBinder(this); } - @Override - public void start() { - Log.d(TAG, "start()"); - if (sHearingAidService != null) { - throw new IllegalStateException("start() called twice"); - } - - mAdapterService = - Objects.requireNonNull( - AdapterService.getAdapterService(), - "AdapterService cannot be null when HearingAidService starts"); - mHearingAidNativeInterface = - Objects.requireNonNull( - HearingAidNativeInterface.getInstance(), - "HearingAidNativeInterface cannot be null when HearingAidService starts"); - mDatabaseManager = - Objects.requireNonNull( - mAdapterService.getDatabase(), - "DatabaseManager cannot be null when HearingAidService starts"); - mAudioManager = getSystemService(AudioManager.class); - Objects.requireNonNull( - mAudioManager, "AudioManager cannot be null when HearingAidService starts"); - - // Start handler thread for state machines - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("HearingAidService.StateMachines"); - mStateMachinesThread.start(); - - // Clear HiSyncId map, capabilities map and HiSyncId Connected map - mDeviceHiSyncIdMap.clear(); - mDeviceCapabilitiesMap.clear(); - mHiSyncIdConnectedMap.clear(); - - // Mark service as started - setHearingAidService(this); - - // Initialize native interface - mHearingAidNativeInterface.init(); - } - @Override public void stop() { Log.d(TAG, "stop()"); - if (sHearingAidService == null) { - Log.w(TAG, "stop() called before start()"); - return; - } // Cleanup native interface - mHearingAidNativeInterface.cleanup(); - mHearingAidNativeInterface = null; + mNativeInterface.cleanup(); // Mark service as stopped setHearingAidService(null); @@ -163,7 +147,6 @@ public class HearingAidService extends ProfileService { synchronized (mStateMachines) { for (HearingAidStateMachine sm : mStateMachines.values()) { sm.doQuit(); - sm.cleanup(); } mStateMachines.clear(); } @@ -177,29 +160,15 @@ public class HearingAidService extends ProfileService { try { mStateMachinesThread.quitSafely(); mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); - mStateMachinesThread = null; } catch (InterruptedException e) { // Do not rethrow as we are shutting down anyway } } - if (mHandler != null) { - mHandler.removeCallbacksAndMessages(null); - mHandler = null; - } + mHandler.removeCallbacksAndMessages(null); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerOnAudioDevicesAddedCallback); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerOnAudioDevicesRemovedCallback); - - // Clear AdapterService, HearingAidNativeInterface - mAudioManager = null; - mHearingAidNativeInterface = null; - mAdapterService = null; - } - - @Override - public void cleanup() { - Log.d(TAG, "cleanup()"); } /** @@ -263,7 +232,7 @@ public class HearingAidService extends ProfileService { if (smConnect == null) { Log.e(TAG, "Cannot connect to " + device + " : no state machine"); } - smConnect.sendMessage(HearingAidStateMachine.CONNECT); + smConnect.sendMessage(HearingAidStateMachine.MESSAGE_CONNECT); } for (BluetoothDevice storedDevice : mDeviceHiSyncIdMap.keySet()) { @@ -279,7 +248,7 @@ public class HearingAidService extends ProfileService { Log.e(TAG, "Ignored connect request for " + device + " : no state machine"); continue; } - sm.sendMessage(HearingAidStateMachine.CONNECT); + sm.sendMessage(HearingAidStateMachine.MESSAGE_CONNECT); } if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID && !device.equals(storedDevice)) { @@ -316,7 +285,7 @@ public class HearingAidService extends ProfileService { "Ignored disconnect request for " + device + " : no state machine"); continue; } - sm.sendMessage(HearingAidStateMachine.DISCONNECT); + sm.sendMessage(HearingAidStateMachine.MESSAGE_DISCONNECT); } if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID && !device.equals(storedDevice)) { @@ -402,7 +371,7 @@ public class HearingAidService extends ProfileService { if (!Utils.arrayContains(featureUuids, BluetoothUuid.HEARING_AID)) { continue; } - int connectionState = BluetoothProfile.STATE_DISCONNECTED; + int connectionState = STATE_DISCONNECTED; HearingAidStateMachine sm = mStateMachines.get(device); if (sm != null) { connectionState = sm.getConnectionState(); @@ -457,7 +426,7 @@ public class HearingAidService extends ProfileService { synchronized (mStateMachines) { HearingAidStateMachine sm = mStateMachines.get(device); if (sm == null) { - return BluetoothProfile.STATE_DISCONNECTED; + return STATE_DISCONNECTED; } return sm.getConnectionState(); } @@ -507,7 +476,7 @@ public class HearingAidService extends ProfileService { } void setVolume(int volume) { - mHearingAidNativeInterface.setVolume(volume); + mNativeInterface.setVolume(volume); } public long getHiSyncId(BluetoothDevice device) { @@ -567,7 +536,7 @@ public class HearingAidService extends ProfileService { return true; } - if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) { + if (getConnectionState(device) != STATE_CONNECTED) { Log.e(TAG, "setActiveDevice(" + device + "): failed because device not connected"); return false; } @@ -597,7 +566,7 @@ public class HearingAidService extends ProfileService { return activeDevices; } for (BluetoothDevice device : mDeviceHiSyncIdMap.keySet()) { - if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) { + if (getConnectionState(device) != STATE_CONNECTED) { continue; } if (mDeviceHiSyncIdMap.get(device) == mActiveDeviceHiSyncId) { @@ -639,8 +608,8 @@ public class HearingAidService extends ProfileService { if (sm == null) { if (stackEvent.type == HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { switch (stackEvent.valueInt1) { - case HearingAidStackEvent.CONNECTION_STATE_CONNECTED: - case HearingAidStackEvent.CONNECTION_STATE_CONNECTING: + case STATE_CONNECTED: + case STATE_CONNECTING: sm = getOrCreateStateMachine(device); break; default: @@ -652,7 +621,7 @@ public class HearingAidService extends ProfileService { Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); return; } - sm.sendMessage(HearingAidStateMachine.STACK_EVENT, stackEvent); + sm.sendMessage(HearingAidStateMachine.MESSAGE_STACK_EVENT, stackEvent); } } @@ -721,12 +690,8 @@ public class HearingAidService extends ProfileService { return null; } Log.d(TAG, "Creating a new state machine for " + device); - sm = - HearingAidStateMachine.make( - device, - this, - mHearingAidNativeInterface, - mStateMachinesThread.getLooper()); + sm = new HearingAidStateMachine(this, device, mNativeInterface, mStateMachinesLooper); + sm.start(); mStateMachines.put(device, sm); return sm; } @@ -747,9 +712,7 @@ public class HearingAidService extends ProfileService { } // Note: This is just a safety check for handling illegal call - setActiveDevice(null). - if (device == null - && stopAudio - && getConnectionState(mActiveDevice) == BluetoothProfile.STATE_CONNECTED) { + if (device == null && stopAudio && getConnectionState(mActiveDevice) == STATE_CONNECTED) { Log.e( TAG, "Illegal arguments: stopAudio should be false when the active hearing aid " @@ -816,7 +779,7 @@ public class HearingAidService extends ProfileService { if (sm == null) { return; } - if (sm.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) { + if (sm.getConnectionState() != STATE_DISCONNECTED) { Log.i(TAG, "Disconnecting device because it was unbonded."); disconnect(device); return; @@ -836,7 +799,6 @@ public class HearingAidService extends ProfileService { } Log.i(TAG, "removeStateMachine: removing state machine for device: " + device); sm.doQuit(); - sm.cleanup(); mStateMachines.remove(device); } } @@ -863,7 +825,7 @@ public class HearingAidService extends ProfileService { + toState); return; } - if (toState == BluetoothProfile.STATE_CONNECTED) { + if (toState == STATE_CONNECTED) { long myHiSyncId = getHiSyncId(device); if (myHiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID || getConnectedPeerDevices(myHiSyncId).size() == 1) { @@ -876,13 +838,13 @@ public class HearingAidService extends ProfileService { mHiSyncIdConnectedMap.put(myHiSyncId, true); } } - if (fromState == BluetoothProfile.STATE_CONNECTED && getConnectedDevices().isEmpty()) { + if (fromState == STATE_CONNECTED && getConnectedDevices().isEmpty()) { long myHiSyncId = getHiSyncId(device); mHiSyncIdConnectedMap.put(myHiSyncId, false); // ActiveDeviceManager will call removeActiveDevice(). } // Check if the device is disconnected - if unbond, remove the state machine - if (toState == BluetoothProfile.STATE_DISCONNECTED) { + if (toState == STATE_DISCONNECTED) { int bondState = mAdapterService.getBondState(device); if (bondState == BluetoothDevice.BOND_NONE) { Log.d(TAG, device + " is unbond. Remove state machine"); @@ -980,7 +942,7 @@ public class HearingAidService extends ProfileService { public int getConnectionState(BluetoothDevice device, AttributionSource source) { HearingAidService service = getService(source); if (service == null) { - return BluetoothProfile.STATE_DISCONNECTED; + return STATE_DISCONNECTED; } return service.getConnectionState(device); diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java index 35bd4e6eeb9..522dedc03ed 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java @@ -22,19 +22,12 @@ import android.bluetooth.BluetoothDevice; * Stack event sent via a callback from JNI to Java, or generated internally by the Hearing Aid * State Machine. */ -public class HearingAidStackEvent { +class HearingAidStackEvent { // Event types for STACK_EVENT message (coming from native) private static final int EVENT_TYPE_NONE = 0; public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1; public static final int EVENT_TYPE_DEVICE_AVAILABLE = 2; - // Do not modify without updating the HAL bt_hearing_aid.h files. - // Match up with enum class ConnectionState of bt_hearing_aid.h. - static final int CONNECTION_STATE_DISCONNECTED = 0; - static final int CONNECTION_STATE_CONNECTING = 1; - static final int CONNECTION_STATE_CONNECTED = 2; - static final int CONNECTION_STATE_DISCONNECTING = 3; - public int type; public BluetoothDevice device; public int valueInt1; diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java index 3a701d5c655..bab78a2c6a6 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java @@ -14,22 +14,40 @@ * limitations under the License. */ -/** - * Bluetooth HearingAid StateMachine. There is one instance per remote device. - "Disconnected" and - * "Connected" are steady states. - "Connecting" and "Disconnecting" are transient states until the - * connection / disconnection is completed. - * - *

    (Disconnected) | ^ CONNECT | | DISCONNECTED V | (Connecting)<--->(Disconnecting) | ^ CONNECTED - * | | DISCONNECT V | (Connected) NOTES: - If state machine is in "Connecting" state and the remote - * device sends DISCONNECT request, the state machine transitions to "Disconnecting" state. - - * Similarly, if the state machine is in "Disconnecting" state and the remote device sends CONNECT - * request, the state machine transitions to "Connecting" state. - * - *

    DISCONNECT (Connecting) ---------------> (Disconnecting) <--------------- CONNECT - */ +// Bluetooth HearingAid StateMachine. There is one instance per remote device. +// - "Disconnected" and "Connected" are steady states. +// - "Connecting" and "Disconnecting" are transient states until the +// connection / disconnection is completed. +// +// +// (Disconnected) +// | ^ +// CONNECT | | DISCONNECTED +// V | +// (Connecting)<--->(Disconnecting) +// | ^ +// CONNECTED | | DISCONNECT +// V | +// (Connected) +// NOTES: +// - If state machine is in "Connecting" state and the remote device sends +// DISCONNECT request, the state machine transitions to "Disconnecting" state. +// - Similarly, if the state machine is in "Disconnecting" state and the remote device +// sends CONNECT request, the state machine transitions to "Connecting" state. +// +// DISCONNECT +// (Connecting) ---------------> (Disconnecting) +// <--------------- +// CONNECT + package com.android.bluetooth.hearingaid; 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 android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; +import static android.bluetooth.BluetoothProfile.getConnectionStateName; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHearingAid; @@ -49,34 +67,33 @@ import com.android.internal.util.StateMachine; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Duration; import java.util.Scanner; final class HearingAidStateMachine extends StateMachine { - private static final String TAG = "HearingAidStateMachine"; + private static final String TAG = HearingAidStateMachine.class.getSimpleName(); - static final int CONNECT = 1; - static final int DISCONNECT = 2; - @VisibleForTesting static final int STACK_EVENT = 101; - private static final int CONNECT_TIMEOUT = 201; + static final int MESSAGE_CONNECT = 1; + static final int MESSAGE_DISCONNECT = 2; + @VisibleForTesting static final int MESSAGE_STACK_EVENT = 101; + private static final int MESSAGE_CONNECT_TIMEOUT = 201; - // NOTE: the value is not "final" - it is modified in the unit tests - @VisibleForTesting static int sConnectTimeoutMs = 30000; // 30s - - private Disconnected mDisconnected; - private Connecting mConnecting; - private Disconnecting mDisconnecting; - private Connected mConnected; - private int mConnectionState = BluetoothProfile.STATE_DISCONNECTED; - private int mLastConnectionState = -1; - - private HearingAidService mService; - private HearingAidNativeInterface mNativeInterface; + @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(30); + private final Disconnected mDisconnected; + private final Connecting mConnecting; + private final Disconnecting mDisconnecting; + private final Connected mConnected; + private final HearingAidService mService; + private final HearingAidNativeInterface mNativeInterface; private final BluetoothDevice mDevice; + private int mConnectionState = STATE_DISCONNECTED; + private int mLastConnectionState = -1; + HearingAidStateMachine( - BluetoothDevice device, HearingAidService svc, + BluetoothDevice device, HearingAidNativeInterface nativeInterface, Looper looper) { super(TAG, looper); @@ -97,27 +114,11 @@ final class HearingAidStateMachine extends StateMachine { setInitialState(mDisconnected); } - static HearingAidStateMachine make( - BluetoothDevice device, - HearingAidService svc, - HearingAidNativeInterface nativeInterface, - Looper looper) { - Log.i(TAG, "make for device " + device); - HearingAidStateMachine HearingAidSm = - new HearingAidStateMachine(device, svc, nativeInterface, looper); - HearingAidSm.start(); - return HearingAidSm; - } - public void doQuit() { log("doQuit for device " + mDevice); quitNow(); } - public void cleanup() { - log("cleanup for device " + mDevice); - } - @VisibleForTesting class Disconnected extends State { @Override @@ -128,13 +129,13 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mConnectionState = BluetoothProfile.STATE_DISCONNECTED; + mConnectionState = STATE_DISCONNECTED; - removeDeferredMessages(DISCONNECT); + removeDeferredMessages(MESSAGE_DISCONNECT); if (mLastConnectionState != -1) { // Don't broadcast during startup - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED, mLastConnectionState); + broadcastConnectionState(STATE_DISCONNECTED); } } @@ -145,7 +146,7 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; + mLastConnectionState = STATE_DISCONNECTED; } @Override @@ -157,7 +158,7 @@ final class HearingAidStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: + case MESSAGE_CONNECT -> { log("Connecting to " + mDevice); if (!mNativeInterface.connectHearingAid(mDevice)) { Log.e(TAG, "Disconnected: error connecting to " + mDevice); @@ -169,28 +170,27 @@ final class HearingAidStateMachine extends StateMachine { // Reject the request and stay in Disconnected state Log.w(TAG, "Outgoing HearingAid Connecting request rejected: " + mDevice); } - break; - case DISCONNECT: + } + case MESSAGE_DISCONNECT -> { Log.d(TAG, "Disconnected: DISCONNECT: call native disconnect for " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { HearingAidStackEvent event = (HearingAidStackEvent) message.obj; Log.d(TAG, "Disconnected: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, "Disconnected: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -198,10 +198,10 @@ final class HearingAidStateMachine extends StateMachine { // in Disconnected state private void processConnectionEvent(int state) { switch (state) { - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.w(TAG, "Ignore HearingAid DISCONNECTED event: " + mDevice); - break; - case HearingAidStackEvent.CONNECTION_STATE_CONNECTING: + } + case STATE_CONNECTING -> { if (mService.okToConnect(mDevice)) { Log.i(TAG, "Incoming HearingAid Connecting request accepted: " + mDevice); transitionTo(mConnecting); @@ -210,8 +210,8 @@ final class HearingAidStateMachine extends StateMachine { Log.w(TAG, "Incoming HearingAid Connecting request rejected: " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); } - break; - case HearingAidStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { Log.w(TAG, "HearingAid Connected from Disconnected state: " + mDevice); if (mService.okToConnect(mDevice)) { Log.i(TAG, "Incoming HearingAid Connected request accepted: " + mDevice); @@ -221,13 +221,11 @@ final class HearingAidStateMachine extends StateMachine { Log.w(TAG, "Incoming HearingAid Connected request rejected: " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); } - break; - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTING: + } + case STATE_DISCONNECTING -> { Log.w(TAG, "Ignore HearingAid DISCONNECTING event: " + mDevice); - break; - default: - Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); - break; + } + default -> Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); } } } @@ -242,9 +240,9 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - mConnectionState = BluetoothProfile.STATE_CONNECTING; - broadcastConnectionState(BluetoothProfile.STATE_CONNECTING, mLastConnectionState); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + mConnectionState = STATE_CONNECTING; + broadcastConnectionState(STATE_CONNECTING); } @Override @@ -254,8 +252,8 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; - removeMessages(CONNECT_TIMEOUT); + mLastConnectionState = STATE_CONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override @@ -267,10 +265,8 @@ final class HearingAidStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: + case MESSAGE_CONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { Log.w(TAG, "Connecting connection timeout: " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); if (mService.isConnectedPeerDevices(mDevice)) { @@ -281,31 +277,30 @@ final class HearingAidStateMachine extends StateMachine { new HearingAidStackEvent( HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - case DISCONNECT: + disconnectEvent.valueInt1 = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, disconnectEvent); + } + case MESSAGE_DISCONNECT -> { log("Connecting: connection canceled to " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); transitionTo(mDisconnected); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { HearingAidStackEvent event = (HearingAidStackEvent) message.obj; log("Connecting: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Connecting: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, "Connecting: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -313,22 +308,16 @@ final class HearingAidStateMachine extends StateMachine { // in Connecting state private void processConnectionEvent(int state) { switch (state) { - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.w(TAG, "Connecting device disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case HearingAidStackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case HearingAidStackEvent.CONNECTION_STATE_CONNECTING: - break; - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTING: + } + case STATE_CONNECTED -> transitionTo(mConnected); + case STATE_DISCONNECTING -> { Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; + } + default -> Log.e(TAG, "Incorrect state: " + state); } } } @@ -343,9 +332,9 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - mConnectionState = BluetoothProfile.STATE_DISCONNECTING; - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTING, mLastConnectionState); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + mConnectionState = STATE_DISCONNECTING; + broadcastConnectionState(STATE_DISCONNECTING); } @Override @@ -355,8 +344,8 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); + mLastConnectionState = STATE_DISCONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override @@ -368,42 +357,33 @@ final class HearingAidStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - { - Log.w(TAG, "Disconnecting connection timeout: " + mDevice); - mNativeInterface.disconnectHearingAid(mDevice); - HearingAidStackEvent disconnectEvent = - new HearingAidStackEvent( - HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = - HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - } - case DISCONNECT: - deferMessage(message); - break; - case STACK_EVENT: + case MESSAGE_CONNECT, MESSAGE_DISCONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { + Log.w(TAG, "Disconnecting connection timeout: " + mDevice); + mNativeInterface.disconnectHearingAid(mDevice); + HearingAidStackEvent disconnectEvent = + new HearingAidStackEvent( + HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + disconnectEvent.device = mDevice; + disconnectEvent.valueInt1 = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, disconnectEvent); + } + case MESSAGE_STACK_EVENT -> { HearingAidStackEvent event = (HearingAidStackEvent) message.obj; log("Disconnecting: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnecting: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, "Disconnecting: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -411,11 +391,11 @@ final class HearingAidStateMachine extends StateMachine { // in Disconnecting state private void processConnectionEvent(int state) { switch (state) { - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case HearingAidStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { if (mService.okToConnect(mDevice)) { Log.w(TAG, "Disconnecting interrupted: device is connected: " + mDevice); transitionTo(mConnected); @@ -424,8 +404,8 @@ final class HearingAidStateMachine extends StateMachine { Log.w(TAG, "Incoming HearingAid Connected request rejected: " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); } - break; - case HearingAidStackEvent.CONNECTION_STATE_CONNECTING: + } + case STATE_CONNECTING -> { if (mService.okToConnect(mDevice)) { Log.i(TAG, "Disconnecting interrupted: try to reconnect: " + mDevice); transitionTo(mConnecting); @@ -434,12 +414,8 @@ final class HearingAidStateMachine extends StateMachine { Log.w(TAG, "Incoming HearingAid Connecting request rejected: " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); } - break; - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTING: - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; + } + default -> Log.e(TAG, "Incorrect state: " + state); } } } @@ -454,9 +430,9 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mConnectionState = BluetoothProfile.STATE_CONNECTED; - removeDeferredMessages(CONNECT); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTED, mLastConnectionState); + mConnectionState = STATE_CONNECTED; + removeDeferredMessages(MESSAGE_CONNECT); + broadcastConnectionState(STATE_CONNECTED); } @Override @@ -466,7 +442,7 @@ final class HearingAidStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; + mLastConnectionState = STATE_CONNECTED; } @Override @@ -474,10 +450,8 @@ final class HearingAidStateMachine extends StateMachine { log("Connected process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); - break; - case DISCONNECT: + case MESSAGE_CONNECT -> Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); + case MESSAGE_DISCONNECT -> { log("Disconnecting from " + mDevice); if (!mNativeInterface.disconnectHearingAid(mDevice)) { // If error in the native stack, transition directly to Disconnected state. @@ -486,24 +460,23 @@ final class HearingAidStateMachine extends StateMachine { break; } transitionTo(mDisconnecting); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { HearingAidStackEvent event = (HearingAidStackEvent) message.obj; log("Connected: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Connected: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, "Connected: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -511,17 +484,15 @@ final class HearingAidStateMachine extends StateMachine { // in Connected state private void processConnectionEvent(int state) { switch (state) { - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected from " + mDevice + " but still in Acceptlist"); transitionTo(mDisconnected); - break; - case HearingAidStackEvent.CONNECTION_STATE_DISCONNECTING: + } + case STATE_DISCONNECTING -> { Log.i(TAG, "Disconnecting from " + mDevice); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state); - break; + } + default -> Log.e(TAG, "Connection State: " + mDevice + " bad state: " + state); } } } @@ -535,23 +506,22 @@ final class HearingAidStateMachine extends StateMachine { } synchronized boolean isConnected() { - return (getConnectionState() == BluetoothProfile.STATE_CONNECTED); + return (getConnectionState() == STATE_CONNECTED); } - // This method does not check for error condition (newState == prevState) - private void broadcastConnectionState(int newState, int prevState) { + private void broadcastConnectionState(int newState) { log( "Connection state " + mDevice + ": " - + profileStateToString(prevState) + + getConnectionStateName(mLastConnectionState) + "->" - + profileStateToString(newState)); + + getConnectionStateName(newState)); - mService.connectionStateChanged(mDevice, prevState, newState); + mService.connectionStateChanged(mDevice, mLastConnectionState, newState); Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); + intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, mLastConnectionState); intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); intent.addFlags( @@ -565,35 +535,13 @@ final class HearingAidStateMachine extends StateMachine { } private static String messageWhatToString(int what) { - switch (what) { - case CONNECT: - return "CONNECT"; - case DISCONNECT: - return "DISCONNECT"; - case STACK_EVENT: - return "STACK_EVENT"; - case CONNECT_TIMEOUT: - return "CONNECT_TIMEOUT"; - default: - break; - } - return Integer.toString(what); - } - - private static String profileStateToString(int state) { - switch (state) { - case BluetoothProfile.STATE_DISCONNECTED: - return "DISCONNECTED"; - case BluetoothProfile.STATE_CONNECTING: - return "CONNECTING"; - case BluetoothProfile.STATE_CONNECTED: - return "CONNECTED"; - case BluetoothProfile.STATE_DISCONNECTING: - return "DISCONNECTING"; - default: - break; - } - return Integer.toString(state); + return switch (what) { + case MESSAGE_CONNECT -> "CONNECT"; + case MESSAGE_DISCONNECT -> "DISCONNECT"; + case MESSAGE_STACK_EVENT -> "STACK_EVENT"; + case MESSAGE_CONNECT_TIMEOUT -> "CONNECT_TIMEOUT"; + default -> Integer.toString(what); + }; } public void dump(StringBuilder sb) { @@ -613,9 +561,4 @@ final class HearingAidStateMachine extends StateMachine { } scanner.close(); } - - @Override - protected void log(String msg) { - super.log(msg); - } } 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 5b1dceb4864..6576b1b67f3 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 @@ -16,6 +16,17 @@ package com.android.bluetooth.hearingaid; +import static android.bluetooth.BluetoothDevice.BOND_BONDED; +import static android.bluetooth.BluetoothDevice.BOND_BONDING; +import static android.bluetooth.BluetoothDevice.BOND_NONE; +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; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; + import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; @@ -27,8 +38,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -41,13 +51,13 @@ import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; -import android.os.Looper; import android.os.ParcelUuid; import android.os.UserHandle; +import android.os.test.TestLooper; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; -import androidx.test.filters.MediumTest; -import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; @@ -71,53 +81,52 @@ import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import java.time.Duration; import java.util.List; import java.util.concurrent.CompletableFuture; -@MediumTest +@SmallTest @RunWith(AndroidJUnit4.class) public class HearingAidServiceTest { - private static final Duration TIMEOUT = Duration.ofSeconds(1); - - private static final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); - private static final BluetoothDevice mLeftDevice = TestUtils.getTestDevice(mAdapter, 0); - private static final BluetoothDevice mRightDevice = TestUtils.getTestDevice(mAdapter, 1); - private static final BluetoothDevice mSingleDevice = TestUtils.getTestDevice(mAdapter, 2); - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - - private HearingAidService mService; - private HearingAidService.BluetoothHearingAidBinder mServiceBinder; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AudioRoutingManager mAudioRoutingManager; - @Mock private Context mContext; @Mock private DatabaseManager mDatabaseManager; @Mock private HearingAidNativeInterface mNativeInterface; @Mock private AudioManager mAudioManager; - private InOrder mInOrder = null; + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mLeftDevice = TestUtils.getTestDevice(mAdapter, 43); + private final BluetoothDevice mRightDevice = TestUtils.getTestDevice(mAdapter, 23); + private final BluetoothDevice mSingleDevice = TestUtils.getTestDevice(mAdapter, 13); + + private HearingAidService mService; + private HearingAidService.BluetoothHearingAidBinder mBinder; + private InOrder mInOrder; + private TestLooper mLooper; @Before - public void setUp() throws Exception { - mInOrder = inOrder(mContext); + public void setUp() { + mInOrder = inOrder(mAdapterService); + mLooper = new TestLooper(); TestUtils.mockGetSystemService( - mContext, Context.AUDIO_SERVICE, AudioManager.class, mAudioManager); + mAdapterService, Context.AUDIO_SERVICE, AudioManager.class, mAudioManager); CompletableFuture future = new CompletableFuture<>(); future.complete(true); doReturn(future).when(mAudioRoutingManager).activateDeviceProfile(any(), anyInt()); - if (Looper.myLooper() == null) { - Looper.prepare(); - } - - TestUtils.setAdapterService(mAdapterService); + doReturn(CONNECTION_POLICY_ALLOWED) + .when(mDatabaseManager) + .getProfileConnectionPolicy(any(), anyInt()); + doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); + doReturn(BOND_BONDED).when(mAdapterService).getBondState(any()); + doReturn(new ParcelUuid[] {BluetoothUuid.HEARING_AID}) + .when(mAdapterService) + .getRemoteUuids(any()); doAnswer( invocation -> { if (Flags.audioRoutingCentralization()) { @@ -128,45 +137,24 @@ public class HearingAidServiceTest { }) .when(mAdapterService) .getActiveDeviceManager(); - doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); - - HearingAidNativeInterface.setInstance(mNativeInterface); - startService(); - mServiceBinder = (HearingAidService.BluetoothHearingAidBinder) mService.initBinder(); - // Override the timeout value to speed up the test - HearingAidStateMachine.sConnectTimeoutMs = (int) TIMEOUT.toMillis(); // 1s + doReturn(true).when(mNativeInterface).connectHearingAid(any()); + doReturn(true).when(mNativeInterface).disconnectHearingAid(any()); - doReturn(BluetoothDevice.BOND_BONDED) - .when(mAdapterService) - .getBondState(any(BluetoothDevice.class)); - doReturn(new ParcelUuid[] {BluetoothUuid.HEARING_AID}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - } - - @After - public void tearDown() throws Exception { - stopService(); - HearingAidNativeInterface.setInstance(null); - TestUtils.clearAdapterService(mAdapterService); - } - - private void startService() { - mService = new HearingAidService(mContext); - mService.start(); + mService = new HearingAidService(mAdapterService, mLooper.getLooper(), mNativeInterface); mService.setAvailable(true); + mBinder = (HearingAidService.BluetoothHearingAidBinder) mService.initBinder(); } - private void stopService() { + @After + public void tearDown() { mService.stop(); - mService = HearingAidService.getHearingAidService(); - assertThat(mService).isNull(); + assertThat(HearingAidService.getHearingAidService()).isNull(); } @SafeVarargs private void verifyIntentSent(Matcher... matchers) { - mInOrder.verify(mContext, timeout(TIMEOUT.toMillis() * 2)) + mInOrder.verify(mAdapterService) .sendBroadcastAsUser( MockitoHamcrest.argThat(AllOf.allOf(matchers)), eq(UserHandle.ALL), @@ -186,421 +174,175 @@ public class HearingAidServiceTest { hasExtra(BluetoothProfile.EXTRA_STATE, newState), hasExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState)); - if (newState == BluetoothProfile.STATE_CONNECTED) { + if (newState == STATE_CONNECTED) { // ActiveDeviceManager calls setActiveDevice when connected. mService.setActiveDevice(device); - } else if (prevState == BluetoothProfile.STATE_CONNECTED) { + } else if (prevState == STATE_CONNECTED) { if (mService.getConnectedDevices().isEmpty()) { mService.removeActiveDevice(stopAudio); } } } - /** Test getting HearingAid Service: getHearingAidService() */ @Test - public void testGetHearingAidService() { - assertThat(mService).isEqualTo(HearingAidService.getHearingAidService()); + public void getHearingAidService() { + assertThat(HearingAidService.getHearingAidService()).isEqualTo(mService); } - /** Test stop HearingAid Service */ @Test - public void testStopHearingAidService() { - // Prepare: connect - connectDevice(mLeftDevice); - // HearingAid Service is already running: test stop(). Note: must be done on the main thread - InstrumentationRegistry.getInstrumentation().runOnMainSync(mService::stop); - // Try to restart the service. Note: must be done on the main thread - InstrumentationRegistry.getInstrumentation().runOnMainSync(mService::start); + public void getConnectionPolicy() { + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.getConnectionPolicy(mLeftDevice)).isEqualTo(policy); + } } - /** Test get/set priority for BluetoothDevice */ @Test - public void testGetSetPriority() throws Exception { - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - // indirect call of mService.getConnectionPolicy to test BluetoothHearingAidBinder - int connectionPolicy = mServiceBinder.getConnectionPolicy(mLeftDevice, null); - assertThat(connectionPolicy).isEqualTo(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - assertThat(mService.getConnectionPolicy(mLeftDevice)) - .isEqualTo(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - assertThat(mService.getConnectionPolicy(mLeftDevice)) - .isEqualTo(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + public void okToConnect_whenNotBonded_returnFalse() { + int badPolicyValue = 1024; + int badBondState = 42; + for (int bondState : List.of(BOND_NONE, BOND_BONDING, badBondState)) { + doReturn(bondState).when(mAdapterService).getBondState(any()); + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED, + badPolicyValue)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mSingleDevice)).isEqualTo(false); + } + } } - /** Test okToConnect method using various test cases */ @Test - public void testOkToConnect() { - int badPriorityValue = 1024; - int badBondState = 42; - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testOkToConnectCase(mSingleDevice, BluetoothDevice.BOND_NONE, badPriorityValue, false); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testOkToConnectCase(mSingleDevice, BluetoothDevice.BOND_BONDING, badPriorityValue, false); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - true); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mSingleDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - true); - testOkToConnectCase(mSingleDevice, BluetoothDevice.BOND_BONDED, badPriorityValue, false); - testOkToConnectCase( - mSingleDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, false); - testOkToConnectCase( - mSingleDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, false); - testOkToConnectCase( - mSingleDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_ALLOWED, false); - testOkToConnectCase(mSingleDevice, badBondState, badPriorityValue, false); + public void okToConnect_whenBonded() { + int badPolicyValue = 1024; + for (int policy : List.of(CONNECTION_POLICY_FORBIDDEN, badPolicyValue)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mSingleDevice)).isEqualTo(false); + } + for (int policy : List.of(CONNECTION_POLICY_UNKNOWN, CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mSingleDevice)).isEqualTo(true); + } } - /** - * Test that an outgoing connection to device that does not have Hearing Aid UUID is rejected - */ @Test - public void testOutgoingConnectMissingHearingAidUuid() { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - + public void connectToDevice_whenUuidIsMissing_returnFalse() { // Return No UUID doReturn(new ParcelUuid[] {}) .when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - // Send a connect request assertThat(mService.connect(mLeftDevice)).isFalse(); } - /** Test that an outgoing connection to device with PRIORITY_OFF is rejected */ @Test - public void testOutgoingConnectPriorityOff() throws Exception { - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); + public void connectToDevice_whenPolicyForbid_returnFalse() { + doReturn(CONNECTION_POLICY_FORBIDDEN) + .when(mDatabaseManager) + .getProfileConnectionPolicy(any(), anyInt()); - // Set the device priority to PRIORITY_OFF so connect() should fail - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - - // Send a connect request via BluetoothHearingAidBinder - assertThat(mServiceBinder.connect(mLeftDevice, null)).isFalse(); + assertThat(mService.connect(mLeftDevice)).isFalse(); } - /** Test that an outgoing connection times out */ @Test - public void testOutgoingConnectTimeout() throws Exception { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - - // Send a connect request + public void outgoingConnect_whenTimeOut_isDisconnected() { assertThat(mService.connect(mLeftDevice)).isTrue(); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTING); + + mLooper.moveTimeForward(HearingAidStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - // indirect call of mService.getConnectionState to test BluetoothHearingAidBinder - int connectionState = mServiceBinder.getConnectionState(mLeftDevice, null); - assertThat(connectionState).isEqualTo(BluetoothProfile.STATE_CONNECTING); - - // Verify the connection state broadcast, and that we are in Disconnected state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyConnectionStateIntent(mLeftDevice, STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTED); } - /** Test that the Hearing Aid Service connects to left and right device at the same time. */ @Test - public void testConnectAPair_connectBothDevices() { - // Update hiSyncId map + public void connectLeft_whenInAPair_connectBothDevices() { getHiSyncIdFromNative(); - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - - // Send a connect request + assertThat(mService.connect(mLeftDevice)).isTrue(); + mLooper.dispatchAll(); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + verifyConnectionStateIntent(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTING); + verifyConnectionStateIntent(mRightDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_CONNECTING); } - /** Test that the service disconnects the current pair before connecting to another pair. */ @Test - public void testConnectAnotherPair_disconnectCurrentPair() throws Exception { - // Update hiSyncId map + public void connectDifferentPair_whenConnected_currentIsDisconnected() { getHiSyncIdFromNative(); - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - - // Send a connect request + assertThat(mService.connect(mLeftDevice)).isTrue(); + mLooper.dispatchAll(); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - - HearingAidStackEvent connCompletedEvent; - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mLeftDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mRightDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); + verifyConnectionStateIntent(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + verifyConnectionStateIntent(mRightDevice, STATE_CONNECTING, STATE_DISCONNECTED); - // Verify the connection state broadcast, and that we are in Connected state for right side - verifyConnectionStateIntent( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - verifyConnectionStateIntent( - mRightDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mRightDevice, STATE_CONNECTED, STATE_CONNECTING); - // Send a connect request for another pair assertThat(mService.connect(mSingleDevice)).isTrue(); + mLooper.dispatchAll(); - // Verify the connection state broadcast, and that the first pair is in Disconnecting state - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); - // indirect call of mService.getConnectedDevices to test BluetoothHearingAidBinder - assertThat(mServiceBinder.getConnectedDevices(null)).doesNotContain(mLeftDevice); - assertThat(mService.getConnectedDevices()).doesNotContain(mRightDevice); - - // Verify the connection state broadcast, and that the second device is in Connecting state - verifyConnectionStateIntent( - mSingleDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mSingleDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + verifyConnectionStateIntent(mLeftDevice, STATE_DISCONNECTING, STATE_CONNECTED); + verifyConnectionStateIntent(mRightDevice, STATE_DISCONNECTING, STATE_CONNECTED); + verifyConnectionStateIntent(mSingleDevice, STATE_CONNECTING, STATE_DISCONNECTED); + + assertThat(mService.getConnectedDevices()).isEmpty(); + assertThat(mService.getConnectionState(mSingleDevice)).isEqualTo(STATE_CONNECTING); } - /** Test that the outgoing connect/disconnect and audio switch is successful. */ @Test - public void testAudioManagerConnectDisconnect() throws Exception { - // Update hiSyncId map + public void disconnect_whenAudioRoutedToHa_audioIsPaused() { getHiSyncIdFromNative(); - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - - // Send a connect request + assertThat(mService.connect(mLeftDevice)).isTrue(); - assertThat(mService.connect(mRightDevice)).isTrue(); + mLooper.dispatchAll(); + verifyConnectionStateIntent(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTING); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - - HearingAidStackEvent connCompletedEvent; - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mLeftDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); - - // Send a message to trigger connection completed for right side - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mRightDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); + assertThat(mService.connect(mRightDevice)).isTrue(); + mLooper.dispatchAll(); + verifyConnectionStateIntent(mRightDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_CONNECTING); - // Verify the connection state broadcast, and that we are in Connected state for right side - verifyConnectionStateIntent( - mRightDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mRightDevice, STATE_CONNECTED, STATE_CONNECTING); - // Verify the list of connected devices - assertThat(mService.getConnectedDevices()).containsAtLeast(mLeftDevice, mRightDevice); + assertThat(mService.getConnectedDevices()).containsExactly(mLeftDevice, mRightDevice); // Verify the audio is routed to Hearing Aid Profile verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mLeftDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - // Send a disconnect request assertThat(mService.disconnect(mLeftDevice)).isTrue(); - // Send a disconnect request via BluetoothHearingAidBinder - assertThat(mServiceBinder.disconnect(mRightDevice, null)).isTrue(); - - // Verify the connection state broadcast, and that we are in Disconnecting state - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTING); - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTING); - - // Send a message to trigger disconnection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mLeftDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED; - mService.messageFromNative(connCompletedEvent); - - // Verify the connection state broadcast, and that we are in Disconnected state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_DISCONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); - - // Send a message to trigger disconnection completed to the right device - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mRightDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED; - mService.messageFromNative(connCompletedEvent); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mLeftDevice, STATE_DISCONNECTING, STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTING); + + assertThat(mService.disconnect(mRightDevice)).isTrue(); + mLooper.dispatchAll(); - // Verify the connection state broadcast, and that we are in Disconnected state - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_DISCONNECTING); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyConnectionStateIntent(mRightDevice, STATE_DISCONNECTING, STATE_CONNECTED); + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_DISCONNECTING); - // Verify the list of connected devices - assertThat(mService.getConnectedDevices()).containsNoneOf(mLeftDevice, mRightDevice); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + generateConnectionMessageFromNative(mRightDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + + assertThat(mService.getConnectedDevices()).isEmpty(); // Verify the audio is not routed to Hearing Aid Profile. // Music should be paused (i.e. should not suppress noisy intent) @@ -613,65 +355,30 @@ public class HearingAidServiceTest { assertThat(connectionInfo.isSuppressNoisyIntent()).isFalse(); } - /** - * Test that the noisy intent is suppressed when we call HearingAidService#removeActiveDevice() - * with (stopAudio == false). - */ @Test - public void testAudioManagerConnectDisconnect_suppressNoisyIntentCase() throws Exception { - // Update hiSyncId map + public void outgoingDisconnect_whenAudioRoutedToHa_audioIsNotPaused() { getHiSyncIdFromNative(); - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - // Send a connect request assertThat(mService.connect(mLeftDevice)).isTrue(); + mLooper.dispatchAll(); + verifyConnectionStateIntent(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTING); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - - HearingAidStackEvent connCompletedEvent; - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mLeftDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); - // Verify the list of connected devices - assertThat(mService.getConnectedDevices()).contains(mLeftDevice); + assertThat(mService.getConnectedDevices()).containsExactly(mLeftDevice); // Verify the audio is routed to Hearing Aid Profile verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mLeftDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - // Send a disconnect request assertThat(mService.disconnect(mLeftDevice)).isTrue(); + mLooper.dispatchAll(); - // Verify the connection state broadcast, and that we are in Disconnecting state // Note that we call verifyConnectionStateIntent() with (stopAudio == false). - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED, - false); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTING); + verifyConnectionStateIntent(mLeftDevice, STATE_DISCONNECTING, STATE_CONNECTED, false); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTING); // Verify the audio is not routed to Hearing Aid Profile. // Note that music should be not paused (i.e. should suppress noisy intent) @@ -684,320 +391,175 @@ public class HearingAidServiceTest { assertThat(connectionInfo.isSuppressNoisyIntent()).isTrue(); } - /** - * Test that only CONNECTION_STATE_CONNECTED or CONNECTION_STATE_CONNECTING Hearing Aid stack - * events will create a state machine. - */ @Test - public void testCreateStateMachineStackEvents() { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - - // Hearing Aid stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + public void incomingConnecting_whenNoDevice_createStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); assertThat(mService.getDevices()).contains(mLeftDevice); + } - // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + @Test + public void incomingDisconnect_whenConnectingDevice_keepStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED, STATE_CONNECTING); assertThat(mService.getDevices()).contains(mLeftDevice); - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); - assertThat(mService.getDevices()).doesNotContain(mLeftDevice); + } - // stack event: CONNECTION_STATE_CONNECTED - state machine should be created - generateConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + @Test + public void incomingConnect_whenNoDevice_createStateMachine() { + // Theoretically impossible case + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTED); assertThat(mService.getDevices()).contains(mLeftDevice); + } + + @Test + public void incomingDisconnect_whenConnectedDevice_keepStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_DISCONNECTED); - // stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed - generateConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED, STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mService.getDevices()).contains(mLeftDevice); - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); - assertThat(mService.getDevices()).doesNotContain(mLeftDevice); + } - // stack event: CONNECTION_STATE_DISCONNECTING - state machine should not be created - generateUnexpectedConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_DISCONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + @Test + public void incomingDisconnecting_whenNoDevice_noStateMachine() { + generateUnexpectedConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTING); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mService.getDevices()).doesNotContain(mLeftDevice); + } - // stack event: CONNECTION_STATE_DISCONNECTED - state machine should not be created - generateUnexpectedConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + @Test + public void incomingDisconnect_whenNoDevice_noStateMachine() { + generateUnexpectedConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mService.getDevices()).doesNotContain(mLeftDevice); } - /** - * Test that a state machine in DISCONNECTED state is removed only after the device is unbond. - */ @Test - public void testDeleteStateMachineUnbondEvents() { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - - // HearingAid stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + public void unBondDevice_whenConnecting_keepStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTING); assertThat(mService.getDevices()).contains(mLeftDevice); - // Device unbond - state machine is not removed - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); + + mService.bondStateChanged(mLeftDevice, BOND_NONE); assertThat(mService.getDevices()).contains(mLeftDevice); + } - // HearingAid stack event: CONNECTION_STATE_CONNECTED - state machine is not removed - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_BONDED); - generateConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + @Test + public void unBondDevice_whenConnected_keepStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTED); assertThat(mService.getDevices()).contains(mLeftDevice); - // Device unbond - state machine is not removed - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); + + mService.bondStateChanged(mLeftDevice, BOND_NONE); assertThat(mService.getDevices()).contains(mLeftDevice); + } - // HearingAid stack event: CONNECTION_STATE_DISCONNECTING - state machine is not removed - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_BONDED); - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTING); + @Test + public void unBondDevice_whenDisconnecting_keepStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTING, STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTING); assertThat(mService.getDevices()).contains(mLeftDevice); - // Device unbond - state machine is not removed - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); + + mService.bondStateChanged(mLeftDevice, BOND_NONE); assertThat(mService.getDevices()).contains(mLeftDevice); + } - // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_BONDED); - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_DISCONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + @Test + public void unBondDevice_whenDisconnected_removeStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTING, STATE_CONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mService.getDevices()).contains(mLeftDevice); - // Device unbond - state machine is removed - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); + + mService.bondStateChanged(mLeftDevice, BOND_NONE); assertThat(mService.getDevices()).doesNotContain(mLeftDevice); } - /** - * Test that a CONNECTION_STATE_DISCONNECTED Hearing Aid stack event will remove the state - * machine only if the device is unbond. - */ @Test - public void testDeleteStateMachineDisconnectEvents() { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - - // HearingAid stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + public void disconnect_whenBonded_keepStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTING, STATE_CONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mService.getDevices()).contains(mLeftDevice); + } - // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + @Test + public void disconnect_whenUnBonded_removeStateMachine() { + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTING, STATE_CONNECTED); assertThat(mService.getDevices()).contains(mLeftDevice); - // HearingAid stack event: CONNECTION_STATE_CONNECTING - state machine remains - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + doReturn(BOND_NONE).when(mAdapterService).getBondState(any()); + mService.bondStateChanged(mLeftDevice, BOND_NONE); assertThat(mService.getDevices()).contains(mLeftDevice); - // Device bond state marked as unbond - state machine is not removed - doReturn(BluetoothDevice.BOND_NONE) - .when(mAdapterService) - .getBondState(any(BluetoothDevice.class)); - assertThat(mService.getDevices()).contains(mLeftDevice); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); - // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine is removed - generateConnectionMessageFromNative( - mLeftDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mService.getDevices()).doesNotContain(mLeftDevice); } @Test - public void testConnectionStateChangedActiveDevice() throws Exception { - // Update hiSyncId map + public void getActiveDevice() { getHiSyncIdFromNative(); - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - - generateConnectionMessageFromNative( - mRightDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getActiveDevices()).contains(mRightDevice); - - // indirect call of mService.getActiveDevices to test BluetoothHearingAidBinder - assertThat(mServiceBinder.getActiveDevices(null)).doesNotContain(mLeftDevice); - - generateConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); + + generateConnectionMessageFromNative(mRightDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getActiveDevices()).containsExactly(null, mRightDevice); + + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_DISCONNECTED); assertThat(mService.getActiveDevices()).containsExactly(mRightDevice, mLeftDevice); - generateConnectionMessageFromNative( - mRightDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getActiveDevices()).doesNotContain(mRightDevice); - assertThat(mService.getActiveDevices()).contains(mLeftDevice); + generateConnectionMessageFromNative(mRightDevice, STATE_DISCONNECTED, STATE_CONNECTED); + assertThat(mService.getActiveDevices()).containsExactly(null, mLeftDevice); - generateConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getActiveDevices()).containsNoneOf(mRightDevice, mLeftDevice); + generateConnectionMessageFromNative(mLeftDevice, STATE_DISCONNECTED, STATE_CONNECTED); + assertThat(mService.getActiveDevices()).containsExactly(null, null); } @Test - public void testConnectionStateChangedAnotherActiveDevice() throws Exception { - // Update hiSyncId map + public void connectNewDevice_whenOtherPairIsActive_newDeviceIsActive() { getHiSyncIdFromNative(); - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - - generateConnectionMessageFromNative( - mRightDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getActiveDevices()).contains(mRightDevice); - assertThat(mService.getActiveDevices()).doesNotContain(mLeftDevice); - - generateConnectionMessageFromNative( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); + + generateConnectionMessageFromNative(mRightDevice, STATE_CONNECTED, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_DISCONNECTED); assertThat(mService.getActiveDevices()).containsExactly(mRightDevice, mLeftDevice); - generateConnectionMessageFromNative( - mSingleDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getActiveDevices()).containsNoneOf(mRightDevice, mLeftDevice); - assertThat(mService.getActiveDevices()).contains(mSingleDevice); + generateConnectionMessageFromNative(mSingleDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getActiveDevices()).containsExactly(null, mSingleDevice); - assertThat(mServiceBinder.setActiveDevice(null, null)).isTrue(); - assertThat(mService.getActiveDevices()).doesNotContain(mSingleDevice); + assertThat(mService.setActiveDevice(null)).isTrue(); + assertThat(mService.getActiveDevices()).containsExactly(null, null); + } - mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION); - mServiceBinder.setActiveDevice(null, null); + @Test + @EnableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION) + public void setBinderActive_whenAudioRouting_redirectedToAudioRouting() { + mBinder.setActiveDevice(null, null); verify(mAudioRoutingManager).activateDeviceProfile(null, BluetoothProfile.HEARING_AID); } - /** - * Verify the correctness during first time connection. Connect to left device -> Get left - * device hiSyncId -> Connect to right device -> Get right device hiSyncId -> Both devices - * should be always connected - */ + // Verify the correctness during first time connection. + // Connect to left device -> Get left device hiSyncId -> Connect to right device -> + // Get right device hiSyncId -> Both devices should be always connected @Test public void firstTimeConnection_shouldConnectToBothDevices() { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - // Send a connect request for left device assertThat(mService.connect(mLeftDevice)).isTrue(); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - - HearingAidStackEvent connCompletedEvent; - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mLeftDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTING); - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); // Get hiSyncId for left device HearingAidStackEvent hiSyncIdEvent = @@ -1005,134 +567,74 @@ public class HearingAidServiceTest { hiSyncIdEvent.device = mLeftDevice; hiSyncIdEvent.valueInt1 = 0x02; hiSyncIdEvent.valueLong2 = 0x0101; - mService.messageFromNative(hiSyncIdEvent); + messageFromNativeAndDispatch(hiSyncIdEvent); - // Send a connect request for right device assertThat(mService.connect(mRightDevice)).isTrue(); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mRightDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_CONNECTING); // Verify the left device is still connected - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTED); - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mRightDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - mRightDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(mRightDevice, STATE_CONNECTED, STATE_CONNECTING); + + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTED); // Get hiSyncId for right device hiSyncIdEvent = new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); hiSyncIdEvent.device = mRightDevice; hiSyncIdEvent.valueInt1 = 0x02; hiSyncIdEvent.valueLong2 = 0x0101; - mService.messageFromNative(hiSyncIdEvent); + messageFromNativeAndDispatch(hiSyncIdEvent); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTED); } - /** Get the HiSyncId from native stack after connecting to left device, then connect right */ @Test public void getHiSyncId_afterFirstDeviceConnected() { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mRightDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); - // Send a connect request assertThat(mService.connect(mLeftDevice)).isTrue(); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mLeftDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); - - HearingAidStackEvent connCompletedEvent; - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mLeftDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - mLeftDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); - - // Get hiSyncId update from native stack + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mLeftDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTING); + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_DISCONNECTED); + + generateConnectionMessageFromNative(mLeftDevice, STATE_CONNECTED, STATE_CONNECTING); + getHiSyncIdFromNative(); - // Send a connect request for right + assertThat(mService.connect(mRightDevice)).isTrue(); - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - mRightDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mRightDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_CONNECTING); // Verify the left device is still connected - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTED); - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mRightDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - mRightDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(mRightDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); - assertThat(mService.getConnectionState(mLeftDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(mRightDevice, STATE_CONNECTED, STATE_CONNECTING); + + assertThat(mService.getConnectionState(mRightDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getConnectionState(mLeftDevice)).isEqualTo(STATE_CONNECTED); } /** Test that the service can update HiSyncId from native message */ @Test - public void getHiSyncIdFromNative_addToMap() throws Exception { + public void getHiSyncIdFromNative_addToMap() { getHiSyncIdFromNative(); assertThat(mService.getHiSyncIdMap()).containsKey(mLeftDevice); assertThat(mService.getHiSyncIdMap()).containsKey(mRightDevice); assertThat(mService.getHiSyncIdMap()).containsKey(mSingleDevice); - long id = mServiceBinder.getHiSyncId(mLeftDevice, null); + long id = mBinder.getHiSyncId(mLeftDevice, null); assertThat(id).isNotEqualTo(BluetoothHearingAid.HI_SYNC_ID_INVALID); - id = mServiceBinder.getHiSyncId(mRightDevice, null); + id = mBinder.getHiSyncId(mRightDevice, null); assertThat(id).isNotEqualTo(BluetoothHearingAid.HI_SYNC_ID_INVALID); - id = mServiceBinder.getHiSyncId(mSingleDevice, null); + id = mBinder.getHiSyncId(mSingleDevice, null); assertThat(id).isNotEqualTo(BluetoothHearingAid.HI_SYNC_ID_INVALID); } @@ -1140,102 +642,55 @@ public class HearingAidServiceTest { @Test public void deviceUnbonded_removeHiSyncId() { getHiSyncIdFromNative(); - mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); + mService.bondStateChanged(mLeftDevice, BOND_NONE); assertThat(mService.getHiSyncIdMap()).doesNotContainKey(mLeftDevice); } @Test - public void serviceBinder_callGetDeviceMode() throws Exception { - int mode = mServiceBinder.getDeviceMode(mSingleDevice, null); + public void serviceBinder_callGetDeviceMode() { + int mode = mBinder.getDeviceMode(mSingleDevice, null); // return unknown value if no device connected assertThat(mode).isEqualTo(BluetoothHearingAid.MODE_UNKNOWN); } @Test - public void serviceBinder_callGetDeviceSide() throws Exception { - int side = mServiceBinder.getDeviceSide(mSingleDevice, null); + public void serviceBinder_callGetDeviceSide() { + int side = mBinder.getDeviceSide(mSingleDevice, null); // return unknown value if no device connected assertThat(side).isEqualTo(BluetoothHearingAid.SIDE_UNKNOWN); } @Test - public void serviceBinder_setConnectionPolicy() throws Exception { + public void serviceBinder_setConnectionPolicy() { when(mDatabaseManager.setProfileConnectionPolicy( - mSingleDevice, - BluetoothProfile.HEARING_AID, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN)) + mSingleDevice, BluetoothProfile.HEARING_AID, CONNECTION_POLICY_UNKNOWN)) .thenReturn(true); - assertThat( - mServiceBinder.setConnectionPolicy( - mSingleDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, null)) + assertThat(mBinder.setConnectionPolicy(mSingleDevice, CONNECTION_POLICY_UNKNOWN, null)) .isTrue(); verify(mDatabaseManager) .setProfileConnectionPolicy( - mSingleDevice, - BluetoothProfile.HEARING_AID, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN); + mSingleDevice, BluetoothProfile.HEARING_AID, CONNECTION_POLICY_UNKNOWN); } @Test - public void serviceBinder_setVolume() throws Exception { - mServiceBinder.setVolume(0, null); + public void serviceBinder_setVolume() { + mBinder.setVolume(0, null); verify(mNativeInterface).setVolume(0); } @Test public void dump_doesNotCrash() { - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy( - mSingleDevice, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); - - // Send a connect request mService.connect(mSingleDevice); + mLooper.dispatchAll(); mService.dump(new StringBuilder()); } - private void connectDevice(BluetoothDevice device) { - HearingAidStackEvent connCompletedEvent; - - List prevConnectedDevices = mService.getConnectedDevices(); - - // Update the device priority so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HEARING_AID)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHearingAid(device); - doReturn(true).when(mNativeInterface).disconnectHearingAid(device); - - // Send a connect request - assertThat(mService.connect(device)).isTrue(); - - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mService.getConnectionState(device)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - - // Send a message to trigger connection completed - connCompletedEvent = - new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = device; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mService.getConnectionState(device)).isEqualTo(BluetoothProfile.STATE_CONNECTED); - - // Verify that the device is in the list of connected devices - assertThat(mService.getConnectedDevices()).contains(device); - // Verify the list of previously connected devices - for (BluetoothDevice prevDevice : prevConnectedDevices) { - assertThat(mService.getConnectedDevices()).contains(prevDevice); - } + private void messageFromNativeAndDispatch(HearingAidStackEvent event) { + mService.messageFromNative(event); + mLooper.dispatchAll(); } private void generateConnectionMessageFromNative( @@ -1244,9 +699,9 @@ public class HearingAidServiceTest { new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); stackEvent.device = device; stackEvent.valueInt1 = newConnectionState; - mService.messageFromNative(stackEvent); - // Verify the connection state broadcast + messageFromNativeAndDispatch(stackEvent); verifyConnectionStateIntent(device, newConnectionState, oldConnectionState); + assertThat(mService.getConnectionState(device)).isEqualTo(newConnectionState); } private void generateUnexpectedConnectionMessageFromNative( @@ -1255,9 +710,8 @@ public class HearingAidServiceTest { new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); stackEvent.device = device; stackEvent.valueInt1 = newConnectionState; - mService.messageFromNative(stackEvent); - // Verify the connection state broadcast - mInOrder.verify(mContext, times(0)) + messageFromNativeAndDispatch(stackEvent); + mInOrder.verify(mAdapterService, never()) .sendBroadcastAsUser( MockitoHamcrest.argThat( hasAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED)), @@ -1266,35 +720,22 @@ public class HearingAidServiceTest { any()); } - /** - * Helper function to test okToConnect() method - * - * @param device test device - * @param bondState bond state value, could be invalid - * @param priority value, could be invalid, could be invalid - * @param expected expected result from okToConnect() - */ - private void testOkToConnectCase( - BluetoothDevice device, int bondState, int priority, boolean expected) { - doReturn(bondState).when(mAdapterService).getBondState(device); - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HEARING_AID)) - .thenReturn(priority); - assertThat(mService.okToConnect(device)).isEqualTo(expected); - } - + // Emulate hiSyncId map update from native stack private void getHiSyncIdFromNative() { HearingAidStackEvent event = new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); event.device = mLeftDevice; event.valueInt1 = 0x02; event.valueLong2 = 0x0101; - mService.messageFromNative(event); + messageFromNativeAndDispatch(event); + event.device = mRightDevice; event.valueInt1 = 0x03; - mService.messageFromNative(event); + messageFromNativeAndDispatch(event); + event.device = mSingleDevice; event.valueInt1 = 0x00; event.valueLong2 = 0x0102; - mService.messageFromNative(event); + messageFromNativeAndDispatch(event); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java index 301051fed4a..267ace2fa05 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java @@ -16,271 +16,190 @@ package com.android.bluetooth.hearingaid; -import static org.mockito.Mockito.*; +import static android.bluetooth.BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED; +import static android.bluetooth.BluetoothProfile.EXTRA_STATE; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; + +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 static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; import android.content.Intent; -import android.os.Bundle; -import android.os.HandlerThread; import android.os.UserHandle; +import android.os.test.TestLooper; -import androidx.test.filters.MediumTest; +import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; -import com.android.bluetooth.btservice.AdapterService; -import org.hamcrest.core.IsInstanceOf; -import org.junit.After; -import org.junit.Assert; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; 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.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -@MediumTest +@SmallTest @RunWith(AndroidJUnit4.class) public class HearingAidStateMachineTest { - private BluetoothAdapter mAdapter; - private HandlerThread mHandlerThread; - private HearingAidStateMachine mHearingAidStateMachine; - private BluetoothDevice mTestDevice; - private static final int TIMEOUT_MS = 1000; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock private AdapterService mAdapterService; - @Mock private HearingAidService mHearingAidService; - @Mock private HearingAidNativeInterface mHearingAidNativeInterface; + @Mock private HearingAidService mService; + @Mock private HearingAidNativeInterface mNativeInterface; + + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mTestDevice = TestUtils.getTestDevice(mAdapter, 0xDA); + + private HearingAidStateMachine mStateMachine; + private InOrder mInOrder; + private TestLooper mLooper; @Before - public void setUp() throws Exception { - TestUtils.setAdapterService(mAdapterService); + public void setUp() { + mInOrder = inOrder(mService); + mLooper = new TestLooper(); - mAdapter = BluetoothAdapter.getDefaultAdapter(); + doReturn(true).when(mService).okToConnect(any()); + doReturn(true).when(mService).isConnectedPeerDevices(mTestDevice); - // Get a device for testing - mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); + doReturn(true).when(mNativeInterface).connectHearingAid(any()); + doReturn(true).when(mNativeInterface).disconnectHearingAid(any()); - // Set up thread and looper - mHandlerThread = new HandlerThread("HearingAidStateMachineTestHandlerThread"); - mHandlerThread.start(); - mHearingAidStateMachine = + mStateMachine = new HearingAidStateMachine( - mTestDevice, - mHearingAidService, - mHearingAidNativeInterface, - mHandlerThread.getLooper()); - // Override the timeout value to speed up the test - mHearingAidStateMachine.sConnectTimeoutMs = 1000; // 1s - mHearingAidStateMachine.start(); - } - - @After - public void tearDown() throws Exception { - mHearingAidStateMachine.doQuit(); - mHandlerThread.quit(); - TestUtils.clearAdapterService(mAdapterService); + mService, mTestDevice, mNativeInterface, mLooper.getLooper()); + mStateMachine.start(); } - /** Test that default state is disconnected */ @Test - public void testDefaultDisconnectedState() { - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mHearingAidStateMachine.getConnectionState()); - } - - /** - * Allow/disallow connection to any device. - * - * @param allow if true, connection is allowed - */ - private void allowConnection(boolean allow) { - doReturn(allow).when(mHearingAidService).okToConnect(any(BluetoothDevice.class)); + public void initialState_isDisconnected() { + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } - /** Test that an incoming connection with low priority is rejected */ @Test - public void testIncomingPriorityReject() { - allowConnection(false); + public void incomingConnect_whenNotOkToConnect_isRejected() { + doReturn(false).when(mService).okToConnect(any()); // Inject an event for when incoming connection is requested HearingAidStackEvent connStCh = new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.device = mTestDevice; - connStCh.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mHearingAidStateMachine.sendMessage(HearingAidStateMachine.STACK_EVENT, connStCh); + connStCh.valueInt1 = STATE_CONNECTED; + sendAndDispatchMessage(HearingAidStateMachine.MESSAGE_STACK_EVENT, connStCh); - // Verify that no connection state broadcast is executed - verify(mHearingAidService, after(TIMEOUT_MS).never()) - .sendBroadcastAsUser( - any(Intent.class), eq(UserHandle.ALL), anyString(), any(Bundle.class)); - // Check that we are in Disconnected state - Assert.assertThat( - mHearingAidStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HearingAidStateMachine.Disconnected.class)); + verify(mService, never()).sendBroadcastAsUser(any(), any(), anyString(), any()); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HearingAidStateMachine.Disconnected.class); } - /** Test that an incoming connection with high priority is accepted */ @Test - public void testIncomingPriorityAccept() { - allowConnection(true); - + public void incomingConnect_whenOkToConnect_isConnected() { // Inject an event for when incoming connection is requested HearingAidStackEvent connStCh = new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.device = mTestDevice; - connStCh.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTING; - mHearingAidStateMachine.sendMessage(HearingAidStateMachine.STACK_EVENT, connStCh); + connStCh.valueInt1 = STATE_CONNECTING; + sendAndDispatchMessage(HearingAidStateMachine.MESSAGE_STACK_EVENT, connStCh); - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHearingAidService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcastAsUser( - intentArgument1.capture(), - eq(UserHandle.ALL), - anyString(), - any(Bundle.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), + hasExtra(EXTRA_STATE, STATE_CONNECTING)); - // Check that we are in Connecting state - Assert.assertThat( - mHearingAidStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HearingAidStateMachine.Connecting.class)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HearingAidStateMachine.Connecting.class); // Send a message to trigger connection completed HearingAidStackEvent connCompletedEvent = new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connCompletedEvent.device = mTestDevice; - connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; - mHearingAidStateMachine.sendMessage(HearingAidStateMachine.STACK_EVENT, connCompletedEvent); + connCompletedEvent.valueInt1 = STATE_CONNECTED; + sendAndDispatchMessage(HearingAidStateMachine.MESSAGE_STACK_EVENT, connCompletedEvent); - // Verify that the expected number of broadcasts are executed: - // - two calls to broadcastConnectionState(): Disconnected -> Conecting -> Connected - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mHearingAidService, timeout(TIMEOUT_MS).times(2)) - .sendBroadcastAsUser( - intentArgument2.capture(), - eq(UserHandle.ALL), - anyString(), - any(Bundle.class)); - // Check that we are in Connected state - Assert.assertThat( - mHearingAidStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HearingAidStateMachine.Connected.class)); + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), hasExtra(EXTRA_STATE, STATE_CONNECTED)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HearingAidStateMachine.Connected.class); } - /** Test that an outgoing connection times out */ @Test - public void testOutgoingTimeout() { - allowConnection(true); - doReturn(true) - .when(mHearingAidNativeInterface) - .connectHearingAid(any(BluetoothDevice.class)); - doReturn(true) - .when(mHearingAidNativeInterface) - .disconnectHearingAid(any(BluetoothDevice.class)); - when(mHearingAidService.isConnectedPeerDevices(mTestDevice)).thenReturn(true); - - // Send a connect request - mHearingAidStateMachine.sendMessage(HearingAidStateMachine.CONNECT, mTestDevice); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHearingAidService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcastAsUser( - intentArgument1.capture(), - eq(UserHandle.ALL), - anyString(), - any(Bundle.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mHearingAidStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HearingAidStateMachine.Connecting.class)); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mHearingAidService, timeout(HearingAidStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcastAsUser( - intentArgument2.capture(), - eq(UserHandle.ALL), - anyString(), - any(Bundle.class)); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Disconnected state - Assert.assertThat( - mHearingAidStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HearingAidStateMachine.Disconnected.class)); - verify(mHearingAidNativeInterface).addToAcceptlist(eq(mTestDevice)); + public void outgoingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { + sendAndDispatchMessage(HearingAidStateMachine.MESSAGE_CONNECT, mTestDevice); + + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), + hasExtra(EXTRA_STATE, STATE_CONNECTING)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HearingAidStateMachine.Connecting.class); + + mLooper.moveTimeForward(HearingAidStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), + hasExtra(EXTRA_STATE, STATE_DISCONNECTED)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HearingAidStateMachine.Disconnected.class); + + verify(mNativeInterface).addToAcceptlist(eq(mTestDevice)); } - /** Test that an incoming connection times out */ @Test - public void testIncomingTimeout() { - allowConnection(true); - doReturn(true) - .when(mHearingAidNativeInterface) - .connectHearingAid(any(BluetoothDevice.class)); - doReturn(true) - .when(mHearingAidNativeInterface) - .disconnectHearingAid(any(BluetoothDevice.class)); - when(mHearingAidService.isConnectedPeerDevices(mTestDevice)).thenReturn(true); - - // Inject an event for when incoming connection is requested + public void incomingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { HearingAidStackEvent connStCh = new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.device = mTestDevice; - connStCh.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTING; - mHearingAidStateMachine.sendMessage(HearingAidStateMachine.STACK_EVENT, connStCh); + connStCh.valueInt1 = STATE_CONNECTING; + sendAndDispatchMessage(HearingAidStateMachine.MESSAGE_STACK_EVENT, connStCh); - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHearingAidService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcastAsUser( - intentArgument1.capture(), - eq(UserHandle.ALL), - anyString(), - any(Bundle.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mHearingAidStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HearingAidStateMachine.Connecting.class)); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mHearingAidService, timeout(HearingAidStateMachine.sConnectTimeoutMs * 2L).times(2)) + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), + hasExtra(EXTRA_STATE, STATE_CONNECTING)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HearingAidStateMachine.Connecting.class); + + mLooper.moveTimeForward(HearingAidStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), + hasExtra(EXTRA_STATE, STATE_DISCONNECTED)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HearingAidStateMachine.Disconnected.class); + + verify(mNativeInterface).addToAcceptlist(eq(mTestDevice)); + } + + private void sendAndDispatchMessage(int what, Object obj) { + mStateMachine.sendMessage(what, obj); + mLooper.dispatchAll(); + } + + @SafeVarargs + private void verifyIntentSent(Matcher... matchers) { + mInOrder.verify(mService) .sendBroadcastAsUser( - intentArgument2.capture(), + MockitoHamcrest.argThat(AllOf.allOf(matchers)), eq(UserHandle.ALL), - anyString(), - any(Bundle.class)); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Disconnected state - Assert.assertThat( - mHearingAidStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HearingAidStateMachine.Disconnected.class)); - verify(mHearingAidNativeInterface).addToAcceptlist(eq(mTestDevice)); + any(), + any()); } } diff --git a/system/include/hardware/bt_hearing_aid.h b/system/include/hardware/bt_hearing_aid.h index 66c35c32686..f94c9e1b6f5 100644 --- a/system/include/hardware/bt_hearing_aid.h +++ b/system/include/hardware/bt_hearing_aid.h @@ -23,6 +23,7 @@ namespace bluetooth { namespace hearing_aid { +// Must be kept in sync with BluetoothProfile.java enum class ConnectionState { DISCONNECTED = 0, CONNECTING, CONNECTED, DISCONNECTING }; class HearingAidCallbacks { -- GitLab From b5b954bb054c2f881873e1cd1ccc4de552560c93 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 8 Oct 2024 17:28:47 -0700 Subject: [PATCH 356/875] VolumeControl: unify requireNonNull usage Bug: 372328699 Flag: Exempt refactor Test: m . Change-Id: I9aad71db55b4f41d922e9083455d450463b942c6 --- .../bluetooth/vc/VolumeControlService.java | 77 +++++-------------- .../bluetooth/BluetoothVolumeControl.java | 13 +++- 2 files changed, 30 insertions(+), 60 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index a7de3ae84a4..d005d3990b6 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -20,6 +20,8 @@ package com.android.bluetooth.vc; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static java.util.Objects.requireNonNull; + import android.annotation.RequiresPermission; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; @@ -60,7 +62,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; @@ -128,22 +129,10 @@ public class VolumeControlService extends ProfileService { // Get AdapterService, VolumeControlNativeInterface, DatabaseManager, AudioManager. // None of them can be null. - mAdapterService = - Objects.requireNonNull( - AdapterService.getAdapterService(), - "AdapterService cannot be null when VolumeControlService starts"); - mDatabaseManager = - Objects.requireNonNull( - mAdapterService.getDatabase(), - "DatabaseManager cannot be null when VolumeControlService starts"); - mVolumeControlNativeInterface = - Objects.requireNonNull( - VolumeControlNativeInterface.getInstance(), - "VolumeControlNativeInterface cannot be null when VolumeControlService" - + " starts"); - mAudioManager = getSystemService(AudioManager.class); - Objects.requireNonNull( - mAudioManager, "AudioManager cannot be null when VolumeControlService starts"); + mAdapterService = requireNonNull(AdapterService.getAdapterService()); + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); + mVolumeControlNativeInterface = requireNonNull(VolumeControlNativeInterface.getInstance()); + mAudioManager = requireNonNull(getSystemService(AudioManager.class)); // Start handler thread for state machines mHandler = new Handler(Looper.getMainLooper()); @@ -1232,7 +1221,7 @@ public class VolumeControlService extends ProfileService { return; } - Objects.requireNonNull(stackEvent.device); + requireNonNull(stackEvent.device); BluetoothDevice device = stackEvent.device; if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE) { @@ -1528,6 +1517,8 @@ public class VolumeControlService extends ProfileService { @RequiresPermission(BLUETOOTH_CONNECT) private VolumeControlService getService(AttributionSource source) { + requireNonNull(source); + // Cache mService because it can change while getService is called VolumeControlService service = mService; @@ -1546,8 +1537,6 @@ public class VolumeControlService extends ProfileService { @Override public List getConnectedDevices(AttributionSource source) { - Objects.requireNonNull(source, "source cannot be null"); - VolumeControlService service = getService(source); if (service == null) { return Collections.emptyList(); @@ -1561,8 +1550,6 @@ public class VolumeControlService extends ProfileService { @Override public List getDevicesMatchingConnectionStates( int[] states, AttributionSource source) { - Objects.requireNonNull(source, "source cannot be null"); - VolumeControlService service = getService(source); if (service == null) { return Collections.emptyList(); @@ -1575,8 +1562,7 @@ public class VolumeControlService extends ProfileService { @Override public int getConnectionState(BluetoothDevice device, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1589,8 +1575,7 @@ public class VolumeControlService extends ProfileService { @Override public boolean setConnectionPolicy( BluetoothDevice device, int connectionPolicy, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1603,8 +1588,7 @@ public class VolumeControlService extends ProfileService { @Override public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1617,8 +1601,7 @@ public class VolumeControlService extends ProfileService { @Override public boolean isVolumeOffsetAvailable(BluetoothDevice device, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1632,8 +1615,7 @@ public class VolumeControlService extends ProfileService { @Override public int getNumberOfVolumeOffsetInstances( BluetoothDevice device, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1650,8 +1632,7 @@ public class VolumeControlService extends ProfileService { int instanceId, int volumeOffset, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1665,8 +1646,7 @@ public class VolumeControlService extends ProfileService { @Override public void setDeviceVolume( BluetoothDevice device, int volume, boolean isGroupOp, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1679,8 +1659,6 @@ public class VolumeControlService extends ProfileService { @Override public void setGroupVolume(int groupId, int volume, AttributionSource source) { - Objects.requireNonNull(source, "source cannot be null"); - VolumeControlService service = getService(source); if (service == null) { return; @@ -1691,8 +1669,6 @@ public class VolumeControlService extends ProfileService { @Override public int getGroupVolume(int groupId, AttributionSource source) { - Objects.requireNonNull(source, "source cannot be null"); - VolumeControlService service = getService(source); if (service == null) { return 0; @@ -1703,8 +1679,6 @@ public class VolumeControlService extends ProfileService { @Override public void setGroupActive(int groupId, boolean active, AttributionSource source) { - Objects.requireNonNull(source, "source cannot be null"); - VolumeControlService service = getService(source); if (service == null) { return; @@ -1715,8 +1689,7 @@ public class VolumeControlService extends ProfileService { @Override public void mute(BluetoothDevice device, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1728,8 +1701,6 @@ public class VolumeControlService extends ProfileService { @Override public void muteGroup(int groupId, AttributionSource source) { - Objects.requireNonNull(source, "source cannot be null"); - VolumeControlService service = getService(source); if (service == null) { return; @@ -1740,8 +1711,7 @@ public class VolumeControlService extends ProfileService { @Override public void unmute(BluetoothDevice device, AttributionSource source) { - Objects.requireNonNull(device, "device cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(device); VolumeControlService service = getService(source); if (service == null) { @@ -1753,8 +1723,6 @@ public class VolumeControlService extends ProfileService { @Override public void unmuteGroup(int groupId, AttributionSource source) { - Objects.requireNonNull(source, "source cannot be null"); - VolumeControlService service = getService(source); if (service == null) { return; @@ -1779,8 +1747,7 @@ public class VolumeControlService extends ProfileService { @Override public void registerCallback( IBluetoothVolumeControlCallback callback, AttributionSource source) { - Objects.requireNonNull(callback, "callback cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(callback); VolumeControlService service = getService(source); if (service == null) { @@ -1794,8 +1761,7 @@ public class VolumeControlService extends ProfileService { @Override public void notifyNewRegisteredCallback( IBluetoothVolumeControlCallback callback, AttributionSource source) { - Objects.requireNonNull(callback, "callback cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(callback); VolumeControlService service = getService(source); if (service == null) { @@ -1809,8 +1775,7 @@ public class VolumeControlService extends ProfileService { @Override public void unregisterCallback( IBluetoothVolumeControlCallback callback, AttributionSource source) { - Objects.requireNonNull(callback, "callback cannot be null"); - Objects.requireNonNull(source, "source cannot be null"); + requireNonNull(callback); VolumeControlService service = getService(source); if (service == null) { diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index d14bcb1ca57..ef9c0ee0b45 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -20,6 +20,8 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static java.util.Objects.requireNonNull; + import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntRange; @@ -46,7 +48,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -407,8 +408,8 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void registerCallback( @NonNull @CallbackExecutor Executor executor, @NonNull Callback callback) { - Objects.requireNonNull(executor, "executor cannot be null"); - Objects.requireNonNull(callback, "callback cannot be null"); + requireNonNull(executor); + requireNonNull(callback); Log.d(TAG, "registerCallback"); synchronized (mCallbackExecutorMap) { if (!mAdapter.isEnabled()) { @@ -466,7 +467,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull Callback callback) { - Objects.requireNonNull(callback, "callback cannot be null"); + requireNonNull(callback); Log.d(TAG, "unregisterCallback"); synchronized (mCallbackExecutorMap) { if (mCallbackExecutorMap.remove(callback) == null) { @@ -551,6 +552,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @NonNull BluetoothDevice device, @IntRange(from = 1, to = 255) int instanceId, @IntRange(from = -255, to = 255) int volumeOffset) { + requireNonNull(device); Log.d( TAG, "setVolumeOffset(" @@ -585,6 +587,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean isVolumeOffsetAvailable(@NonNull BluetoothDevice device) { + requireNonNull(device); Log.d(TAG, "isVolumeOffsetAvailable(" + device + ")"); final IBluetoothVolumeControl service = getService(); if (service == null) { @@ -616,6 +619,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getNumberOfVolumeOffsetInstances(@NonNull BluetoothDevice device) { + requireNonNull(device); Log.d(TAG, "getNumberOfVolumeOffsetInstances(" + device + ")"); final IBluetoothVolumeControl service = getService(); final int defaultValue = 0; @@ -725,6 +729,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @NonNull BluetoothDevice device, @IntRange(from = 0, to = 255) int volume, boolean isGroupOperation) { + requireNonNull(device); if (volume < 0 || volume > 255) { throw new IllegalArgumentException("illegal volume " + volume); } -- GitLab From e19aedc4c746740d04cb265bb4837bf5e54b4316 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 8 Oct 2024 17:51:31 -0700 Subject: [PATCH 357/875] VolumeControl: Clean api annotation Bug: 372328699 Flag: Exempt refactor Test: m . Change-Id: I8e84ed0ee6e99f2d3664b30fd845a59a29d4c85b --- .../bluetooth/BluetoothVolumeControl.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index ef9c0ee0b45..a45019950dd 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -268,12 +268,12 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose } /** - * Close this VolumeControl server instance. + * {@inheritDoc} * - *

    Application should call this method as early as possible after it is done with this - * VolumeControl server. + * @hide */ @Override + @SystemApi public void close() { Log.v(TAG, "close()"); @@ -343,11 +343,12 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose } /** - * Get the list of devices matching specified states. Currently at most one. + * {@inheritDoc} * - * @return list of matching devices * @hide */ + @Override + @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public List getDevicesMatchingConnectionStates(int[] states) { @@ -368,11 +369,12 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose } /** - * Get connection state of device + * {@inheritDoc} * - * @return device connection state * @hide */ + @Override + @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { -- GitLab From aeadcdbc332c55de942b3c2e09637bdecef9be40 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 3 Oct 2024 17:18:23 +0000 Subject: [PATCH 358/875] Remove os/log.h The logging macros within have long been removed, this is just cleanup work to inline the included headers where necessary Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I2147ce4bdcea977b92318b2cb96e7020a8958161 --- .../audio_hal_interface/a2dp_encoding_host.cc | 1 - .../aidl/a2dp/a2dp_encoding_aidl.h | 1 - .../aidl/a2dp/a2dp_provider_info.cc | 1 - .../hearing_aid_software_encoding_aidl.cc | 1 - .../aidl/le_audio_software_aidl.cc | 1 - .../hal_version_manager.cc | 1 - .../hfp_client_interface.cc | 1 - .../hearing_aid_software_encoding_hidl.cc | 1 - .../hidl/le_audio_software_hidl.cc | 2 -- .../audio_hal_interface/le_audio_software.cc | 1 - system/bta/ag/bta_ag_at.cc | 1 - system/bta/ag/bta_ag_int.h | 1 + system/bta/av/bta_av_api.cc | 1 - system/bta/av/bta_av_ci.cc | 1 - system/bta/av/bta_av_ssm.cc | 1 - system/bta/dm/bta_dm_pm.cc | 1 - system/bta/gatt/bta_gattc_api.cc | 1 - system/bta/gatt/bta_gattc_db_storage.cc | 1 - system/bta/gatt/bta_gattc_main.cc | 1 - system/bta/gatt/bta_gattc_queue.cc | 1 - system/bta/gatt/bta_gatts_queue.cc | 1 - system/bta/gmap/gmap_client.cc | 1 - system/bta/gmap/gmap_server.cc | 1 - system/bta/has/has_client.cc | 1 - system/bta/has/has_ctp.cc | 2 +- system/bta/hd/bta_hd_api.cc | 1 - .../hearing_aid/hearing_aid_audio_source.cc | 1 - system/bta/hf_client/bta_hf_client_at.cc | 1 - system/bta/hf_client/bta_hf_client_sdp.cc | 1 - system/bta/hh/bta_hh_api.cc | 1 - system/bta/hh/bta_hh_main.cc | 1 - system/bta/hh/bta_hh_utils.cc | 1 - system/bta/include/bta_api.h | 1 - .../audio_hal_client/audio_sink_hal_client.cc | 1 - .../audio_source_hal_client.cc | 1 - .../bta/le_audio/broadcaster/state_machine.cc | 1 - system/bta/le_audio/client_parser.cc | 1 - system/bta/le_audio/codec_interface.cc | 2 -- system/bta/le_audio/codec_manager.cc | 1 - .../bta/le_audio/content_control_id_keeper.cc | 1 - system/bta/le_audio/devices.h | 1 - system/bta/le_audio/devices_test.cc | 1 - system/bta/le_audio/le_audio_health_status.cc | 1 - system/bta/le_audio/le_audio_log_history.cc | 2 +- ...e_audio_set_configuration_provider_json.cc | 1 - system/bta/le_audio/le_audio_utils.cc | 1 - system/bta/le_audio/storage_helper.cc | 1 - system/bta/ras/ras_utils.cc | 1 - system/bta/sys/bta_sys_main.cc | 1 - system/bta/vc/device.cc | 1 - system/bta/vc/vc.cc | 1 - system/btcore/src/module.cc | 1 - system/btcore/src/osi_module.cc | 1 - system/btif/co/bta_pan_co.cc | 1 - system/btif/include/btif_common.h | 1 - system/btif/src/btif_av.cc | 1 + system/btif/src/btif_profile_queue.cc | 4 +-- system/btif/src/btif_rc.cc | 1 + system/common/base_bind_unittest.cc | 2 -- system/device/src/device_iot_config.cc | 1 - system/device/src/device_iot_config_int.cc | 1 - system/device/src/interop.cc | 1 - system/gd/common/audit_log.cc | 5 +++- system/gd/common/byte_array_test.cc | 2 -- system/gd/common/circular_buffer_test.cc | 2 -- system/gd/common/lru_cache.h | 1 - system/gd/common/metric_id_manager.cc | 2 -- system/gd/common/strings.h | 1 - system/gd/common/sync_map_count_test.cc | 2 -- system/gd/docs/architecture/style_guide.md | 21 ------------- system/gd/docs/testing/gtest.md | 1 - system/gd/dumpsys/internal/filter_internal.cc | 1 - .../dumpsys/internal/filter_internal_test.cc | 1 - system/gd/dumpsys/reflection_schema.cc | 1 - system/gd/facade/grpc_root_server.cc | 1 - system/gd/grpc/grpc_event_queue.h | 1 - system/gd/grpc/grpc_module.cc | 2 -- system/gd/hal/hci_hal_host.cc | 1 - system/gd/hal/hci_hal_host_rootcanal.cc | 1 - system/gd/hal/hci_hal_host_test.cc | 1 - system/gd/hal/mgmt.cc | 2 -- system/gd/hal/ranging_hal_android.cc | 2 +- system/gd/hal/ranging_hal_host.cc | 2 +- system/gd/hci/acl_manager/assembler.h | 1 - .../classic_acl_connection_test.cc | 1 - .../acl_manager/round_robin_scheduler_test.cc | 1 - system/gd/hci/distance_measurement_manager.cc | 1 - system/gd/hci/event_checkers.h | 1 - .../facade/le_advertising_manager_facade.cc | 1 - .../hci/facade/le_scanning_manager_facade.cc | 1 - system/gd/hci/fuzz/acl_manager_fuzz_test.cc | 1 - system/gd/hci/fuzz/fuzz_hci_layer.h | 1 - system/gd/hci/fuzz/hci_layer_fuzz_test.cc | 1 - system/gd/hci/hci_layer_test.cc | 1 - system/gd/hci/hci_packets_fuzz_test.cc | 1 - system/gd/hci/hci_packets_test.cc | 1 - system/gd/hci/le_scanning_manager.cc | 1 - system/gd/hci/le_scanning_reassembler.cc | 1 - system/gd/metrics/chromeos/metrics.cc | 1 - system/gd/metrics/counter_metrics.cc | 1 - system/gd/module.h | 1 - system/gd/neighbor/name_db.cc | 1 - system/gd/neighbor/scan.cc | 1 - system/gd/os/android/metrics.cc | 1 - system/gd/os/android/system_properties.cc | 1 - system/gd/os/android/wakelock_native.cc | 18 ----------- system/gd/os/chromeos/metrics.cc | 1 - system/gd/os/chromeos/parameter_provider.cc | 2 -- system/gd/os/chromeos/wakelock_native.cc | 2 -- system/gd/os/handler.cc | 1 - system/gd/os/handler_unittest.cc | 1 - system/gd/os/host/metrics.cc | 2 -- system/gd/os/host/parameter_provider.cc | 2 -- system/gd/os/host/wakelock_native.cc | 2 -- system/gd/os/linux/metrics.cc | 2 -- system/gd/os/linux/parameter_provider.cc | 2 -- system/gd/os/linux/wakelock_native.cc | 2 -- system/gd/os/linux_generic/alarm.cc | 1 - system/gd/os/linux_generic/files.cc | 2 -- .../gd/os/linux_generic/reactive_semaphore.cc | 1 - system/gd/os/linux_generic/reactor.cc | 2 -- .../gd/os/linux_generic/reactor_unittest.cc | 1 - system/gd/os/linux_generic/repeating_alarm.cc | 1 - system/gd/os/linux_generic/thread.cc | 2 -- .../gd/os/linux_generic/wakelock_manager.cc | 1 - system/gd/os/log.h | 30 ------------------- system/gd/os/mock_queue.h | 1 - system/gd/os/queue.h | 1 - system/gd/os/rand.h | 2 -- system/gd/packet/bit_inserter_unittest.cc | 2 -- .../packet/fragmenting_inserter_unittest.cc | 2 -- system/gd/packet/packet_builder.h | 1 - system/gd/packet/packet_struct.h | 1 - .../parser/test/generated_packet_test.cc | 2 +- system/gd/packet/raw_builder.cc | 2 -- system/gd/rust/topshim/csis/csis_shim.cc | 8 ++--- system/gd/rust/topshim/hfp/hfp_shim.cc | 1 - .../gd/rust/topshim/le_audio/le_audio_shim.cc | 12 ++++---- system/gd/rust/topshim/vc/vc_shim.cc | 16 ++++------ system/gd/shim/dumpsys.cc | 1 - system/gd/stack_manager.cc | 1 - system/gd/storage/device.cc | 1 - system/gd/storage/legacy_config_file.cc | 1 - system/gd/storage/mutation.cc | 2 -- system/gd/storage/mutation.h | 1 - system/gd/storage/mutation_entry.cc | 2 -- system/gd/sysprops/sysprops_module.cc | 1 - system/hci/src/packet_fragmenter.cc | 1 - system/main/shim/config.cc | 1 - system/main/stack_config.cc | 1 - system/osi/src/alarm.cc | 1 - system/osi/src/future.cc | 1 - system/osi/src/internal/semaphore.cc | 1 - system/osi/src/reactor.cc | 1 - system/osi/src/socket.cc | 1 - system/osi/src/stack_power_telemetry.cc | 2 +- system/osi/src/thread.cc | 1 - system/osi/src/wakelock.cc | 1 - system/rust/src/core/ffi/module.cc | 2 +- system/rust/src/gatt/ffi/gatt_shim.cc | 1 - system/stack/a2dp/a2dp_aac.cc | 1 - system/stack/a2dp/a2dp_aac_decoder.cc | 1 - system/stack/a2dp/a2dp_aac_encoder.cc | 1 - system/stack/a2dp/a2dp_sbc_encoder.cc | 3 ++ system/stack/a2dp/a2dp_vendor_aptx_encoder.cc | 1 - system/stack/a2dp/a2dp_vendor_aptx_hd.cc | 1 - .../stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc | 1 - system/stack/a2dp/a2dp_vendor_ldac.cc | 1 - system/stack/a2dp/a2dp_vendor_ldac_decoder.cc | 1 - system/stack/a2dp/a2dp_vendor_ldac_encoder.cc | 1 - system/stack/a2dp/a2dp_vendor_opus.cc | 1 - system/stack/a2dp/a2dp_vendor_opus_decoder.cc | 1 - system/stack/a2dp/a2dp_vendor_opus_encoder.cc | 1 - system/stack/acl/btm_pm.cc | 1 - system/stack/avct/avct_lcb.cc | 1 - system/stack/avdt/avdt_api.cc | 1 + system/stack/avdt/avdt_msg.cc | 1 - system/stack/avrc/avrc_api.cc | 1 - system/stack/avrc/avrc_bld_ct.cc | 1 - system/stack/avrc/avrc_bld_tg.cc | 1 - system/stack/avrc/avrc_pars_ct.cc | 1 - system/stack/avrc/avrc_pars_tg.cc | 1 - system/stack/avrc/avrc_sdp.cc | 1 - system/stack/avrc/avrc_utils.cc | 1 - system/stack/btm/btm_ble_addr.cc | 1 - system/stack/btm/btm_iso_impl.h | 1 - system/stack/btm/btm_sco_hci.cc | 1 - system/stack/btm/btm_sco_hfp_hal_linux.cc | 1 - system/stack/btm/btm_sec_cb.cc | 1 - .../btm/btm_security_client_interface.cc | 1 - system/stack/btm/hfp_lc3_decoder.cc | 1 - system/stack/btm/hfp_lc3_decoder_linux.cc | 1 - system/stack/btm/hfp_lc3_encoder.cc | 1 - system/stack/btm/hfp_lc3_encoder_linux.cc | 1 - system/stack/btm/hfp_msbc_decoder.cc | 1 - system/stack/btm/security_device_record.h | 2 +- system/stack/btu/main_thread.cc | 1 - system/stack/gatt/gatt_int.h | 1 + system/stack/hid/hidd_api.cc | 1 - system/stack/hid/hidh_api.cc | 1 - system/stack/include/avdt_api.h | 1 - system/stack/pan/pan_api.cc | 2 +- system/stack/pan/pan_main.cc | 1 - system/stack/pan/pan_utils.cc | 1 - system/stack/smp/smp_br_main.cc | 1 - system/stack/smp/smp_main.cc | 1 - system/stack/srvc/srvc_dis.cc | 1 - system/stack/test/a2dp/a2dp_sbc_unittest.cc | 1 - system/stack/test/a2dp/wav_reader.cc | 1 - system/test/common/jni_thread.cc | 2 -- system/test/common/main_handler.cc | 1 - system/test/headless/adapter/adapter.cc | 1 - system/test/headless/discovery/discovery.cc | 1 - system/test/headless/get_options.cc | 1 - system/test/headless/headless.cc | 1 - system/test/headless/interface.h | 1 - system/test/headless/log.cc | 2 -- system/test/headless/main.cc | 1 - system/test/headless/nop/nop.cc | 1 - system/test/headless/property.cc | 1 - system/test/headless/read/read.cc | 1 - system/test/headless/scan/scan.cc | 1 - system/test/headless/text.cc | 1 - system/test/mock/mock_bta_av_api.h | 1 - system/udrv/ulinux/uipc.cc | 1 - 225 files changed, 36 insertions(+), 334 deletions(-) delete mode 100644 system/gd/os/log.h diff --git a/system/audio_hal_interface/a2dp_encoding_host.cc b/system/audio_hal_interface/a2dp_encoding_host.cc index e9bb1873399..92f4361b781 100644 --- a/system/audio_hal_interface/a2dp_encoding_host.cc +++ b/system/audio_hal_interface/a2dp_encoding_host.cc @@ -27,7 +27,6 @@ #include "btif/include/btif_a2dp_source.h" #include "btif/include/btif_av.h" #include "btif/include/btif_hf.h" -#include "os/log.h" #include "stack/include/avdt_api.h" #include "types/raw_address.h" #include "udrv/include/uipc.h" diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h index 32ef7923d81..f470d5e06a5 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h @@ -22,7 +22,6 @@ #include "a2dp_sbc_constants.h" #include "common/message_loop_thread.h" #include "hardware/bt_av.h" -#include "os/log.h" #include "osi/include/properties.h" #include "types/raw_address.h" diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc index 9f4c86b2cf6..074929290bf 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc @@ -33,7 +33,6 @@ #include "a2dp_vendor_ldac_constants.h" #include "a2dp_vendor_opus_constants.h" #include "client_interface_aidl.h" -#include "os/log.h" namespace bluetooth::audio::aidl::a2dp { diff --git a/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc b/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc index 64f4d3d6e44..b6a761889b4 100644 --- a/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc @@ -22,7 +22,6 @@ #include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h" #include "client_interface_aidl.h" -#include "os/log.h" #include "osi/include/properties.h" namespace fmt { 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 8e3d8bfa03d..7ba08289d0e 100644 --- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc +++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc @@ -28,7 +28,6 @@ #include #include "hal_version_manager.h" -#include "os/log.h" namespace bluetooth { namespace audio { diff --git a/system/audio_hal_interface/hal_version_manager.cc b/system/audio_hal_interface/hal_version_manager.cc index 19c48c58da2..2068b766e93 100644 --- a/system/audio_hal_interface/hal_version_manager.cc +++ b/system/audio_hal_interface/hal_version_manager.cc @@ -24,7 +24,6 @@ #include #include "aidl/audio_aidl_interfaces.h" -#include "os/log.h" namespace bluetooth { namespace audio { diff --git a/system/audio_hal_interface/hfp_client_interface.cc b/system/audio_hal_interface/hfp_client_interface.cc index 22e6b993730..9ff47a34903 100644 --- a/system/audio_hal_interface/hfp_client_interface.cc +++ b/system/audio_hal_interface/hfp_client_interface.cc @@ -24,7 +24,6 @@ #include "aidl/hfp_client_interface_aidl.h" #include "hal_version_manager.h" #include "hfp_client_interface.h" -#include "os/log.h" #include "osi/include/properties.h" using ::bluetooth::audio::aidl::hfp::HfpDecodingTransport; diff --git a/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc b/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc index 7f32ca7a2aa..f80aac6b439 100644 --- a/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc +++ b/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc @@ -22,7 +22,6 @@ #include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h" #include "client_interface_hidl.h" -#include "os/log.h" #include "osi/include/properties.h" namespace fmt { diff --git a/system/audio_hal_interface/hidl/le_audio_software_hidl.cc b/system/audio_hal_interface/hidl/le_audio_software_hidl.cc index 94f8b8745bb..740c05a0ad7 100644 --- a/system/audio_hal_interface/hidl/le_audio_software_hidl.cc +++ b/system/audio_hal_interface/hidl/le_audio_software_hidl.cc @@ -21,8 +21,6 @@ #include -#include "os/log.h" - namespace bluetooth { namespace audio { namespace hidl { diff --git a/system/audio_hal_interface/le_audio_software.cc b/system/audio_hal_interface/le_audio_software.cc index 7061f865e68..a984d966ee1 100644 --- a/system/audio_hal_interface/le_audio_software.cc +++ b/system/audio_hal_interface/le_audio_software.cc @@ -31,7 +31,6 @@ #include "bta/le_audio/le_audio_types.h" #include "hal_version_manager.h" #include "hidl/le_audio_software_hidl.h" -#include "os/log.h" #include "osi/include/properties.h" namespace bluetooth { diff --git a/system/bta/ag/bta_ag_at.cc b/system/bta/ag/bta_ag_at.cc index 2a7a24022d8..a42017c29ba 100644 --- a/system/bta/ag/bta_ag_at.cc +++ b/system/bta/ag/bta_ag_at.cc @@ -34,7 +34,6 @@ #include "bta/ag/bta_ag_int.h" #include "bta/include/utl.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" using namespace bluetooth; diff --git a/system/bta/ag/bta_ag_int.h b/system/bta/ag/bta_ag_int.h index 2173d86d62d..21d39365a30 100644 --- a/system/bta/ag/bta_ag_int.h +++ b/system/bta/ag/bta_ag_int.h @@ -34,6 +34,7 @@ #include "bta/include/bta_api.h" #include "bta/sys/bta_sys.h" #include "internal_include/bt_target.h" +#include "os/logging/log_adapter.h" #include "stack/include/bt_hdr.h" #include "stack/include/btm_api_types.h" #include "stack/include/sdp_status.h" diff --git a/system/bta/av/bta_av_api.cc b/system/bta/av/bta_av_api.cc index 2c349e43343..0d3b26a086a 100644 --- a/system/bta/av/bta_av_api.cc +++ b/system/bta/av/bta_av_api.cc @@ -32,7 +32,6 @@ #include "btif/include/btif_av.h" #include "internal_include/bt_target.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" #include "stack/include/bt_hdr.h" diff --git a/system/bta/av/bta_av_ci.cc b/system/bta/av/bta_av_ci.cc index 2fa1afb0799..7a83c8570a1 100644 --- a/system/bta/av/bta_av_ci.cc +++ b/system/bta/av/bta_av_ci.cc @@ -30,7 +30,6 @@ #include #include "bta/av/bta_av_int.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/bta/av/bta_av_ssm.cc b/system/bta/av/bta_av_ssm.cc index 56c03a00cc5..37df2021a2e 100644 --- a/system/bta/av/bta_av_ssm.cc +++ b/system/bta/av/bta_av_ssm.cc @@ -28,7 +28,6 @@ #include "bta/av/bta_av_int.h" #include "internal_include/bt_target.h" -#include "os/log.h" using namespace bluetooth; diff --git a/system/bta/dm/bta_dm_pm.cc b/system/bta/dm/bta_dm_pm.cc index dfd93ca2dc9..ca3bb38058f 100644 --- a/system/bta/dm/bta_dm_pm.cc +++ b/system/bta/dm/bta_dm_pm.cc @@ -39,7 +39,6 @@ #include "hci/controller_interface.h" #include "main/shim/dumpsys.h" #include "main/shim/entry.h" -#include "os/log.h" #include "osi/include/properties.h" #include "stack/include/acl_api.h" #include "stack/include/btm_client_interface.h" diff --git a/system/bta/gatt/bta_gattc_api.cc b/system/bta/gatt/bta_gattc_api.cc index d4dfc500b1a..38b3691b4a3 100644 --- a/system/bta/gatt/bta_gattc_api.cc +++ b/system/bta/gatt/bta_gattc_api.cc @@ -34,7 +34,6 @@ #include "bta/gatt/bta_gattc_int.h" #include "gd/hci/uuid.h" #include "gd/os/rand.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/main_thread.h" diff --git a/system/bta/gatt/bta_gattc_db_storage.cc b/system/bta/gatt/bta_gattc_db_storage.cc index 6a741e85442..34beb0852c2 100644 --- a/system/bta/gatt/bta_gattc_db_storage.cc +++ b/system/bta/gatt/bta_gattc_db_storage.cc @@ -28,7 +28,6 @@ #include "bta/gatt/bta_gattc_int.h" #include "gatt/database.h" -#include "os/log.h" #include "stack/include/gattdefs.h" #include "types/bluetooth/uuid.h" diff --git a/system/bta/gatt/bta_gattc_main.cc b/system/bta/gatt/bta_gattc_main.cc index fc642edfd46..2912879e77d 100644 --- a/system/bta/gatt/bta_gattc_main.cc +++ b/system/bta/gatt/bta_gattc_main.cc @@ -28,7 +28,6 @@ #include "bta/gatt/bta_gattc_int.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "stack/include/bt_hdr.h" using base::StringPrintf; diff --git a/system/bta/gatt/bta_gattc_queue.cc b/system/bta/gatt/bta_gattc_queue.cc index 6d2cc8c887b..40d99a7fb59 100644 --- a/system/bta/gatt/bta_gattc_queue.cc +++ b/system/bta/gatt/bta_gattc_queue.cc @@ -24,7 +24,6 @@ #include #include "bta_gatt_queue.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/eatt/eatt.h" diff --git a/system/bta/gatt/bta_gatts_queue.cc b/system/bta/gatt/bta_gatts_queue.cc index 1344f036f05..ef6a73e9d97 100644 --- a/system/bta/gatt/bta_gatts_queue.cc +++ b/system/bta/gatt/bta_gatts_queue.cc @@ -23,7 +23,6 @@ #include #include "bta_gatt_server_queue.h" -#include "os/log.h" using gatts_operation = BtaGattServerQueue::gatts_operation; using bluetooth::Uuid; diff --git a/system/bta/gmap/gmap_client.cc b/system/bta/gmap/gmap_client.cc index 7cd8d8c054a..917070e2ac9 100644 --- a/system/bta/gmap/gmap_client.cc +++ b/system/bta/gmap/gmap_client.cc @@ -33,7 +33,6 @@ #include "gap_api.h" #include "gatt_api.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/properties.h" #include "stack/include/bt_types.h" diff --git a/system/bta/gmap/gmap_server.cc b/system/bta/gmap/gmap_server.cc index deb0e9cb3c6..6d5ca2cd47b 100644 --- a/system/bta/gmap/gmap_server.cc +++ b/system/bta/gmap/gmap_server.cc @@ -38,7 +38,6 @@ #include "gd/os/rand.h" #include "include/hardware/bt_gmap.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "os/logging/log_adapter.h" #include "osi/include/properties.h" #include "stack/include/bt_types.h" diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 6992211a4f0..bb9e354ec41 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -39,7 +39,6 @@ #include "gatt_api.h" #include "has_types.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/properties.h" #include "stack/include/bt_types.h" diff --git a/system/bta/has/has_ctp.cc b/system/bta/has/has_ctp.cc index 080298fc9e5..c39bef152a7 100644 --- a/system/bta/has/has_ctp.cc +++ b/system/bta/has/has_ctp.cc @@ -19,7 +19,7 @@ #include -#include "os/log.h" +#include "os/logging/log_adapter.h" #include "stack/include/bt_types.h" using namespace bluetooth; diff --git a/system/bta/hd/bta_hd_api.cc b/system/bta/hd/bta_hd_api.cc index 09c353b7df6..3f5d3827a20 100644 --- a/system/bta/hd/bta_hd_api.cc +++ b/system/bta/hd/bta_hd_api.cc @@ -32,7 +32,6 @@ #include #include "bta/hd/bta_hd_int.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" #include "stack/include/bt_hdr.h" diff --git a/system/bta/hearing_aid/hearing_aid_audio_source.cc b/system/bta/hearing_aid/hearing_aid_audio_source.cc index 429bb4f0ce1..ccc67080794 100644 --- a/system/bta/hearing_aid/hearing_aid_audio_source.cc +++ b/system/bta/hearing_aid/hearing_aid_audio_source.cc @@ -29,7 +29,6 @@ #include "bta/include/bta_hearing_aid_api.h" #include "common/repeating_timer.h" #include "common/time_util.h" -#include "os/log.h" #include "osi/include/wakelock.h" #include "stack/include/main_thread.h" #include "udrv/include/uipc.h" diff --git a/system/bta/hf_client/bta_hf_client_at.cc b/system/bta/hf_client/bta_hf_client_at.cc index 9be68cab973..883d0f09553 100644 --- a/system/bta/hf_client/bta_hf_client_at.cc +++ b/system/bta/hf_client/bta_hf_client_at.cc @@ -23,7 +23,6 @@ #include "bta/hf_client/bta_hf_client_int.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" #include "osi/include/properties.h" diff --git a/system/bta/hf_client/bta_hf_client_sdp.cc b/system/bta/hf_client/bta_hf_client_sdp.cc index a9dc87489ca..94ebd879170 100644 --- a/system/bta/hf_client/bta_hf_client_sdp.cc +++ b/system/bta/hf_client/bta_hf_client_sdp.cc @@ -33,7 +33,6 @@ #include "bta/include/bta_rfcomm_scn.h" #include "bta/sys/bta_sys.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_types.h" #include "stack/include/bt_uuid16.h" diff --git a/system/bta/hh/bta_hh_api.cc b/system/bta/hh/bta_hh_api.cc index 10ca7f2d65a..413eeb9b6dd 100644 --- a/system/bta/hh/bta_hh_api.cc +++ b/system/bta/hh/bta_hh_api.cc @@ -30,7 +30,6 @@ #include "bta/hh/bta_hh_int.h" #include "bta/sys/bta_sys.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/main_thread.h" diff --git a/system/bta/hh/bta_hh_main.cc b/system/bta/hh/bta_hh_main.cc index a4dd1444b4d..16016635736 100644 --- a/system/bta/hh/bta_hh_main.cc +++ b/system/bta/hh/bta_hh_main.cc @@ -31,7 +31,6 @@ #include "bta/hh/bta_hh_int.h" #include "main/shim/dumpsys.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/bta/hh/bta_hh_utils.cc b/system/bta/hh/bta_hh_utils.cc index c163c1e5ab3..b5b86cf94d0 100644 --- a/system/bta/hh/bta_hh_utils.cc +++ b/system/bta/hh/bta_hh_utils.cc @@ -26,7 +26,6 @@ #include "btif/include/btif_storage.h" #include "device/include/interop.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_status.h" diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index 43f5fc1d72a..8772fe183cc 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -35,7 +35,6 @@ #include "bta_api_data_types.h" #include "hci/le_rand_callback.h" #include "macros.h" -#include "os/log.h" #include "stack/btm/btm_eir.h" #include "stack/btm/power_mode.h" #include "stack/include/bt_dev_class.h" diff --git a/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc index 8f05b7248be..2f86a94e5b7 100644 --- a/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc +++ b/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc @@ -24,7 +24,6 @@ #include "audio_hal_interface/le_audio_software.h" #include "bta/le_audio/codec_manager.h" #include "common/time_util.h" -#include "os/log.h" #include "osi/include/wakelock.h" #include "stack/include/main_thread.h" diff --git a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc index b721d4546da..bd7c8bea856 100644 --- a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc +++ b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc @@ -30,7 +30,6 @@ #include "common/repeating_timer.h" #include "common/time_util.h" #include "gd/hal/link_clocker.h" -#include "os/log.h" #include "osi/include/wakelock.h" #include "stack/include/main_thread.h" diff --git a/system/bta/le_audio/broadcaster/state_machine.cc b/system/bta/le_audio/broadcaster/state_machine.cc index 07c258683a2..d81011b6559 100644 --- a/system/bta/le_audio/broadcaster/state_machine.cc +++ b/system/bta/le_audio/broadcaster/state_machine.cc @@ -30,7 +30,6 @@ #include "bta/le_audio/le_audio_types.h" #include "common/strings.h" #include "hci/le_advertising_manager.h" -#include "os/log.h" #include "osi/include/properties.h" #include "stack/include/btm_iso_api.h" diff --git a/system/bta/le_audio/client_parser.cc b/system/bta/le_audio/client_parser.cc index f3b3b669252..9de6734bc72 100644 --- a/system/bta/le_audio/client_parser.cc +++ b/system/bta/le_audio/client_parser.cc @@ -33,7 +33,6 @@ #include "internal_include/bt_trace.h" #include "le_audio_types.h" #include "le_audio_utils.h" -#include "os/log.h" #include "stack/include/bt_types.h" using bluetooth::le_audio::types::acs_ac_record; diff --git a/system/bta/le_audio/codec_interface.cc b/system/bta/le_audio/codec_interface.cc index b5c75c6e1c1..637c77f5bf3 100644 --- a/system/bta/le_audio/codec_interface.cc +++ b/system/bta/le_audio/codec_interface.cc @@ -25,8 +25,6 @@ #include #include -#include "os/log.h" - namespace bluetooth::le_audio { struct CodecInterface::Impl { diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index fce821417d1..d4b0fe0efc7 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -31,7 +31,6 @@ #include "le_audio_set_configuration_provider.h" #include "le_audio_utils.h" #include "main/shim/entry.h" -#include "os/log.h" #include "osi/include/properties.h" #include "stack/include/hcimsgs.h" diff --git a/system/bta/le_audio/content_control_id_keeper.cc b/system/bta/le_audio/content_control_id_keeper.cc index cfda2dedc23..f4ca933f06e 100644 --- a/system/bta/le_audio/content_control_id_keeper.cc +++ b/system/bta/le_audio/content_control_id_keeper.cc @@ -24,7 +24,6 @@ #include "common/strings.h" #include "le_audio_types.h" -#include "os/log.h" namespace { diff --git a/system/bta/le_audio/devices.h b/system/bta/le_audio/devices.h index 1f972aae853..0707bae4b4a 100644 --- a/system/bta/le_audio/devices.h +++ b/system/bta/le_audio/devices.h @@ -26,7 +26,6 @@ #include "gatt_api.h" #include "gmap_client.h" #include "le_audio_types.h" -#include "os/log.h" #include "osi/include/alarm.h" #include "raw_address.h" diff --git a/system/bta/le_audio/devices_test.cc b/system/bta/le_audio/devices_test.cc index 1ad0684ce6e..11480961b85 100644 --- a/system/bta/le_audio/devices_test.cc +++ b/system/bta/le_audio/devices_test.cc @@ -32,7 +32,6 @@ #include "le_audio_types.h" #include "mock_codec_manager.h" #include "mock_csis_client.h" -#include "os/log.h" #include "stack/btm/btm_int_types.h" #include "test/mock/mock_main_shim_entry.h" diff --git a/system/bta/le_audio/le_audio_health_status.cc b/system/bta/le_audio/le_audio_health_status.cc index 3b349e81797..5a2c2feb928 100644 --- a/system/bta/le_audio/le_audio_health_status.cc +++ b/system/bta/le_audio/le_audio_health_status.cc @@ -23,7 +23,6 @@ #include "bta/include/bta_groups.h" #include "common/strings.h" #include "main/shim/metrics_api.h" -#include "os/log.h" #include "osi/include/properties.h" using bluetooth::common::ToString; diff --git a/system/bta/le_audio/le_audio_log_history.cc b/system/bta/le_audio/le_audio_log_history.cc index 0022d7b7daf..22fd9399948 100644 --- a/system/bta/le_audio/le_audio_log_history.cc +++ b/system/bta/le_audio/le_audio_log_history.cc @@ -25,7 +25,7 @@ #include "common/circular_buffer.h" #include "common/strings.h" #include "main/shim/dumpsys.h" -#include "os/log.h" +#include "os/logging/log_adapter.h" #include "osi/include/osi.h" #include "osi/include/properties.h" diff --git a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc index 169943323c9..3b8643152d3 100644 --- a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc +++ b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc @@ -29,7 +29,6 @@ #include "flatbuffers/util.h" #include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" -#include "os/log.h" #include "osi/include/osi.h" #include "osi/include/properties.h" diff --git a/system/bta/le_audio/le_audio_utils.cc b/system/bta/le_audio/le_audio_utils.cc index 2e29fd1e030..719d017607a 100644 --- a/system/bta/le_audio/le_audio_utils.cc +++ b/system/bta/le_audio/le_audio_utils.cc @@ -20,7 +20,6 @@ #include "common/strings.h" #include "le_audio_types.h" -#include "os/log.h" using bluetooth::common::ToString; using bluetooth::le_audio::types::AudioContexts; diff --git a/system/bta/le_audio/storage_helper.cc b/system/bta/le_audio/storage_helper.cc index b9f24233c38..916c8249b19 100644 --- a/system/bta/le_audio/storage_helper.cc +++ b/system/bta/le_audio/storage_helper.cc @@ -23,7 +23,6 @@ #include "client_parser.h" #include "common/strings.h" #include "le_audio_types.h" -#include "os/log.h" #include "stack/include/bt_types.h" // TODO(b/369381361) Enfore -Wmissing-prototypes diff --git a/system/bta/ras/ras_utils.cc b/system/bta/ras/ras_utils.cc index d27a6bf697a..2a9b3b9c882 100644 --- a/system/bta/ras/ras_utils.cc +++ b/system/bta/ras/ras_utils.cc @@ -21,7 +21,6 @@ #include "bta/include/bta_gatt_api.h" #include "bta/include/bta_ras_api.h" #include "bta/ras/ras_types.h" -#include "os/log.h" #include "stack/include/bt_types.h" #include "stack/include/btm_ble_addr.h" #include "stack/include/gap_api.h" diff --git a/system/bta/sys/bta_sys_main.cc b/system/bta/sys/bta_sys_main.cc index 4e5ad74d524..524f750ff78 100644 --- a/system/bta/sys/bta_sys_main.cc +++ b/system/bta/sys/bta_sys_main.cc @@ -33,7 +33,6 @@ #include "bta/sys/bta_sys_int.h" #include "include/hardware/bluetooth.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/bta/vc/device.cc b/system/bta/vc/device.cc index ec2088981e0..f4f016f2d9b 100644 --- a/system/bta/vc/device.cc +++ b/system/bta/vc/device.cc @@ -25,7 +25,6 @@ #include "bta/include/bta_gatt_queue.h" #include "bta/vc/devices.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "os/logging/log_adapter.h" #include "stack/btm/btm_sec.h" #include "stack/include/bt_types.h" diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index 6a449c74c35..2c415a59c0b 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -33,7 +33,6 @@ #include "bta/le_audio/le_audio_types.h" #include "bta/vc/devices.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/osi.h" #include "stack/btm/btm_sec.h" #include "stack/include/bt_types.h" diff --git a/system/btcore/src/module.cc b/system/btcore/src/module.cc index 3f809d4d5d3..ec34b326360 100644 --- a/system/btcore/src/module.cc +++ b/system/btcore/src/module.cc @@ -28,7 +28,6 @@ #include #include "common/message_loop_thread.h" -#include "os/log.h" using bluetooth::common::MessageLoopThread; using namespace bluetooth; diff --git a/system/btcore/src/osi_module.cc b/system/btcore/src/osi_module.cc index 22d8f05398a..638748fe030 100644 --- a/system/btcore/src/osi_module.cc +++ b/system/btcore/src/osi_module.cc @@ -21,7 +21,6 @@ #include "btcore/include/osi_module.h" #include "btcore/include/module.h" -#include "os/log.h" #include "osi/include/alarm.h" #include "osi/include/future.h" #include "osi/include/osi.h" diff --git a/system/btif/co/bta_pan_co.cc b/system/btif/co/bta_pan_co.cc index bdc0ac397bb..db84d8bd343 100644 --- a/system/btif/co/bta_pan_co.cc +++ b/system/btif/co/bta_pan_co.cc @@ -36,7 +36,6 @@ #include "btif_pan_internal.h" #include "btif_sock_thread.h" #include "btif_util.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "pan_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h index 64433579f0f..109dd49893a 100644 --- a/system/btif/include/btif_common.h +++ b/system/btif/include/btif_common.h @@ -30,7 +30,6 @@ #include "abstract_message_loop.h" #include "bta/include/bta_api.h" -#include "os/log.h" #include "osi/include/osi.h" #include "stack/include/bt_hdr.h" #include "types/raw_address.h" diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index c62d54c2811..2132172e480 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -52,6 +52,7 @@ #include "device/include/device_iot_config.h" #include "hardware/bt_av.h" #include "include/hardware/bt_rc.h" +#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" diff --git a/system/btif/src/btif_profile_queue.cc b/system/btif/src/btif_profile_queue.cc index b640c70d02e..15237abe75f 100644 --- a/system/btif/src/btif_profile_queue.cc +++ b/system/btif/src/btif_profile_queue.cc @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -53,8 +52,7 @@ public: : address_(address), uuid_(uuid), busy_(false), connect_cb_(connect_cb) {} std::string ToString() const { - return base::StringPrintf("address=%s UUID=%04X busy=%s", ADDRESS_TO_LOGGABLE_CSTR(address_), - uuid_, (busy_) ? "true" : "false"); + return fmt::format("address={} UUID={:04X} busy={}", address_, uuid_, busy_); } const RawAddress& address() const { return address_; } diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index a059d5a05fa..cf244403b14 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -44,6 +44,7 @@ #include "btif_common.h" #include "btif_util.h" #include "device/include/interop.h" +#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/list.h" diff --git a/system/common/base_bind_unittest.cc b/system/common/base_bind_unittest.cc index d31ea01642e..b4f35f53e46 100644 --- a/system/common/base_bind_unittest.cc +++ b/system/common/base_bind_unittest.cc @@ -24,8 +24,6 @@ #include #include -#include "os/log.h" - class BaseBindThreadTest : public ::testing::Test { public: protected: diff --git a/system/device/src/device_iot_config.cc b/system/device/src/device_iot_config.cc index 0918a54f7be..2da612ac47d 100644 --- a/system/device/src/device_iot_config.cc +++ b/system/device/src/device_iot_config.cc @@ -32,7 +32,6 @@ #include "device_iot_config_int.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" diff --git a/system/device/src/device_iot_config_int.cc b/system/device/src/device_iot_config_int.cc index 60f2d884bd7..33b5f8106d6 100644 --- a/system/device/src/device_iot_config_int.cc +++ b/system/device/src/device_iot_config_int.cc @@ -32,7 +32,6 @@ #include "btcore/include/module.h" #include "btif/include/btif_common.h" #include "device/include/device_iot_config.h" -#include "os/log.h" #include "osi/include/alarm.h" #include "osi/include/config.h" #include "osi/include/future.h" diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc index 78b1b70b348..c45031a7b07 100644 --- a/system/device/src/interop.cc +++ b/system/device/src/interop.cc @@ -40,7 +40,6 @@ #include "btif/include/btif_storage.h" #include "device/include/interop_config.h" #include "device/include/interop_database.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" #include "osi/include/config.h" diff --git a/system/gd/common/audit_log.cc b/system/gd/common/audit_log.cc index 74be6f25c99..5897c70aac2 100644 --- a/system/gd/common/audit_log.cc +++ b/system/gd/common/audit_log.cc @@ -16,9 +16,12 @@ #include "common/audit_log.h" +#ifdef __ANDROID__ +#include +#endif // __ANDROID__ + #include "common/strings.h" #include "hci/hci_packets.h" -#include "os/log.h" namespace { #if defined(__ANDROID__) && !defined(FUZZ_TARGET) diff --git a/system/gd/common/byte_array_test.cc b/system/gd/common/byte_array_test.cc index 4798faccf03..b9a64b38823 100644 --- a/system/gd/common/byte_array_test.cc +++ b/system/gd/common/byte_array_test.cc @@ -18,8 +18,6 @@ #include -#include "os/log.h" - using bluetooth::common::ByteArray; namespace { diff --git a/system/gd/common/circular_buffer_test.cc b/system/gd/common/circular_buffer_test.cc index 577bb6681b1..e35a60c98e9 100644 --- a/system/gd/common/circular_buffer_test.cc +++ b/system/gd/common/circular_buffer_test.cc @@ -22,8 +22,6 @@ #include #include -#include "os/log.h" - namespace testing { long long timestamp_{0}; diff --git a/system/gd/common/lru_cache.h b/system/gd/common/lru_cache.h index 75b104f2686..303688d55fd 100644 --- a/system/gd/common/lru_cache.h +++ b/system/gd/common/lru_cache.h @@ -27,7 +27,6 @@ #include #include "common/list_map.h" -#include "os/log.h" namespace bluetooth { namespace common { diff --git a/system/gd/common/metric_id_manager.cc b/system/gd/common/metric_id_manager.cc index 84268dba1df..131b09402cc 100644 --- a/system/gd/common/metric_id_manager.cc +++ b/system/gd/common/metric_id_manager.cc @@ -27,8 +27,6 @@ #include #include -#include "os/log.h" - namespace bluetooth { namespace common { diff --git a/system/gd/common/strings.h b/system/gd/common/strings.h index ed5af390aa3..5593715eb25 100644 --- a/system/gd/common/strings.h +++ b/system/gd/common/strings.h @@ -32,7 +32,6 @@ #include #include "common/type_helper.h" -#include "os/log.h" namespace bluetooth { namespace common { diff --git a/system/gd/common/sync_map_count_test.cc b/system/gd/common/sync_map_count_test.cc index 189e6f47c6a..0e29c324679 100644 --- a/system/gd/common/sync_map_count_test.cc +++ b/system/gd/common/sync_map_count_test.cc @@ -23,8 +23,6 @@ #include #include -#include "os/log.h" - namespace testing { const char* data[] = { diff --git a/system/gd/docs/architecture/style_guide.md b/system/gd/docs/architecture/style_guide.md index bdc5657f9a7..88829823964 100644 --- a/system/gd/docs/architecture/style_guide.md +++ b/system/gd/docs/architecture/style_guide.md @@ -186,24 +186,3 @@ only symbols that should be exposed are: * A header library to all exposed API service to profiles and layers * An entry point to a certification interface, libbluetooth\_certification.so * A header library to this certification stack - -## Logging - -Gabeldorsche uses `printf` style logging with macros defined in `os/log.h`. Five -log levels are available. - -* LOG_VERBOSE(fmt, args...): Will be disabled by default -* LOG_INFO(fmt, args...): Will be disabled by default -* LOG_INFO(fmt, args...): Enabled -* LOG_WARN(fmt, args...): Enabled -* LOG_ERROR(fmt, args...): Enabled -* LOG_ALWAYS_FATAL(fmt, args...): Enabled, will always crash -* ASSERT(condition): Enabled, will crash when condition is false -* ASSERT_LOG(conditon, fmt, args...): Enabled, will crash and print log when - condition is false - -In general, errors that are caused by remote device should never crash our stack -and should be logged using LOG_WARN() only. Recoverable errors due to our stack -or badly behaved bluetooth controller firmware should be logged using -LOG_ERROR() before recovery. Non-recoverable errors should be logged as -LOG_ALWAYS_FATAL() to crash the stack and restart. diff --git a/system/gd/docs/testing/gtest.md b/system/gd/docs/testing/gtest.md index 5120250a227..9ec38f82155 100644 --- a/system/gd/docs/testing/gtest.md +++ b/system/gd/docs/testing/gtest.md @@ -134,7 +134,6 @@ Note: All paths are relative to #include "l2cap/internal/channel_impl.h" #include "l2cap/l2cap_packets.h" #include "os/handler.h" -#include "os/log.h" namespace bluetooth { namespace l2cap { diff --git a/system/gd/dumpsys/internal/filter_internal.cc b/system/gd/dumpsys/internal/filter_internal.cc index a26c56383f6..2db2878f95c 100644 --- a/system/gd/dumpsys/internal/filter_internal.cc +++ b/system/gd/dumpsys/internal/filter_internal.cc @@ -23,7 +23,6 @@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" -#include "os/log.h" #define DBG 0 diff --git a/system/gd/dumpsys/internal/filter_internal_test.cc b/system/gd/dumpsys/internal/filter_internal_test.cc index 2db4b2d0076..38f3481f0c1 100644 --- a/system/gd/dumpsys/internal/filter_internal_test.cc +++ b/system/gd/dumpsys/internal/filter_internal_test.cc @@ -27,7 +27,6 @@ #include "dumpsys/internal/test_data/string_generated.h" #include "dumpsys/internal/test_data/struct_bfbs.h" #include "dumpsys/internal/test_data/struct_generated.h" -#include "os/log.h" namespace testing { diff --git a/system/gd/dumpsys/reflection_schema.cc b/system/gd/dumpsys/reflection_schema.cc index 3ab9fc2803a..b2d79313eb0 100644 --- a/system/gd/dumpsys/reflection_schema.cc +++ b/system/gd/dumpsys/reflection_schema.cc @@ -23,7 +23,6 @@ #include "bundler_schema_generated.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" -#include "os/log.h" using namespace bluetooth; diff --git a/system/gd/facade/grpc_root_server.cc b/system/gd/facade/grpc_root_server.cc index 886e6d9b309..8e3bfb3f3fd 100644 --- a/system/gd/facade/grpc_root_server.cc +++ b/system/gd/facade/grpc_root_server.cc @@ -30,7 +30,6 @@ #include "hci/facade/le_initiator_address_facade.h" #include "hci/facade/le_scanning_manager_facade.h" #include "neighbor/facade/facade.h" -#include "os/log.h" #include "os/thread.h" #include "stack_manager.h" diff --git a/system/gd/grpc/grpc_event_queue.h b/system/gd/grpc/grpc_event_queue.h index c181573ab1d..c7f8c87314a 100644 --- a/system/gd/grpc/grpc_event_queue.h +++ b/system/gd/grpc/grpc_event_queue.h @@ -25,7 +25,6 @@ #include "blueberry/facade/common.pb.h" #include "common/blocking_queue.h" -#include "os/log.h" namespace bluetooth { namespace grpc { diff --git a/system/gd/grpc/grpc_module.cc b/system/gd/grpc/grpc_module.cc index 93979f533e1..53b40f80356 100644 --- a/system/gd/grpc/grpc_module.cc +++ b/system/gd/grpc/grpc_module.cc @@ -18,8 +18,6 @@ #include -#include "os/log.h" - using ::grpc::Server; using ::grpc::ServerBuilder; diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc index c6bba6968ad..79e1cabd859 100644 --- a/system/gd/hal/hci_hal_host.cc +++ b/system/gd/hal/hci_hal_host.cc @@ -37,7 +37,6 @@ #include "hal/mgmt.h" #include "hal/snoop_logger.h" #include "metrics/counter_metrics.h" -#include "os/log.h" #include "os/reactor.h" #include "os/thread.h" diff --git a/system/gd/hal/hci_hal_host_rootcanal.cc b/system/gd/hal/hci_hal_host_rootcanal.cc index 26ffa848942..05d898228d6 100644 --- a/system/gd/hal/hci_hal_host_rootcanal.cc +++ b/system/gd/hal/hci_hal_host_rootcanal.cc @@ -31,7 +31,6 @@ #include "hal/hci_hal_host.h" #include "hal/snoop_logger.h" #include "metrics/counter_metrics.h" -#include "os/log.h" #include "os/reactor.h" #include "os/thread.h" diff --git a/system/gd/hal/hci_hal_host_test.cc b/system/gd/hal/hci_hal_host_test.cc index 14c689738e5..ab0ccef8f67 100644 --- a/system/gd/hal/hci_hal_host_test.cc +++ b/system/gd/hal/hci_hal_host_test.cc @@ -34,7 +34,6 @@ #include "hal/hci_hal.h" #include "hal/serialize_packet.h" -#include "os/log.h" #include "os/thread.h" #include "os/utils.h" #include "packet/raw_builder.h" diff --git a/system/gd/hal/mgmt.cc b/system/gd/hal/mgmt.cc index dd2e0bca6e6..c5de32c3f78 100644 --- a/system/gd/hal/mgmt.cc +++ b/system/gd/hal/mgmt.cc @@ -30,8 +30,6 @@ #include -#include "os/log.h" - extern int GetAdapterIndex(); namespace bluetooth { diff --git a/system/gd/hal/ranging_hal_android.cc b/system/gd/hal/ranging_hal_android.cc index 658b7d777b5..893a25fd106 100644 --- a/system/gd/hal/ranging_hal_android.cc +++ b/system/gd/hal/ranging_hal_android.cc @@ -23,7 +23,7 @@ #include -// AIDL uses syslog.h, so these defines conflict with os/log.h +// AIDL uses syslog.h, so these defines conflict with log/log.h #undef LOG_DEBUG #undef LOG_INFO #undef LOG_WARNING diff --git a/system/gd/hal/ranging_hal_host.cc b/system/gd/hal/ranging_hal_host.cc index 16e44995b6e..36c821f419e 100644 --- a/system/gd/hal/ranging_hal_host.cc +++ b/system/gd/hal/ranging_hal_host.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -// AIDL uses syslog.h, so these defines conflict with os/log.h +// AIDL uses syslog.h, so these defines conflict with log/log.h #undef LOG_DEBUG #undef LOG_INFO #undef LOG_WARNING diff --git a/system/gd/hci/acl_manager/assembler.h b/system/gd/hci/acl_manager/assembler.h index 147cc7a99e2..d126a980a28 100644 --- a/system/gd/hci/acl_manager/assembler.h +++ b/system/gd/hci/acl_manager/assembler.h @@ -26,7 +26,6 @@ #include "hci/acl_manager/acl_connection.h" #include "hci/address_with_type.h" #include "os/handler.h" -#include "os/log.h" #include "packet/packet_view.h" namespace bluetooth { diff --git a/system/gd/hci/acl_manager/classic_acl_connection_test.cc b/system/gd/hci/acl_manager/classic_acl_connection_test.cc index 8cc66ab8076..97ee9fc4afc 100644 --- a/system/gd/hci/acl_manager/classic_acl_connection_test.cc +++ b/system/gd/hci/acl_manager/classic_acl_connection_test.cc @@ -33,7 +33,6 @@ #include "hci/address.h" #include "hci/hci_packets.h" #include "os/handler.h" -#include "os/log.h" #include "os/thread.h" using namespace bluetooth; 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 210cc71125a..f019bf8fe1c 100644 --- a/system/gd/hci/acl_manager/round_robin_scheduler_test.cc +++ b/system/gd/hci/acl_manager/round_robin_scheduler_test.cc @@ -23,7 +23,6 @@ #include "hci/controller.h" #include "hci/hci_packets.h" #include "os/handler.h" -#include "os/log.h" #include "packet/raw_builder.h" using ::bluetooth::common::BidiQueue; diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index b5761e7afa3..78b5a5bfd4a 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -32,7 +32,6 @@ #include "hci/hci_layer.h" #include "module.h" #include "os/handler.h" -#include "os/log.h" #include "os/repeating_alarm.h" #include "packet/packet_view.h" #include "ras/ras_packets.h" diff --git a/system/gd/hci/event_checkers.h b/system/gd/hci/event_checkers.h index 41aca0718f1..a484f5752e1 100644 --- a/system/gd/hci/event_checkers.h +++ b/system/gd/hci/event_checkers.h @@ -19,7 +19,6 @@ #include #include "hci/hci_packets.h" -#include "os/log.h" namespace bluetooth { namespace hci { diff --git a/system/gd/hci/facade/le_advertising_manager_facade.cc b/system/gd/hci/facade/le_advertising_manager_facade.cc index 43b68aedf5e..d9c6cca0d8a 100644 --- a/system/gd/hci/facade/le_advertising_manager_facade.cc +++ b/system/gd/hci/facade/le_advertising_manager_facade.cc @@ -31,7 +31,6 @@ #include "hci/address.h" #include "hci/address_with_type.h" #include "hci/le_advertising_manager.h" -#include "os/log.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/gd/hci/facade/le_scanning_manager_facade.cc b/system/gd/hci/facade/le_scanning_manager_facade.cc index 8a2e7f90eef..243b46ff4e1 100644 --- a/system/gd/hci/facade/le_scanning_manager_facade.cc +++ b/system/gd/hci/facade/le_scanning_manager_facade.cc @@ -28,7 +28,6 @@ #include "common/bind.h" #include "grpc/grpc_event_queue.h" #include "hci/le_scanning_manager.h" -#include "os/log.h" #include "packet/raw_builder.h" namespace bluetooth { diff --git a/system/gd/hci/fuzz/acl_manager_fuzz_test.cc b/system/gd/hci/fuzz/acl_manager_fuzz_test.cc index 527982ced5f..06544789b72 100644 --- a/system/gd/hci/fuzz/acl_manager_fuzz_test.cc +++ b/system/gd/hci/fuzz/acl_manager_fuzz_test.cc @@ -24,7 +24,6 @@ #include "hci/hci_layer.h" #include "module.h" #include "os/fake_timer/fake_timerfd.h" -#include "os/log.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/gd/hci/fuzz/fuzz_hci_layer.h b/system/gd/hci/fuzz/fuzz_hci_layer.h index 07a58fdc74c..10492cdda96 100644 --- a/system/gd/hci/fuzz/fuzz_hci_layer.h +++ b/system/gd/hci/fuzz/fuzz_hci_layer.h @@ -26,7 +26,6 @@ #include "hci/hci_layer.h" #include "os/fuzz/dev_null_queue.h" #include "os/fuzz/fuzz_inject_queue.h" -#include "os/log.h" namespace bluetooth { namespace hci { diff --git a/system/gd/hci/fuzz/hci_layer_fuzz_test.cc b/system/gd/hci/fuzz/hci_layer_fuzz_test.cc index 48191efe1c9..392ffdd3e66 100644 --- a/system/gd/hci/fuzz/hci_layer_fuzz_test.cc +++ b/system/gd/hci/fuzz/hci_layer_fuzz_test.cc @@ -24,7 +24,6 @@ #include "hci/hci_layer.h" #include "module.h" #include "os/fake_timer/fake_timerfd.h" -#include "os/log.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/gd/hci/hci_layer_test.cc b/system/gd/hci/hci_layer_test.cc index 9f8d9ead3cb..1f677d518b7 100644 --- a/system/gd/hci/hci_layer_test.cc +++ b/system/gd/hci/hci_layer_test.cc @@ -24,7 +24,6 @@ #include "hal/hci_hal_fake.h" #include "hci/hci_packets.h" #include "module.h" -#include "os/log.h" #include "os/thread.h" #include "packet/bit_inserter.h" #include "packet/raw_builder.h" diff --git a/system/gd/hci/hci_packets_fuzz_test.cc b/system/gd/hci/hci_packets_fuzz_test.cc index 68ebf7e6daf..2868477c469 100644 --- a/system/gd/hci/hci_packets_fuzz_test.cc +++ b/system/gd/hci/hci_packets_fuzz_test.cc @@ -18,7 +18,6 @@ #include #include "hci/hci_packets.h" -#include "os/log.h" #include "packet/bit_inserter.h" #include "packet/raw_builder.h" diff --git a/system/gd/hci/hci_packets_test.cc b/system/gd/hci/hci_packets_test.cc index 9df54187bba..01121c79229 100644 --- a/system/gd/hci/hci_packets_test.cc +++ b/system/gd/hci/hci_packets_test.cc @@ -20,7 +20,6 @@ #define PACKET_TESTING // Instantiate the tests in the packet files #include "hci/hci_packets.h" -#include "os/log.h" #include "packet/bit_inserter.h" #include "packet/raw_builder.h" diff --git a/system/gd/hci/le_scanning_manager.cc b/system/gd/hci/le_scanning_manager.cc index 4ade641f931..6c9e9744b49 100644 --- a/system/gd/hci/le_scanning_manager.cc +++ b/system/gd/hci/le_scanning_manager.cc @@ -31,7 +31,6 @@ #include "hci/le_scanning_reassembler.h" #include "module.h" #include "os/handler.h" -#include "os/log.h" #include "os/system_properties.h" #include "storage/storage_module.h" diff --git a/system/gd/hci/le_scanning_reassembler.cc b/system/gd/hci/le_scanning_reassembler.cc index c3199221a36..8f8ad06b003 100644 --- a/system/gd/hci/le_scanning_reassembler.cc +++ b/system/gd/hci/le_scanning_reassembler.cc @@ -28,7 +28,6 @@ #include "hci/le_scanning_interface.h" #include "module.h" #include "os/handler.h" -#include "os/log.h" #include "storage/storage_module.h" namespace bluetooth::hci { diff --git a/system/gd/metrics/chromeos/metrics.cc b/system/gd/metrics/chromeos/metrics.cc index fbe7afcba33..9a7541735a6 100644 --- a/system/gd/metrics/chromeos/metrics.cc +++ b/system/gd/metrics/chromeos/metrics.cc @@ -24,7 +24,6 @@ #include "metrics/chromeos/metrics_allowlist.h" #include "metrics/chromeos/metrics_event.h" #include "metrics/utils.h" -#include "os/log.h" namespace bluetooth { namespace metrics { diff --git a/system/gd/metrics/counter_metrics.cc b/system/gd/metrics/counter_metrics.cc index 0155eb1bd09..1315a87df14 100644 --- a/system/gd/metrics/counter_metrics.cc +++ b/system/gd/metrics/counter_metrics.cc @@ -20,7 +20,6 @@ #include #include "common/bind.h" -#include "os/log.h" #include "os/metrics.h" namespace bluetooth { diff --git a/system/gd/module.h b/system/gd/module.h index 14c81ccaf4d..44aa0bcb29e 100644 --- a/system/gd/module.h +++ b/system/gd/module.h @@ -30,7 +30,6 @@ #include "common/bind.h" #include "os/handler.h" -#include "os/log.h" #include "os/thread.h" namespace bluetooth { diff --git a/system/gd/neighbor/name_db.cc b/system/gd/neighbor/name_db.cc index 99eca8d0e12..48cdae47052 100644 --- a/system/gd/neighbor/name_db.cc +++ b/system/gd/neighbor/name_db.cc @@ -28,7 +28,6 @@ #include "hci/remote_name_request.h" #include "module.h" #include "os/handler.h" -#include "os/log.h" namespace bluetooth { namespace neighbor { diff --git a/system/gd/neighbor/scan.cc b/system/gd/neighbor/scan.cc index fafb316b33e..8559f338dae 100644 --- a/system/gd/neighbor/scan.cc +++ b/system/gd/neighbor/scan.cc @@ -25,7 +25,6 @@ #include "hci/hci_packets.h" #include "module.h" #include "os/handler.h" -#include "os/log.h" namespace bluetooth { namespace neighbor { diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc index daea83d0a58..0a2dbd92b6d 100644 --- a/system/gd/os/android/metrics.cc +++ b/system/gd/os/android/metrics.cc @@ -30,7 +30,6 @@ #include "common/strings.h" #include "hardware/bt_av.h" #include "hci/hci_packets.h" -#include "os/log.h" namespace fmt { template <> diff --git a/system/gd/os/android/system_properties.cc b/system/gd/os/android/system_properties.cc index d7dc9e918af..d0f2707173e 100644 --- a/system/gd/os/android/system_properties.cc +++ b/system/gd/os/android/system_properties.cc @@ -23,7 +23,6 @@ #include #include "common/strings.h" -#include "os/log.h" namespace bluetooth { namespace os { diff --git a/system/gd/os/android/wakelock_native.cc b/system/gd/os/android/wakelock_native.cc index d34fa94cabb..bc7d2ae1307 100644 --- a/system/gd/os/android/wakelock_native.cc +++ b/system/gd/os/android/wakelock_native.cc @@ -32,20 +32,6 @@ #include #include -// We want the os/log.h definitions -#undef LOG_DEBUG -#undef LOG_INFO - -#include "os/log.h" - -// Save the os/log.h definitions -#pragma push_macro("LOG_DEBUG") -#pragma push_macro("LOG_INFO") - -// Undef these to avoid conflicting with later imports -#undef LOG_DEBUG -#undef LOG_INFO - using ::aidl::android::system::suspend::ISystemSuspend; using ::aidl::android::system::suspend::IWakeLock; using ::aidl::android::system::suspend::WakeLockType; @@ -54,10 +40,6 @@ namespace bluetooth { namespace os { namespace internal { -// Restore the os/log.h definitions after all imported headers -#pragma pop_macro("LOG_DEBUG") -#pragma pop_macro("LOG_INFO") - static void onSuspendDeath(void* cookie) { auto onDeath = static_cast*>(cookie); (*onDeath)(); diff --git a/system/gd/os/chromeos/metrics.cc b/system/gd/os/chromeos/metrics.cc index 2ec46c8c556..b3795341f2c 100644 --- a/system/gd/os/chromeos/metrics.cc +++ b/system/gd/os/chromeos/metrics.cc @@ -22,7 +22,6 @@ #include #include "metrics/utils.h" -#include "os/log.h" namespace bluetooth { namespace os { diff --git a/system/gd/os/chromeos/parameter_provider.cc b/system/gd/os/chromeos/parameter_provider.cc index 2302a68e119..a8ee19c5a66 100644 --- a/system/gd/os/chromeos/parameter_provider.cc +++ b/system/gd/os/chromeos/parameter_provider.cc @@ -22,8 +22,6 @@ #include #include -#include "os/log.h" - namespace bluetooth { namespace os { diff --git a/system/gd/os/chromeos/wakelock_native.cc b/system/gd/os/chromeos/wakelock_native.cc index 8cf7f71fde4..33c84d45b5a 100644 --- a/system/gd/os/chromeos/wakelock_native.cc +++ b/system/gd/os/chromeos/wakelock_native.cc @@ -22,8 +22,6 @@ #include -#include "os/log.h" - namespace bluetooth { namespace os { namespace internal { diff --git a/system/gd/os/handler.cc b/system/gd/os/handler.cc index f49236fde30..388fcd4c72a 100644 --- a/system/gd/os/handler.cc +++ b/system/gd/os/handler.cc @@ -20,7 +20,6 @@ #include "common/bind.h" #include "common/callback.h" -#include "os/log.h" #include "os/reactor.h" namespace bluetooth { diff --git a/system/gd/os/handler_unittest.cc b/system/gd/os/handler_unittest.cc index 0a06699c391..7306effd302 100644 --- a/system/gd/os/handler_unittest.cc +++ b/system/gd/os/handler_unittest.cc @@ -22,7 +22,6 @@ #include "common/bind.h" #include "common/callback.h" #include "gtest/gtest.h" -#include "os/log.h" namespace bluetooth { namespace os { diff --git a/system/gd/os/host/metrics.cc b/system/gd/os/host/metrics.cc index 27e5d7d470f..a0190333488 100644 --- a/system/gd/os/host/metrics.cc +++ b/system/gd/os/host/metrics.cc @@ -18,8 +18,6 @@ #include "os/metrics.h" -#include "os/log.h" - namespace bluetooth { namespace os { diff --git a/system/gd/os/host/parameter_provider.cc b/system/gd/os/host/parameter_provider.cc index 37d6232ebe8..7b150da4bec 100644 --- a/system/gd/os/host/parameter_provider.cc +++ b/system/gd/os/host/parameter_provider.cc @@ -23,8 +23,6 @@ #include #include -#include "os/log.h" - namespace bluetooth { namespace os { diff --git a/system/gd/os/host/wakelock_native.cc b/system/gd/os/host/wakelock_native.cc index d09d91fbf3d..dd8026d0077 100644 --- a/system/gd/os/host/wakelock_native.cc +++ b/system/gd/os/host/wakelock_native.cc @@ -22,8 +22,6 @@ #include -#include "os/log.h" - namespace bluetooth { namespace os { namespace internal { diff --git a/system/gd/os/linux/metrics.cc b/system/gd/os/linux/metrics.cc index df3a413eee4..c5e38493da7 100644 --- a/system/gd/os/linux/metrics.cc +++ b/system/gd/os/linux/metrics.cc @@ -18,8 +18,6 @@ #include "os/metrics.h" -#include "os/log.h" - namespace bluetooth { namespace os { diff --git a/system/gd/os/linux/parameter_provider.cc b/system/gd/os/linux/parameter_provider.cc index 2302a68e119..a8ee19c5a66 100644 --- a/system/gd/os/linux/parameter_provider.cc +++ b/system/gd/os/linux/parameter_provider.cc @@ -22,8 +22,6 @@ #include #include -#include "os/log.h" - namespace bluetooth { namespace os { diff --git a/system/gd/os/linux/wakelock_native.cc b/system/gd/os/linux/wakelock_native.cc index 8cf7f71fde4..33c84d45b5a 100644 --- a/system/gd/os/linux/wakelock_native.cc +++ b/system/gd/os/linux/wakelock_native.cc @@ -22,8 +22,6 @@ #include -#include "os/log.h" - namespace bluetooth { namespace os { namespace internal { diff --git a/system/gd/os/linux_generic/alarm.cc b/system/gd/os/linux_generic/alarm.cc index 971b595dbc9..46c06e5d26a 100644 --- a/system/gd/os/linux_generic/alarm.cc +++ b/system/gd/os/linux_generic/alarm.cc @@ -25,7 +25,6 @@ #include "common/bind.h" #include "os/linux_generic/linux.h" -#include "os/log.h" #include "os/utils.h" #ifdef __ANDROID__ diff --git a/system/gd/os/linux_generic/files.cc b/system/gd/os/linux_generic/files.cc index 38896cccc79..a759e1d6312 100644 --- a/system/gd/os/linux_generic/files.cc +++ b/system/gd/os/linux_generic/files.cc @@ -28,8 +28,6 @@ #include #include -#include "os/log.h" - namespace { void HandleError(const std::string& temp_path, int* dir_fd, FILE** fp) { diff --git a/system/gd/os/linux_generic/reactive_semaphore.cc b/system/gd/os/linux_generic/reactive_semaphore.cc index 47d1ee9406c..57fc9d6fe92 100644 --- a/system/gd/os/linux_generic/reactive_semaphore.cc +++ b/system/gd/os/linux_generic/reactive_semaphore.cc @@ -24,7 +24,6 @@ #include #include "os/linux_generic/linux.h" -#include "os/log.h" namespace bluetooth { namespace os { diff --git a/system/gd/os/linux_generic/reactor.cc b/system/gd/os/linux_generic/reactor.cc index 58a5f93a11e..4fc2ac92b38 100644 --- a/system/gd/os/linux_generic/reactor.cc +++ b/system/gd/os/linux_generic/reactor.cc @@ -27,8 +27,6 @@ #include #include -#include "os/log.h" - namespace { // Use at most sizeof(epoll_event) * kEpollMaxEvents kernel memory diff --git a/system/gd/os/linux_generic/reactor_unittest.cc b/system/gd/os/linux_generic/reactor_unittest.cc index de6b829a678..d131f5f74d1 100644 --- a/system/gd/os/linux_generic/reactor_unittest.cc +++ b/system/gd/os/linux_generic/reactor_unittest.cc @@ -26,7 +26,6 @@ #include "common/bind.h" #include "common/callback.h" #include "gtest/gtest.h" -#include "os/log.h" namespace bluetooth { namespace os { diff --git a/system/gd/os/linux_generic/repeating_alarm.cc b/system/gd/os/linux_generic/repeating_alarm.cc index f62de8be652..20542228d49 100644 --- a/system/gd/os/linux_generic/repeating_alarm.cc +++ b/system/gd/os/linux_generic/repeating_alarm.cc @@ -24,7 +24,6 @@ #include "common/bind.h" #include "os/linux_generic/linux.h" -#include "os/log.h" #include "os/utils.h" #ifdef __ANDROID__ diff --git a/system/gd/os/linux_generic/thread.cc b/system/gd/os/linux_generic/thread.cc index 9bc2e496b1b..33dfb2a2293 100644 --- a/system/gd/os/linux_generic/thread.cc +++ b/system/gd/os/linux_generic/thread.cc @@ -24,8 +24,6 @@ #include #include -#include "os/log.h" - namespace bluetooth { namespace os { diff --git a/system/gd/os/linux_generic/wakelock_manager.cc b/system/gd/os/linux_generic/wakelock_manager.cc index 022904c942d..b8cc9000ba0 100644 --- a/system/gd/os/linux_generic/wakelock_manager.cc +++ b/system/gd/os/linux_generic/wakelock_manager.cc @@ -26,7 +26,6 @@ #include #include "os/internal/wakelock_native.h" -#include "os/log.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/gd/os/log.h b/system/gd/os/log.h deleted file mode 100644 index 456fbe3f0d9..00000000000 --- a/system/gd/os/log.h +++ /dev/null @@ -1,30 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 - -#include - -#include "os/logging/log_adapter.h" - -#if defined(__ANDROID__) -#include -#include -#endif // defined(__ANDROID__) diff --git a/system/gd/os/mock_queue.h b/system/gd/os/mock_queue.h index 41aa743e9c0..03ede2025b5 100644 --- a/system/gd/os/mock_queue.h +++ b/system/gd/os/mock_queue.h @@ -26,7 +26,6 @@ #include "common/bind.h" #include "common/callback.h" #include "os/handler.h" -#include "os/log.h" #include "os/queue.h" namespace bluetooth { diff --git a/system/gd/os/queue.h b/system/gd/os/queue.h index d722c33a4ab..fef9073202f 100644 --- a/system/gd/os/queue.h +++ b/system/gd/os/queue.h @@ -27,7 +27,6 @@ #include "common/callback.h" #include "os/handler.h" #include "os/linux_generic/reactive_semaphore.h" -#include "os/log.h" namespace bluetooth { namespace os { diff --git a/system/gd/os/rand.h b/system/gd/os/rand.h index edda493b31a..e2b0b649fd2 100644 --- a/system/gd/os/rand.h +++ b/system/gd/os/rand.h @@ -22,8 +22,6 @@ #include #include -#include "os/log.h" - namespace bluetooth { namespace os { diff --git a/system/gd/packet/bit_inserter_unittest.cc b/system/gd/packet/bit_inserter_unittest.cc index 5c78db51ffd..636fa470bd0 100644 --- a/system/gd/packet/bit_inserter_unittest.cc +++ b/system/gd/packet/bit_inserter_unittest.cc @@ -20,8 +20,6 @@ #include -#include "os/log.h" - using bluetooth::packet::BitInserter; using std::vector; diff --git a/system/gd/packet/fragmenting_inserter_unittest.cc b/system/gd/packet/fragmenting_inserter_unittest.cc index dee70a615cb..5d90a5a075d 100644 --- a/system/gd/packet/fragmenting_inserter_unittest.cc +++ b/system/gd/packet/fragmenting_inserter_unittest.cc @@ -20,8 +20,6 @@ #include -#include "os/log.h" - using bluetooth::packet::FragmentingInserter; using std::vector; diff --git a/system/gd/packet/packet_builder.h b/system/gd/packet/packet_builder.h index e86af5289da..19a0be11835 100644 --- a/system/gd/packet/packet_builder.h +++ b/system/gd/packet/packet_builder.h @@ -22,7 +22,6 @@ #include #include -#include "os/log.h" #include "packet/base_packet_builder.h" #include "packet/bit_inserter.h" #include "packet/endian_inserter.h" diff --git a/system/gd/packet/packet_struct.h b/system/gd/packet/packet_struct.h index 92e3200f35e..92ab83e4dba 100644 --- a/system/gd/packet/packet_struct.h +++ b/system/gd/packet/packet_struct.h @@ -22,7 +22,6 @@ #include #include -#include "os/log.h" #include "packet/base_struct.h" #include "packet/bit_inserter.h" #include "packet/endian_inserter.h" diff --git a/system/gd/packet/parser/test/generated_packet_test.cc b/system/gd/packet/parser/test/generated_packet_test.cc index 66ca1fb7ccb..e706e15bee6 100644 --- a/system/gd/packet/parser/test/generated_packet_test.cc +++ b/system/gd/packet/parser/test/generated_packet_test.cc @@ -20,7 +20,7 @@ #include #define PACKET_TESTING -#include "os/log.h" + #include "packet/bit_inserter.h" #include "packet/parser/test/big_endian_test_packets.h" #include "packet/parser/test/six_bytes.h" diff --git a/system/gd/packet/raw_builder.cc b/system/gd/packet/raw_builder.cc index 604d3ee8a1e..49ebeed3517 100644 --- a/system/gd/packet/raw_builder.cc +++ b/system/gd/packet/raw_builder.cc @@ -19,8 +19,6 @@ #include #include -#include "os/log.h" - namespace bluetooth { namespace packet { diff --git a/system/gd/rust/topshim/csis/csis_shim.cc b/system/gd/rust/topshim/csis/csis_shim.cc index 371d4976f59..c08deb019d5 100644 --- a/system/gd/rust/topshim/csis/csis_shim.cc +++ b/system/gd/rust/topshim/csis/csis_shim.cc @@ -21,7 +21,6 @@ #include -#include "os/log.h" #include "src/profiles/csis.rs.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" @@ -101,19 +100,18 @@ public: DBusCsisClientCallbacks() {} void OnConnectionState(const RawAddress& addr, csis::ConnectionState state) override { - log::info("addr={}, state={}", ADDRESS_TO_LOGGABLE_CSTR(addr), static_cast(state)); + log::info("addr={}, state={}", addr, static_cast(state)); topshim::rust::internal::connection_state_cb(addr, state); } void OnDeviceAvailable(const RawAddress& addr, int group_id, int group_size, int rank, const bluetooth::Uuid& uuid) override { - log::info("addr={}, group_id={}, group_size={}, rank={}", ADDRESS_TO_LOGGABLE_CSTR(addr), - group_id, group_size, rank); + log::info("addr={}, group_id={}, group_size={}, rank={}", addr, group_id, group_size, rank); topshim::rust::internal::device_available_cb(addr, group_id, group_size, rank, uuid); } void OnSetMemberAvailable(const RawAddress& addr, int group_id) { - log::info("addr={}, group_id={}", ADDRESS_TO_LOGGABLE_CSTR(addr), group_id); + log::info("addr={}, group_id={}", addr, group_id); topshim::rust::internal::set_member_available_cb(addr, group_id); } diff --git a/system/gd/rust/topshim/hfp/hfp_shim.cc b/system/gd/rust/topshim/hfp/hfp_shim.cc index 12c338e535e..549b54a479c 100644 --- a/system/gd/rust/topshim/hfp/hfp_shim.cc +++ b/system/gd/rust/topshim/hfp/hfp_shim.cc @@ -22,7 +22,6 @@ #include "common/strings.h" #include "device/include/interop.h" #include "include/hardware/bt_hf.h" -#include "os/log.h" #include "src/profiles/hfp.rs.h" #include "types/raw_address.h" diff --git a/system/gd/rust/topshim/le_audio/le_audio_shim.cc b/system/gd/rust/topshim/le_audio/le_audio_shim.cc index bb70fc37d08..77d7a5c60d5 100644 --- a/system/gd/rust/topshim/le_audio/le_audio_shim.cc +++ b/system/gd/rust/topshim/le_audio/le_audio_shim.cc @@ -22,7 +22,6 @@ #include #include "bta/le_audio/le_audio_types.h" -#include "os/log.h" #include "src/profiles/le_audio.rs.h" #include "types/raw_address.h" @@ -253,7 +252,7 @@ public: } void OnConnectionState(le_audio::ConnectionState state, const RawAddress& address) override { - log::info("state={}, address={}", static_cast(state), ADDRESS_TO_LOGGABLE_CSTR(address)); + log::info("state={}, address={}", static_cast(state), address); topshim::rust::internal::connection_state_cb(state, address); } @@ -264,8 +263,8 @@ public: void OnGroupNodeStatus(const RawAddress& bd_addr, int group_id, le_audio::GroupNodeStatus node_status) { - log::info("bd_addr={}, group_id={}, node_status={}", ADDRESS_TO_LOGGABLE_CSTR(bd_addr), - group_id, static_cast(node_status)); + log::info("bd_addr={}, group_id={}, node_status={}", bd_addr, group_id, + static_cast(node_status)); topshim::rust::internal::group_node_status_cb(bd_addr, group_id, node_status); } @@ -280,8 +279,7 @@ public: } void OnSinkAudioLocationAvailable(const RawAddress& address, uint32_t snk_audio_locations) { - log::info("address={}, snk_audio_locations={}", ADDRESS_TO_LOGGABLE_CSTR(address), - snk_audio_locations); + log::info("address={}, snk_audio_locations={}", address, snk_audio_locations); topshim::rust::internal::sink_audio_location_available_cb(address, snk_audio_locations); } @@ -323,7 +321,7 @@ public: void OnHealthBasedRecommendationAction(const RawAddress& address, le_audio::LeAudioHealthBasedAction action) { - log::info("address={}, action={}", ADDRESS_TO_LOGGABLE_CSTR(address), static_cast(action)); + log::info("address={}, action={}", address, static_cast(action)); } void OnHealthBasedGroupRecommendationAction(int group_id, diff --git a/system/gd/rust/topshim/vc/vc_shim.cc b/system/gd/rust/topshim/vc/vc_shim.cc index 55d8369db69..f7f68d5af25 100644 --- a/system/gd/rust/topshim/vc/vc_shim.cc +++ b/system/gd/rust/topshim/vc/vc_shim.cc @@ -21,7 +21,6 @@ #include -#include "os/log.h" #include "src/profiles/vc.rs.h" #include "types/raw_address.h" @@ -94,14 +93,14 @@ public: DBusVolumeControlCallbacks() {} void OnConnectionState(vc::ConnectionState state, const RawAddress& address) override { - log::info("state={}, address={}", static_cast(state), ADDRESS_TO_LOGGABLE_CSTR(address)); + log::info("state={}, address={}", static_cast(state), address); topshim::rust::internal::connection_state_cb(state, address); } void OnVolumeStateChanged(const RawAddress& address, uint8_t volume, bool mute, uint8_t flags, bool is_autonomous) override { - log::info("address={}, volume={}, mute={}, flags={}, is_autonomous={}", - ADDRESS_TO_LOGGABLE_CSTR(address), volume, mute, flags, is_autonomous); + log::info("address={}, volume={}, mute={}, flags={}, is_autonomous={}", address, volume, mute, + flags, is_autonomous); topshim::rust::internal::volume_state_cb(address, volume, mute, is_autonomous); } @@ -120,22 +119,19 @@ public: void OnExtAudioOutVolumeOffsetChanged(const RawAddress& address, uint8_t ext_output_id, int16_t offset) override { - log::info("address={}, ext_output_id={}, offset={}", ADDRESS_TO_LOGGABLE_CSTR(address), - ext_output_id, offset); + log::info("address={}, ext_output_id={}, offset={}", address, ext_output_id, offset); topshim::rust::internal::ext_audio_out_volume_offset_cb(address, ext_output_id, offset); } void OnExtAudioOutLocationChanged(const RawAddress& address, uint8_t ext_output_id, uint32_t location) override { - log::info("address={}, ext_output_id, location={}", ADDRESS_TO_LOGGABLE_CSTR(address), - ext_output_id, location); + log::info("address={}, ext_output_id, location={}", address, ext_output_id, location); topshim::rust::internal::ext_audio_out_location_cb(address, ext_output_id, location); } void OnExtAudioOutDescriptionChanged(const RawAddress& address, uint8_t ext_output_id, std::string descr) override { - log::info("address={}, ext_output_id={}, descr={}", ADDRESS_TO_LOGGABLE_CSTR(address), - ext_output_id, descr.c_str()); + log::info("address={}, ext_output_id={}, descr={}", address, ext_output_id, descr.c_str()); topshim::rust::internal::ext_audio_out_description_cb(address, ext_output_id, descr); } diff --git a/system/gd/shim/dumpsys.cc b/system/gd/shim/dumpsys.cc index 24a0083175f..30d9f70c0b5 100644 --- a/system/gd/shim/dumpsys.cc +++ b/system/gd/shim/dumpsys.cc @@ -30,7 +30,6 @@ #include "main/shim/stack.h" #include "module.h" #include "module_dumper.h" -#include "os/log.h" #include "os/system_properties.h" #include "shim/dumpsys.h" diff --git a/system/gd/stack_manager.cc b/system/gd/stack_manager.cc index d62507400cc..856d10a3c49 100644 --- a/system/gd/stack_manager.cc +++ b/system/gd/stack_manager.cc @@ -25,7 +25,6 @@ #include "common/bind.h" #include "module.h" #include "os/handler.h" -#include "os/log.h" #include "os/system_properties.h" #include "os/thread.h" #include "os/wakelock_manager.h" diff --git a/system/gd/storage/device.cc b/system/gd/storage/device.cc index 50d973bdc51..7210a110fe4 100644 --- a/system/gd/storage/device.cc +++ b/system/gd/storage/device.cc @@ -21,7 +21,6 @@ #include #include -#include "os/log.h" #include "storage/classic_device.h" #include "storage/config_cache_helper.h" #include "storage/le_device.h" diff --git a/system/gd/storage/legacy_config_file.cc b/system/gd/storage/legacy_config_file.cc index a64be377ea2..0bee52af036 100644 --- a/system/gd/storage/legacy_config_file.cc +++ b/system/gd/storage/legacy_config_file.cc @@ -24,7 +24,6 @@ #include "common/strings.h" #include "os/files.h" -#include "os/log.h" #include "storage/device.h" namespace bluetooth { diff --git a/system/gd/storage/mutation.cc b/system/gd/storage/mutation.cc index c0dacdcc802..559a0415d9e 100644 --- a/system/gd/storage/mutation.cc +++ b/system/gd/storage/mutation.cc @@ -16,8 +16,6 @@ #include "storage/mutation.h" -#include "os/log.h" - namespace bluetooth { namespace storage { diff --git a/system/gd/storage/mutation.h b/system/gd/storage/mutation.h index ddaf5804f27..493faddacec 100644 --- a/system/gd/storage/mutation.h +++ b/system/gd/storage/mutation.h @@ -17,7 +17,6 @@ #include -#include "os/log.h" #include "storage/config_cache.h" #include "storage/mutation_entry.h" diff --git a/system/gd/storage/mutation_entry.cc b/system/gd/storage/mutation_entry.cc index 6d078d60a88..f1c930e576f 100644 --- a/system/gd/storage/mutation_entry.cc +++ b/system/gd/storage/mutation_entry.cc @@ -16,8 +16,6 @@ #include "storage/mutation_entry.h" -#include "os/log.h" - namespace bluetooth { namespace storage { diff --git a/system/gd/sysprops/sysprops_module.cc b/system/gd/sysprops/sysprops_module.cc index dfb5bfbc5a8..0cdcaa2efa9 100644 --- a/system/gd/sysprops/sysprops_module.cc +++ b/system/gd/sysprops/sysprops_module.cc @@ -19,7 +19,6 @@ #include #include "os/handler.h" -#include "os/log.h" #include "os/parameter_provider.h" #include "os/system_properties.h" #include "storage/legacy_config_file.h" diff --git a/system/hci/src/packet_fragmenter.cc b/system/hci/src/packet_fragmenter.cc index 9ecb6bd7b5a..c95c25dfe68 100644 --- a/system/hci/src/packet_fragmenter.cc +++ b/system/hci/src/packet_fragmenter.cc @@ -28,7 +28,6 @@ #include "hci/include/buffer_allocator.h" #include "hci/include/hci_layer.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" diff --git a/system/main/shim/config.cc b/system/main/shim/config.cc index efa9e142219..a2568e455cb 100644 --- a/system/main/shim/config.cc +++ b/system/main/shim/config.cc @@ -23,7 +23,6 @@ #include #include "main/shim/entry.h" -#include "os/log.h" #include "storage/storage_module.h" using ::bluetooth::shim::GetStorage; diff --git a/system/main/stack_config.cc b/system/main/stack_config.cc index ae5ebc4da51..9b04e7f16cd 100644 --- a/system/main/stack_config.cc +++ b/system/main/stack_config.cc @@ -22,7 +22,6 @@ #include -#include "os/log.h" #include "osi/include/future.h" using namespace bluetooth; diff --git a/system/osi/src/alarm.cc b/system/osi/src/alarm.cc index 0d515c486df..a280442bb0b 100644 --- a/system/osi/src/alarm.cc +++ b/system/osi/src/alarm.cc @@ -32,7 +32,6 @@ #include -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/fixed_queue.h" #include "osi/include/list.h" diff --git a/system/osi/src/future.cc b/system/osi/src/future.cc index 63dc2541235..ce8c7f0b4b2 100644 --- a/system/osi/src/future.cc +++ b/system/osi/src/future.cc @@ -22,7 +22,6 @@ #include -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "osi/semaphore.h" diff --git a/system/osi/src/internal/semaphore.cc b/system/osi/src/internal/semaphore.cc index 23aa60c1315..8f2706862fa 100644 --- a/system/osi/src/internal/semaphore.cc +++ b/system/osi/src/internal/semaphore.cc @@ -27,7 +27,6 @@ #include #include -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" diff --git a/system/osi/src/reactor.cc b/system/osi/src/reactor.cc index 045bc24f3c0..82522172c58 100644 --- a/system/osi/src/reactor.cc +++ b/system/osi/src/reactor.cc @@ -30,7 +30,6 @@ #include -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/list.h" diff --git a/system/osi/src/socket.cc b/system/osi/src/socket.cc index c1694e68c38..0c7c96b71c6 100644 --- a/system/osi/src/socket.cc +++ b/system/osi/src/socket.cc @@ -28,7 +28,6 @@ #include #include -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "osi/include/reactor.h" diff --git a/system/osi/src/stack_power_telemetry.cc b/system/osi/src/stack_power_telemetry.cc index f8ca11e32c9..262bb2afb2c 100644 --- a/system/osi/src/stack_power_telemetry.cc +++ b/system/osi/src/stack_power_telemetry.cc @@ -28,7 +28,7 @@ #include #include -#include "os/log.h" +#include "os/logging/log_adapter.h" #include "osi/include/properties.h" #include "stack/include/acl_api_types.h" #include "stack/include/bt_psm_types.h" diff --git a/system/osi/src/thread.cc b/system/osi/src/thread.cc index b43a576458a..0fa15fc6d38 100644 --- a/system/osi/src/thread.cc +++ b/system/osi/src/thread.cc @@ -32,7 +32,6 @@ #include #include -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" #include "osi/include/fixed_queue.h" diff --git a/system/osi/src/wakelock.cc b/system/osi/src/wakelock.cc index 9865ecb16a1..5cae5ed5803 100644 --- a/system/osi/src/wakelock.cc +++ b/system/osi/src/wakelock.cc @@ -34,7 +34,6 @@ #include #include "common/metrics.h" -#include "os/log.h" #include "osi/include/osi.h" using bluetooth::common::BluetoothMetricsLogger; diff --git a/system/rust/src/core/ffi/module.cc b/system/rust/src/core/ffi/module.cc index 5e79d143fad..edd2b13b587 100644 --- a/system/rust/src/core/ffi/module.cc +++ b/system/rust/src/core/ffi/module.cc @@ -20,7 +20,7 @@ #include #include "btcore/include/module.h" -#include "os/log.h" + #ifndef TARGET_FLOSS #include "src/core/ffi.rs.h" #include "src/gatt/ffi.rs.h" diff --git a/system/rust/src/gatt/ffi/gatt_shim.cc b/system/rust/src/gatt/ffi/gatt_shim.cc index 3b17f83cdac..442c5b5fa44 100644 --- a/system/rust/src/gatt/ffi/gatt_shim.cc +++ b/system/rust/src/gatt/ffi/gatt_shim.cc @@ -26,7 +26,6 @@ #include "include/hardware/bt_common_types.h" #include "include/hardware/bt_gatt_client.h" #include "include/hardware/bt_gatt_server.h" -#include "os/log.h" #include "rust/cxx.h" #include "stack/include/gatt_api.h" #include "types/bluetooth/uuid.h" diff --git a/system/stack/a2dp/a2dp_aac.cc b/system/stack/a2dp/a2dp_aac.cc index 1784e824c53..ca0dec4037f 100644 --- a/system/stack/a2dp/a2dp_aac.cc +++ b/system/stack/a2dp/a2dp_aac.cc @@ -31,7 +31,6 @@ #include "a2dp_aac_decoder.h" #include "a2dp_aac_encoder.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/osi.h" #include "osi/include/properties.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_aac_decoder.cc b/system/stack/a2dp/a2dp_aac_decoder.cc index e1fb4f49292..fba7ea44cf3 100644 --- a/system/stack/a2dp/a2dp_aac_decoder.cc +++ b/system/stack/a2dp/a2dp_aac_decoder.cc @@ -21,7 +21,6 @@ #include #include -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_aac_encoder.cc b/system/stack/a2dp/a2dp_aac_encoder.cc index d322d7f8cf1..774fdd92ae0 100644 --- a/system/stack/a2dp/a2dp_aac_encoder.cc +++ b/system/stack/a2dp/a2dp_aac_encoder.cc @@ -26,7 +26,6 @@ #include "a2dp_aac.h" #include "common/time_util.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_sbc_encoder.cc b/system/stack/a2dp/a2dp_sbc_encoder.cc index c0c923ec827..e5cb5552621 100644 --- a/system/stack/a2dp/a2dp_sbc_encoder.cc +++ b/system/stack/a2dp/a2dp_sbc_encoder.cc @@ -25,11 +25,14 @@ #include #include +#include + #include "a2dp_sbc.h" #include "a2dp_sbc_up_sample.h" #include "common/time_util.h" #include "embdrv/sbc/encoder/include/sbc_encoder.h" #include "internal_include/bt_target.h" +#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc index 969a06643da..7bb81bf2443 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc @@ -28,7 +28,6 @@ #include "aptXbtenc.h" #include "common/time_util.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd.cc index f6ed0c6cfa5..cc599366383 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_hd.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_hd.cc @@ -32,7 +32,6 @@ #include "a2dp_vendor_aptx_hd_encoder.h" #include "btif/include/btif_av_co.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/osi.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc index d6daf805a58..b6996d0108e 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc @@ -28,7 +28,6 @@ #include "aptXHDbtenc.h" #include "common/time_util.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_vendor_ldac.cc b/system/stack/a2dp/a2dp_vendor_ldac.cc index b3ad871b310..8c1519eb651 100644 --- a/system/stack/a2dp/a2dp_vendor_ldac.cc +++ b/system/stack/a2dp/a2dp_vendor_ldac.cc @@ -32,7 +32,6 @@ #include "a2dp_vendor_ldac_encoder.h" #include "btif/include/btif_av_co.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/osi.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc b/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc index 4babdc79dc0..4107e64e90a 100644 --- a/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc +++ b/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc @@ -26,7 +26,6 @@ #include #include "a2dp_vendor_ldac.h" -#include "os/log.h" #include "stack/include/bt_hdr.h" using namespace bluetooth; diff --git a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc index 7a616a038a3..d89de9a550c 100644 --- a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc @@ -31,7 +31,6 @@ #include "a2dp_vendor_ldac.h" #include "common/time_util.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/a2dp/a2dp_vendor_opus.cc b/system/stack/a2dp/a2dp_vendor_opus.cc index f6fb3c3e2d5..fac881856f3 100644 --- a/system/stack/a2dp/a2dp_vendor_opus.cc +++ b/system/stack/a2dp/a2dp_vendor_opus.cc @@ -31,7 +31,6 @@ #include "a2dp_vendor_opus_decoder.h" #include "a2dp_vendor_opus_encoder.h" #include "internal_include/bt_trace.h" -#include "os/log.h" #include "osi/include/osi.h" using namespace bluetooth; diff --git a/system/stack/a2dp/a2dp_vendor_opus_decoder.cc b/system/stack/a2dp/a2dp_vendor_opus_decoder.cc index 25658e60c0c..bbbd3a2c3bf 100644 --- a/system/stack/a2dp/a2dp_vendor_opus_decoder.cc +++ b/system/stack/a2dp/a2dp_vendor_opus_decoder.cc @@ -22,7 +22,6 @@ #include #include "a2dp_vendor_opus.h" -#include "os/log.h" #include "osi/include/allocator.h" using namespace bluetooth; diff --git a/system/stack/a2dp/a2dp_vendor_opus_encoder.cc b/system/stack/a2dp/a2dp_vendor_opus_encoder.cc index b59288c7c64..e7476c10281 100644 --- a/system/stack/a2dp/a2dp_vendor_opus_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_opus_encoder.cc @@ -26,7 +26,6 @@ #include "a2dp_vendor.h" #include "a2dp_vendor_opus.h" #include "common/time_util.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/acl/btm_pm.cc b/system/stack/acl/btm_pm.cc index f77efd47b71..c34e776a1f9 100644 --- a/system/stack/acl/btm_pm.cc +++ b/system/stack/acl/btm_pm.cc @@ -42,7 +42,6 @@ #include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" #include "main/shim/entry.h" -#include "os/log.h" #include "osi/include/stack_power_telemetry.h" #include "stack/btm/btm_int_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc index c8e12c4f08f..01673e08548 100644 --- a/system/stack/avct/avct_lcb.cc +++ b/system/stack/avct/avct_lcb.cc @@ -32,7 +32,6 @@ #include "avct_int.h" #include "device/include/device_iot_config.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "types/raw_address.h" diff --git a/system/stack/avdt/avdt_api.cc b/system/stack/avdt/avdt_api.cc index d293517a548..6304e782557 100644 --- a/system/stack/avdt/avdt_api.cc +++ b/system/stack/avdt/avdt_api.cc @@ -35,6 +35,7 @@ #include "avdtc_api.h" #include "bta/include/bta_sec_api.h" #include "internal_include/bt_target.h" +#include "os/logging/log_adapter.h" #include "stack/include/a2dp_codec_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" diff --git a/system/stack/avdt/avdt_msg.cc b/system/stack/avdt/avdt_msg.cc index d8d52693405..4241cd741a7 100644 --- a/system/stack/avdt/avdt_msg.cc +++ b/system/stack/avdt/avdt_msg.cc @@ -35,7 +35,6 @@ #include "avdt_int.h" #include "avdtc_api.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/avrc/avrc_api.cc b/system/stack/avrc/avrc_api.cc index 60d1da067ed..2acddeb5e0f 100644 --- a/system/stack/avrc/avrc_api.cc +++ b/system/stack/avrc/avrc_api.cc @@ -31,7 +31,6 @@ #include "btif/include/btif_av.h" #include "btif/include/btif_config.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/fixed_queue.h" #include "osi/include/properties.h" diff --git a/system/stack/avrc/avrc_bld_ct.cc b/system/stack/avrc/avrc_bld_ct.cc index 3ec21640460..a68c9dca9d9 100644 --- a/system/stack/avrc/avrc_bld_ct.cc +++ b/system/stack/avrc/avrc_bld_ct.cc @@ -25,7 +25,6 @@ #include "avrc_defs.h" #include "avrc_int.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" diff --git a/system/stack/avrc/avrc_bld_tg.cc b/system/stack/avrc/avrc_bld_tg.cc index 63902322931..7b5791a8c2c 100644 --- a/system/stack/avrc/avrc_bld_tg.cc +++ b/system/stack/avrc/avrc_bld_tg.cc @@ -24,7 +24,6 @@ #include "avrc_defs.h" #include "avrc_int.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "stack/avct/avct_defs.h" diff --git a/system/stack/avrc/avrc_pars_ct.cc b/system/stack/avrc/avrc_pars_ct.cc index 045cee3dd2f..2560ebab990 100644 --- a/system/stack/avrc/avrc_pars_ct.cc +++ b/system/stack/avrc/avrc_pars_ct.cc @@ -21,7 +21,6 @@ #include "avrc_api.h" #include "avrc_defs.h" #include "avrc_int.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "stack/include/bt_types.h" diff --git a/system/stack/avrc/avrc_pars_tg.cc b/system/stack/avrc/avrc_pars_tg.cc index b178fd5acb3..dd4f9bdcfe4 100644 --- a/system/stack/avrc/avrc_pars_tg.cc +++ b/system/stack/avrc/avrc_pars_tg.cc @@ -21,7 +21,6 @@ #include "avrc_api.h" #include "avrc_defs.h" #include "avrc_int.h" -#include "os/log.h" #include "stack/include/bt_types.h" using namespace bluetooth; diff --git a/system/stack/avrc/avrc_sdp.cc b/system/stack/avrc/avrc_sdp.cc index cb209dde09e..d4ed5bb4211 100644 --- a/system/stack/avrc/avrc_sdp.cc +++ b/system/stack/avrc/avrc_sdp.cc @@ -28,7 +28,6 @@ #include "avrc_api.h" #include "avrc_int.h" -#include "os/log.h" #include "stack/include/bt_types.h" #include "stack/include/bt_uuid16.h" #include "stack/include/sdp_api.h" diff --git a/system/stack/avrc/avrc_utils.cc b/system/stack/avrc/avrc_utils.cc index cf2d428385b..6e07b12d738 100644 --- a/system/stack/avrc/avrc_utils.cc +++ b/system/stack/avrc/avrc_utils.cc @@ -22,7 +22,6 @@ #include "avrc_api.h" #include "avrc_int.h" -#include "os/log.h" #include "stack/include/bt_types.h" using namespace bluetooth; diff --git a/system/stack/btm/btm_ble_addr.cc b/system/stack/btm/btm_ble_addr.cc index 308a69cd85b..aae99cc80fc 100644 --- a/system/stack/btm/btm_ble_addr.cc +++ b/system/stack/btm/btm_ble_addr.cc @@ -36,7 +36,6 @@ #include "crypto_toolbox/crypto_toolbox.h" #include "hci/controller_interface.h" #include "main/shim/entry.h" -#include "os/log.h" #include "stack/btm/btm_int_types.h" #include "stack/include/acl_api.h" #include "stack/include/bt_octets.h" diff --git a/system/stack/btm/btm_iso_impl.h b/system/stack/btm/btm_iso_impl.h index ddebeb94399..fcd97d03326 100644 --- a/system/stack/btm/btm_iso_impl.h +++ b/system/stack/btm/btm_iso_impl.h @@ -33,7 +33,6 @@ #include "internal_include/stack_config.h" #include "main/shim/entry.h" #include "main/shim/hci_layer.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" diff --git a/system/stack/btm/btm_sco_hci.cc b/system/stack/btm/btm_sco_hci.cc index a7f5e152ace..dc9d1896918 100644 --- a/system/stack/btm/btm_sco_hci.cc +++ b/system/stack/btm/btm_sco_hci.cc @@ -28,7 +28,6 @@ #include "bta/ag/bta_ag_int.h" #include "btif/include/core_callbacks.h" #include "btif/include/stack_manager_t.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/btm/btm_sco.h" #include "udrv/include/uipc.h" diff --git a/system/stack/btm/btm_sco_hfp_hal_linux.cc b/system/stack/btm/btm_sco_hfp_hal_linux.cc index 018ba1fd652..9ca83962ee9 100644 --- a/system/stack/btm/btm_sco_hfp_hal_linux.cc +++ b/system/stack/btm/btm_sco_hfp_hal_linux.cc @@ -23,7 +23,6 @@ #include "hci/controller_interface.h" #include "main/shim/entry.h" -#include "os/log.h" #include "osi/include/properties.h" #include "stack/btm/btm_sco_hfp_hal.h" #include "stack/include/hcimsgs.h" diff --git a/system/stack/btm/btm_sec_cb.cc b/system/stack/btm/btm_sec_cb.cc index 3e87d19810a..60a2f0398e1 100644 --- a/system/stack/btm/btm_sec_cb.cc +++ b/system/stack/btm/btm_sec_cb.cc @@ -25,7 +25,6 @@ #include "internal_include/bt_trace.h" #include "internal_include/stack_config.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/fixed_queue.h" #include "osi/include/list.h" diff --git a/system/stack/btm/btm_security_client_interface.cc b/system/stack/btm/btm_security_client_interface.cc index a8a4a1c5567..f2d397a9a74 100644 --- a/system/stack/btm/btm_security_client_interface.cc +++ b/system/stack/btm/btm_security_client_interface.cc @@ -19,7 +19,6 @@ #include -#include "os/log.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" #include "stack/btm/btm_sec_cb.h" diff --git a/system/stack/btm/hfp_lc3_decoder.cc b/system/stack/btm/hfp_lc3_decoder.cc index 30e30d1ffc8..245527b0dc8 100644 --- a/system/stack/btm/hfp_lc3_decoder.cc +++ b/system/stack/btm/hfp_lc3_decoder.cc @@ -23,7 +23,6 @@ #include -#include "os/log.h" #include "osi/include/allocator.h" using namespace bluetooth; diff --git a/system/stack/btm/hfp_lc3_decoder_linux.cc b/system/stack/btm/hfp_lc3_decoder_linux.cc index b30da4ff194..0ba81c9dd04 100644 --- a/system/stack/btm/hfp_lc3_decoder_linux.cc +++ b/system/stack/btm/hfp_lc3_decoder_linux.cc @@ -23,7 +23,6 @@ #include "hfp_lc3_decoder.h" #include "mmc/codec_client/codec_client.h" #include "mmc/proto/mmc_config.pb.h" -#include "os/log.h" using namespace bluetooth; diff --git a/system/stack/btm/hfp_lc3_encoder.cc b/system/stack/btm/hfp_lc3_encoder.cc index 6e0cdb28df9..9d909fef0dc 100644 --- a/system/stack/btm/hfp_lc3_encoder.cc +++ b/system/stack/btm/hfp_lc3_encoder.cc @@ -23,7 +23,6 @@ #include -#include "os/log.h" #include "osi/include/allocator.h" using namespace bluetooth; diff --git a/system/stack/btm/hfp_lc3_encoder_linux.cc b/system/stack/btm/hfp_lc3_encoder_linux.cc index 448e6403c2a..21f8d55d688 100644 --- a/system/stack/btm/hfp_lc3_encoder_linux.cc +++ b/system/stack/btm/hfp_lc3_encoder_linux.cc @@ -21,7 +21,6 @@ #include "hfp_lc3_encoder.h" #include "mmc/codec_client/codec_client.h" #include "mmc/proto/mmc_config.pb.h" -#include "os/log.h" using namespace bluetooth; diff --git a/system/stack/btm/hfp_msbc_decoder.cc b/system/stack/btm/hfp_msbc_decoder.cc index 334cf91f9f7..d1396a771d4 100644 --- a/system/stack/btm/hfp_msbc_decoder.cc +++ b/system/stack/btm/hfp_msbc_decoder.cc @@ -24,7 +24,6 @@ #include "embdrv/sbc/decoder/include/oi_codec_sbc.h" #include "embdrv/sbc/decoder/include/oi_status.h" -#include "os/log.h" #define HFP_MSBC_PKT_LEN 60 #define HFP_MSBC_PCM_BYTES 240 diff --git a/system/stack/btm/security_device_record.h b/system/stack/btm/security_device_record.h index 14463ac2113..c1037a40f49 100644 --- a/system/stack/btm/security_device_record.h +++ b/system/stack/btm/security_device_record.h @@ -26,7 +26,7 @@ #include "internal_include/bt_target.h" #include "macros.h" -#include "os/log.h" +#include "os/logging/log_adapter.h" #include "stack/include/bt_device_type.h" #include "stack/include/bt_name.h" #include "stack/include/bt_octets.h" diff --git a/system/stack/btu/main_thread.cc b/system/stack/btu/main_thread.cc index 03afc210f57..6223e667161 100644 --- a/system/stack/btu/main_thread.cc +++ b/system/stack/btu/main_thread.cc @@ -27,7 +27,6 @@ #include "common/message_loop_thread.h" #include "include/hardware/bluetooth.h" -#include "os/log.h" using bluetooth::common::MessageLoopThread; using namespace bluetooth; diff --git a/system/stack/gatt/gatt_int.h b/system/stack/gatt/gatt_int.h index 485c7f6a344..59dc338b5df 100644 --- a/system/stack/gatt/gatt_int.h +++ b/system/stack/gatt/gatt_int.h @@ -34,6 +34,7 @@ #include "gatt_api.h" #include "internal_include/bt_target.h" #include "macros.h" +#include "os/logging/log_adapter.h" #include "osi/include/fixed_queue.h" #include "stack/include/bt_hdr.h" #include "types/bluetooth/uuid.h" diff --git a/system/stack/hid/hidd_api.cc b/system/stack/hid/hidd_api.cc index 3a213d4c1dc..79f4d1d7b00 100644 --- a/system/stack/hid/hidd_api.cc +++ b/system/stack/hid/hidd_api.cc @@ -34,7 +34,6 @@ #include "hidd_int.h" #include "hiddefs.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/hid/hidh_api.cc b/system/stack/hid/hidh_api.cc index 72c30e3f13a..f415c48fb11 100644 --- a/system/stack/hid/hidh_api.cc +++ b/system/stack/hid/hidh_api.cc @@ -34,7 +34,6 @@ #include "hiddefs.h" #include "hidh_int.h" #include "internal_include/bt_target.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_uuid16.h" diff --git a/system/stack/include/avdt_api.h b/system/stack/include/avdt_api.h index 30a7ebea265..c1275db1059 100644 --- a/system/stack/include/avdt_api.h +++ b/system/stack/include/avdt_api.h @@ -33,7 +33,6 @@ #include "internal_include/bt_target.h" #include "macros.h" -#include "os/log.h" #include "stack/include/bt_hdr.h" #include "types/raw_address.h" diff --git a/system/stack/pan/pan_api.cc b/system/stack/pan/pan_api.cc index 496a92050ac..1fb209a17b1 100644 --- a/system/stack/pan/pan_api.cc +++ b/system/stack/pan/pan_api.cc @@ -36,7 +36,7 @@ #include "bta/sys/bta_sys.h" #include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" -#include "os/log.h" +#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/bnep_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/pan/pan_main.cc b/system/stack/pan/pan_main.cc index 88b433ed81d..0b3cb558985 100644 --- a/system/stack/pan/pan_main.cc +++ b/system/stack/pan/pan_main.cc @@ -31,7 +31,6 @@ #include -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/bnep_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/pan/pan_utils.cc b/system/stack/pan/pan_utils.cc index eda89c4bed7..eef94310040 100644 --- a/system/stack/pan/pan_utils.cc +++ b/system/stack/pan/pan_utils.cc @@ -30,7 +30,6 @@ #include #include "internal_include/bt_target.h" -#include "os/log.h" #include "stack/include/bt_types.h" #include "stack/include/bt_uuid16.h" #include "stack/include/sdp_api.h" diff --git a/system/stack/smp/smp_br_main.cc b/system/stack/smp/smp_br_main.cc index 12ee3740112..20e6459a028 100644 --- a/system/stack/smp/smp_br_main.cc +++ b/system/stack/smp/smp_br_main.cc @@ -20,7 +20,6 @@ #include -#include "os/log.h" #include "smp_int.h" #include "types/hci_role.h" diff --git a/system/stack/smp/smp_main.cc b/system/stack/smp/smp_main.cc index faaa2567cb1..ead1d83028f 100644 --- a/system/stack/smp/smp_main.cc +++ b/system/stack/smp/smp_main.cc @@ -20,7 +20,6 @@ #include -#include "os/log.h" #include "smp_int.h" #include "stack/include/btm_log_history.h" diff --git a/system/stack/srvc/srvc_dis.cc b/system/stack/srvc/srvc_dis.cc index 58f6befd11e..06cd12336cc 100644 --- a/system/stack/srvc/srvc_dis.cc +++ b/system/stack/srvc/srvc_dis.cc @@ -23,7 +23,6 @@ #include "gatt_api.h" #include "hardware/bt_gatt_types.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "srvc_dis_int.h" diff --git a/system/stack/test/a2dp/a2dp_sbc_unittest.cc b/system/stack/test/a2dp/a2dp_sbc_unittest.cc index 950a6100ddc..cde2795cfc7 100644 --- a/system/stack/test/a2dp/a2dp_sbc_unittest.cc +++ b/system/stack/test/a2dp/a2dp_sbc_unittest.cc @@ -24,7 +24,6 @@ #include #include "common/time_util.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "stack/include/a2dp_sbc_decoder.h" #include "stack/include/a2dp_sbc_encoder.h" diff --git a/system/stack/test/a2dp/wav_reader.cc b/system/stack/test/a2dp/wav_reader.cc index 0dddd30e9fa..b692f17014b 100644 --- a/system/stack/test/a2dp/wav_reader.cc +++ b/system/stack/test/a2dp/wav_reader.cc @@ -22,7 +22,6 @@ #include #include "os/files.h" -#include "os/log.h" namespace bluetooth { namespace testing { diff --git a/system/test/common/jni_thread.cc b/system/test/common/jni_thread.cc index 984b2337c15..db1520d36b7 100644 --- a/system/test/common/jni_thread.cc +++ b/system/test/common/jni_thread.cc @@ -21,8 +21,6 @@ #include -#include "os/log.h" - // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/test/common/main_handler.cc b/system/test/common/main_handler.cc index 8728ab1cd8b..c6e792c4dcc 100644 --- a/system/test/common/main_handler.cc +++ b/system/test/common/main_handler.cc @@ -27,7 +27,6 @@ #include "common/message_loop_thread.h" #include "common/postable_context.h" #include "include/hardware/bluetooth.h" -#include "os/log.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/test/headless/adapter/adapter.cc b/system/test/headless/adapter/adapter.cc index bbb3231047f..cdf430d459f 100644 --- a/system/test/headless/adapter/adapter.cc +++ b/system/test/headless/adapter/adapter.cc @@ -20,7 +20,6 @@ #include -#include "gd/os/log.h" #include "test/headless/headless.h" #include "test/headless/interface.h" #include "test/headless/log.h" diff --git a/system/test/headless/discovery/discovery.cc b/system/test/headless/discovery/discovery.cc index 5244eb893af..34c295188be 100644 --- a/system/test/headless/discovery/discovery.cc +++ b/system/test/headless/discovery/discovery.cc @@ -21,7 +21,6 @@ #include #include "btif/include/btif_api.h" -#include "os/log.h" // android log only #include "stack/include/sdp_api.h" #include "test/headless/bt_property.h" #include "test/headless/get_options.h" diff --git a/system/test/headless/get_options.cc b/system/test/headless/get_options.cc index 3ad9fd48e51..fcab08d45dc 100644 --- a/system/test/headless/get_options.cc +++ b/system/test/headless/get_options.cc @@ -23,7 +23,6 @@ #include #include -#include "os/log.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc index ebfcb041ecd..5f0d820c7ac 100644 --- a/system/test/headless/headless.cc +++ b/system/test/headless/headless.cc @@ -25,7 +25,6 @@ #include #include -#include "gd/os/log.h" #include "include/hardware/bluetooth.h" #include "test/headless/bt_stack_info.h" #include "test/headless/interface.h" diff --git a/system/test/headless/interface.h b/system/test/headless/interface.h index f06df13a4c9..11c314c8b70 100644 --- a/system/test/headless/interface.h +++ b/system/test/headless/interface.h @@ -21,7 +21,6 @@ #include #include -#include "gd/os/log.h" #include "include/hardware/bluetooth.h" #include "macros.h" #include "test/headless/log.h" diff --git a/system/test/headless/log.cc b/system/test/headless/log.cc index 4714b98c2d1..729db464759 100644 --- a/system/test/headless/log.cc +++ b/system/test/headless/log.cc @@ -14,8 +14,6 @@ * limitations under the License. */ -#include "os/log.h" - #include #include #include diff --git a/system/test/headless/main.cc b/system/test/headless/main.cc index feba9c19091..313b0f1e711 100644 --- a/system/test/headless/main.cc +++ b/system/test/headless/main.cc @@ -25,7 +25,6 @@ #include #include -#include "os/log.h" // android log only #include "test/headless/adapter/adapter.h" #include "test/headless/connect/connect.h" #include "test/headless/discovery/discovery.h" diff --git a/system/test/headless/nop/nop.cc b/system/test/headless/nop/nop.cc index fcae19aa258..53839536088 100644 --- a/system/test/headless/nop/nop.cc +++ b/system/test/headless/nop/nop.cc @@ -20,7 +20,6 @@ #include -#include "os/log.h" // android log only #include "stack/include/sdp_api.h" #include "test/headless/get_options.h" #include "test/headless/headless.h" diff --git a/system/test/headless/property.cc b/system/test/headless/property.cc index 65373f82f92..fe6e21f1ed1 100644 --- a/system/test/headless/property.cc +++ b/system/test/headless/property.cc @@ -20,7 +20,6 @@ #include -#include "gd/os/log.h" #include "include/hardware/bluetooth.h" #include "test/headless/log.h" diff --git a/system/test/headless/read/read.cc b/system/test/headless/read/read.cc index 08cf26d8fdd..51e29448ac0 100644 --- a/system/test/headless/read/read.cc +++ b/system/test/headless/read/read.cc @@ -18,7 +18,6 @@ #include "test/headless/read/read.h" -#include "os/log.h" // android log only #include "test/headless/get_options.h" #include "test/headless/headless.h" #include "test/headless/read/name.h" diff --git a/system/test/headless/scan/scan.cc b/system/test/headless/scan/scan.cc index d72b52236af..58c7bc9bcfb 100644 --- a/system/test/headless/scan/scan.cc +++ b/system/test/headless/scan/scan.cc @@ -20,7 +20,6 @@ #include -#include "os/log.h" #include "test/headless/get_options.h" #include "test/headless/headless.h" #include "test/headless/interface.h" diff --git a/system/test/headless/text.cc b/system/test/headless/text.cc index dc9303b982a..fefc47780db 100644 --- a/system/test/headless/text.cc +++ b/system/test/headless/text.cc @@ -22,7 +22,6 @@ #include "include/hardware/bluetooth.h" #include "macros.h" -#include "os/log.h" std::string bt_conn_direction_text(const bt_conn_direction_t& direction) { switch (direction) { diff --git a/system/test/mock/mock_bta_av_api.h b/system/test/mock/mock_bta_av_api.h index f6319691c0a..31fd804f672 100644 --- a/system/test/mock/mock_bta_av_api.h +++ b/system/test/mock/mock_bta_av_api.h @@ -33,7 +33,6 @@ // may need attention to prune from (or add to ) the inclusion set. #include "bta/av/bta_av_int.h" #include "btif/include/btif_av.h" -#include "os/log.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" #include "stack/include/bt_hdr.h" diff --git a/system/udrv/ulinux/uipc.cc b/system/udrv/ulinux/uipc.cc index 464e02b7f13..d0d7de0fbb6 100644 --- a/system/udrv/ulinux/uipc.cc +++ b/system/udrv/ulinux/uipc.cc @@ -44,7 +44,6 @@ #include #include -#include "os/log.h" #include "osi/include/osi.h" #include "osi/include/socket_utils/sockets.h" -- GitLab From f2133c577e178ccc0fb306bcb0bdc6dbe139d7da Mon Sep 17 00:00:00 2001 From: Gowtham Anandha Babu Date: Fri, 4 Oct 2024 14:28:56 +0530 Subject: [PATCH 359/875] Fix a2dp state machine java crash Multiple threads trying to execute the a2dp state machine block, where the message is sent even before starting the state machine, resulting in FATAL exception on com.android.bluetooth. Make the Device State Machine Map synchronized to avoid multiple threads accessing the same resource at a time. Gaurding mDeviceStateMap with itself to resolve this synchronization issue. Bug: 373331233 Flag: EXEMPT, minor bugfix Test: m com.android.btservices Change-Id: I5adf470dd623fd674f11526b0f692b9ef1f2cf8a Signed-off-by: Gowtham Anandha Babu --- .../bluetooth/a2dpsink/A2dpSinkService.java | 71 ++++++++++++------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java index 7e03b2c4bc2..b94a76001e5 100644 --- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java +++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java @@ -51,6 +51,8 @@ import java.util.concurrent.ConcurrentHashMap; public class A2dpSinkService extends ProfileService { private static final String TAG = A2dpSinkService.class.getSimpleName(); + // This is also used as a lock for shared data in {@link A2dpSinkService} + @GuardedBy("mDeviceStateMap") private final Map mDeviceStateMap = new ConcurrentHashMap<>(1); @@ -116,10 +118,12 @@ public class A2dpSinkService extends ProfileService { public void stop() { setA2dpSinkService(null); mNativeInterface.cleanup(); - for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) { - stateMachine.quitNow(); + synchronized (mDeviceStateMap) { + for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) { + stateMachine.quitNow(); + } + mDeviceStateMap.clear(); } - mDeviceStateMap.clear(); synchronized (mStreamHandlerLock) { if (mA2dpSinkStreamHandler != null) { mA2dpSinkStreamHandler.cleanup(); @@ -362,7 +366,10 @@ public class A2dpSinkService extends ProfileService { throw new IllegalArgumentException("Null device"); } - A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device); + A2dpSinkStateMachine stateMachine; + synchronized (mDeviceStateMap) { + stateMachine = mDeviceStateMap.get(device); + } // a state machine instance doesn't exist. maybe it is already gone? if (stateMachine == null) { return false; @@ -389,7 +396,9 @@ public class A2dpSinkService extends ProfileService { if (stateMachine == null) { return; } - mDeviceStateMap.remove(stateMachine.getDevice()); + synchronized (mDeviceStateMap) { + mDeviceStateMap.remove(stateMachine.getDevice()); + } stateMachine.quitNow(); } @@ -400,21 +409,25 @@ public class A2dpSinkService extends ProfileService { protected A2dpSinkStateMachine getOrCreateStateMachine(BluetoothDevice device) { A2dpSinkStateMachine newStateMachine = new A2dpSinkStateMachine(mLooper, device, this, mNativeInterface); - A2dpSinkStateMachine existingStateMachine = - mDeviceStateMap.putIfAbsent(device, newStateMachine); - // Given null is not a valid value in our map, ConcurrentHashMap will return null if the - // key was absent and our new value was added. We should then start and return it. Else - // we quit the new one so we don't leak a thread - if (existingStateMachine == null) { - newStateMachine.start(); - return newStateMachine; - } - return existingStateMachine; + synchronized (mDeviceStateMap) { + A2dpSinkStateMachine existingStateMachine = + mDeviceStateMap.putIfAbsent(device, newStateMachine); + // Given null is not a valid value in our map, ConcurrentHashMap will return null if the + // key was absent and our new value was added. We should then start and return it. Else + // we quit the new one so we don't leak a thread + if (existingStateMachine == null) { + newStateMachine.start(); + return newStateMachine; + } + return existingStateMachine; + } } @VisibleForTesting protected A2dpSinkStateMachine getStateMachineForDevice(BluetoothDevice device) { - return mDeviceStateMap.get(device); + synchronized (mDeviceStateMap) { + return mDeviceStateMap.get(device); + } } List getDevicesMatchingConnectionStates(int[] states) { @@ -451,10 +464,13 @@ public class A2dpSinkService extends ProfileService { */ public int getConnectionState(BluetoothDevice device) { if (device == null) return BluetoothProfile.STATE_DISCONNECTED; - A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device); + A2dpSinkStateMachine stateMachine; + synchronized (mDeviceStateMap) { + stateMachine = mDeviceStateMap.get(device); + } return (stateMachine == null) - ? BluetoothProfile.STATE_DISCONNECTED - : stateMachine.getState(); + ? BluetoothProfile.STATE_DISCONNECTED + : stateMachine.getState(); } /** @@ -501,17 +517,22 @@ public class A2dpSinkService extends ProfileService { super.dump(sb); ProfileService.println(sb, "Active Device = " + getActiveDevice()); ProfileService.println(sb, "Max Connected Devices = " + mMaxConnectedAudioDevices); - ProfileService.println(sb, "Devices Tracked = " + mDeviceStateMap.size()); - for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) { - ProfileService.println( - sb, "==== StateMachine for " + stateMachine.getDevice() + " ===="); - stateMachine.dump(sb); + synchronized (mDeviceStateMap) { + ProfileService.println(sb, "Devices Tracked = " + mDeviceStateMap.size()); + for (A2dpSinkStateMachine stateMachine : mDeviceStateMap.values()) { + ProfileService.println( + sb, "==== StateMachine for " + stateMachine.getDevice() + " ===="); + stateMachine.dump(sb); + } } } BluetoothAudioConfig getAudioConfig(BluetoothDevice device) { if (device == null) return null; - A2dpSinkStateMachine stateMachine = mDeviceStateMap.get(device); + A2dpSinkStateMachine stateMachine; + synchronized (mDeviceStateMap) { + stateMachine = mDeviceStateMap.get(device); + } // a state machine instance doesn't exist. maybe it is already gone? if (stateMachine == null) { return null; -- GitLab From 819eb2abb7330b64a4d3962b8b4044a80f3a3dfb Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Tue, 15 Oct 2024 00:48:23 +0000 Subject: [PATCH 360/875] [le audio] Remove external source without local metadata When a newly connected device has an existing source, the assistant doesn't have current metadata and it can't remove this source from remotes. Assistant should also be able to remove the source without metadata. Also this CL fixed one test error with bad code. Flag: EXEMPT, trivial change covered by unit tests Bug: 330690784 Test: atest BassClientServiceTest BassClientStateMachineTest Test: manually test with newly connected device Change-Id: I99bcffbf3868c21e52365862ceaf9de98538f956 --- .../bass_client/BassClientService.java | 12 +++-- .../bass_client/BassClientStateMachine.java | 38 ++++++++------ .../bass_client/BassClientServiceTest.java | 51 ++++++++++++++++++ .../BassClientStateMachineTest.java | 52 ++++++++++++------- 4 files changed, 114 insertions(+), 39 deletions(-) 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 c58c652bb6c..8e51586a44f 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -3026,14 +3026,18 @@ public class BassClientService extends ProfileService { stopBigMonitoring(metaData.getBroadcastId(), true); } - if (metaData != null && stateMachine.isSyncedToTheSource(sourceId)) { + if (stateMachine.isSyncedToTheSource(sourceId)) { sEventLogger.logd( TAG, "Remove Broadcast Source(Force lost PA sync): " + ("device: " + device) + (", sourceId: " + sourceId) - + (", broadcastId: " + metaData.getBroadcastId()) - + (", broadcastName: " + metaData.getBroadcastName())); + + (", broadcastId: " + + ((metaData == null) + ? BassConstants.INVALID_BROADCAST_ID + : metaData.getBroadcastId())) + + (", broadcastName: " + + ((metaData == null) ? "" : metaData.getBroadcastName()))); log("Force source to lost PA sync"); Message message = @@ -3041,9 +3045,9 @@ public class BassClientService extends ProfileService { message.arg1 = sourceId; message.arg2 = BassConstants.PA_SYNC_DO_NOT_SYNC; /* Pending remove set. Remove source once not synchronized to PA */ + /* MetaData can be null if source is from remote's receive state */ message.obj = metaData; stateMachine.sendMessage(message); - continue; } diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index 333d8532d5b..9bad2f6457f 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -1879,7 +1879,7 @@ public class BassClientStateMachine extends StateMachine { return res; } - private byte[] convertBroadcastMetadataToUpdateSourceByteArray( + private byte[] convertToUpdateSourceByteArray( int sourceId, BluetoothLeBroadcastMetadata metaData, int paSync) { BluetoothLeBroadcastReceiveState existingState = getBroadcastReceiveStateForSourceId(sourceId); @@ -1887,8 +1887,10 @@ public class BassClientStateMachine extends StateMachine { log("no existing SI for update source op"); return null; } - List subGroups = metaData.getSubgroups(); - byte numSubGroups = (byte) subGroups.size(); + int numSubGroups = + (metaData != null) + ? metaData.getSubgroups().size() + : existingState.getNumSubgroups(); byte[] res = new byte[UPDATE_SOURCE_FIXED_LENGTH + numSubGroups * 5]; int offset = 0; // Opcode @@ -1908,23 +1910,22 @@ public class BassClientStateMachine extends StateMachine { res[offset++] = (byte) 0xFF; res[offset++] = (byte) 0xFF; // Num_Subgroups - res[offset++] = numSubGroups; + res[offset++] = (byte) numSubGroups; - for (BluetoothLeBroadcastSubgroup subGroup : subGroups) { - int bisIndexValue; + for (int i = 0; i < numSubGroups; i++) { + int bisIndexValue = existingState.getBisSyncState().get(i).intValue(); if (paSync == BassConstants.PA_SYNC_DO_NOT_SYNC) { bisIndexValue = 0; - } else if (paSync == BassConstants.PA_SYNC_PAST_AVAILABLE - || paSync == BassConstants.PA_SYNC_PAST_NOT_AVAILABLE) { - bisIndexValue = getBisSyncFromChannelPreference(subGroup.getChannels()); - + } else if (metaData != null + && (paSync == BassConstants.PA_SYNC_PAST_AVAILABLE + || paSync == BassConstants.PA_SYNC_PAST_NOT_AVAILABLE)) { + bisIndexValue = + getBisSyncFromChannelPreference( + metaData.getSubgroups().get(i).getChannels()); // Let sink decide to which BIS sync if there is no channel preference if (bisIndexValue == 0) { bisIndexValue = 0xFFFFFFFF; } - } else { - bisIndexValue = - existingState.getBisSyncState().get(subGroups.indexOf(subGroup)).intValue(); } log("UPDATE_BCAST_SOURCE: bisIndexValue : " + bisIndexValue); // BIS_Sync @@ -2239,9 +2240,9 @@ public class BassClientStateMachine extends StateMachine { int sourceId = message.arg1; int paSync = message.arg2; log("Updating Broadcast source: " + metaData); + // Convert the source from either metadata or remote receive state byte[] updateSourceInfo = - convertBroadcastMetadataToUpdateSourceByteArray( - sourceId, metaData, paSync); + convertToUpdateSourceByteArray(sourceId, metaData, paSync); if (updateSourceInfo == null) { Log.e(TAG, "update source: source Info is NULL"); break; @@ -2253,7 +2254,9 @@ public class BassClientStateMachine extends StateMachine { if (paSync == BassConstants.PA_SYNC_DO_NOT_SYNC) { setPendingRemove(sourceId, true); } - if (metaData.isEncrypted() && (metaData.getBroadcastCode() != null)) { + if (metaData != null + && metaData.isEncrypted() + && metaData.getBroadcastCode() != null) { mSetBroadcastCodePending = true; } mPendingMetadata = metaData; @@ -2262,9 +2265,10 @@ public class BassClientStateMachine extends StateMachine { GATT_TXN_TIMEOUT, UPDATE_BCAST_SOURCE, BassConstants.GATT_TXN_TIMEOUT_MS); + // convertToUpdateSourceByteArray ensures receive state valid for sourceId sendMessageDelayed( CANCEL_PENDING_SOURCE_OPERATION, - metaData.getBroadcastId(), + getBroadcastReceiveStateForSourceId(sourceId).getBroadcastId(), BassConstants.SOURCE_OPERATION_TIMEOUT_MS); } else { Log.e(TAG, "UPDATE_BCAST_SOURCE: no Bluetooth Gatt handle, Fatal"); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 246677b6ed1..4d3060a289a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -1868,6 +1868,57 @@ public class BassClientServiceTest { } } + /** + * Test whether service.removeSource() does send modify source if source is from remote receive + * state. In this case, assistant should be able to remove source which was not managed by BASS + * service (external manager/no source metadata) + */ + @Test + public void testRemoveSourceForGroupAndTriggerModifySourceWithoutMetadata() { + prepareConnectedDeviceGroup(); + startSearchingForSources(); + onScanResult(mSourceDevice, TEST_BROADCAST_ID); + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); + + for (BassClientStateMachine sm : mStateMachines.values()) { + injectRemoteSourceStateSourceAdded( + sm, + meta, + TEST_SOURCE_ID, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null); + // no current broadcast metadata for external broadcast source + doReturn(null).when(sm).getCurrentBroadcastMetadata(eq(TEST_SOURCE_ID)); + doReturn(true).when(sm).isSyncedToTheSource(eq(TEST_SOURCE_ID)); + } + + for (BassClientStateMachine sm : mStateMachines.values()) { + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); + mBassClientService.removeSource(sm.getDevice(), TEST_SOURCE_ID); + // Verify device get update source + verify(sm, atLeast(1)).sendMessage(messageCaptor.capture()); + + Optional msg = + messageCaptor.getAllValues().stream() + .filter(m -> m.what == BassClientStateMachine.UPDATE_BCAST_SOURCE) + .findFirst(); + assertThat(msg.isPresent()).isEqualTo(true); + + assertThat(msg.get().arg1).isEqualTo(TEST_SOURCE_ID); + assertThat(msg.get().arg2).isEqualTo(BassConstants.PA_SYNC_DO_NOT_SYNC); + // Verify metadata is null + assertThat(msg.get().obj).isEqualTo(null); + } + + for (BassClientStateMachine sm : mStateMachines.values()) { + injectRemoteSourceStateRemoval(sm, TEST_SOURCE_ID); + } + } + /** Test whether the group operation flag is set on addSource() and removed on removeSource */ @Test public void testGroupStickyFlagSetUnset() { diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index 70b50063dd8..8e8bfb01c03 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -1585,23 +1585,6 @@ public class BassClientStateMachineTest { 0x00, // broadcastIdBytes (byte) BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, (byte) BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_CODE_REQUIRED, - // 16 bytes badBroadcastCode - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, 0x01, // numSubGroups // SubGroup #1 0x00, @@ -2409,7 +2392,7 @@ public class BassClientStateMachineTest { Utils.getByteAddress(mSourceTestDevice)[1], Utils.getByteAddress(mSourceTestDevice)[0], // sourceAddress 0x00, // sourceAdvSid - 0x00, + (byte) (TEST_BROADCAST_ID & 0xFF), 0x00, 0x00, // broadcastIdBytes (byte) paSync, @@ -2652,6 +2635,39 @@ public class BassClientStateMachineTest { verify(callbacks).notifyBassStateReady(eq(mTestDevice)); } + @Test + public void updateBroadcastSource_withoutMetadata() { + int sourceId = 1; + int paSync = BassConstants.PA_SYNC_DO_NOT_SYNC; + + prepareInitialReceiveStateForGatt(); + + generateBroadcastReceiveStatesAndVerify( + mSourceTestDevice, + TEST_SOURCE_ID, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING, + 0x1L); + + BassClientStateMachine.BluetoothGattTestableWrapper btGatt = + Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class); + mBassClientStateMachine.mBluetoothGatt = btGatt; + BluetoothGattCharacteristic scanControlPoint = + Mockito.mock(BluetoothGattCharacteristic.class); + mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; + + mBassClientStateMachine.mPendingOperation = 0; + mBassClientStateMachine.mPendingSourceId = 0; + mBassClientStateMachine.mPendingMetadata = null; + + // update source without metadata + sendMessageAndVerifyTransition( + mBassClientStateMachine.obtainMessage(UPDATE_BCAST_SOURCE, sourceId, paSync, null), + BassClientStateMachine.ConnectedProcessing.class); + assertThat(mBassClientStateMachine.mPendingOperation).isEqualTo(UPDATE_BCAST_SOURCE); + assertThat(mBassClientStateMachine.mPendingSourceId).isEqualTo(sourceId); + } + private void initToConnectingState() { allowConnection(true); allowConnectGatt(true); -- GitLab From cd3fd0c79988ec98aff5ee012c4438b57545d047 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Thu, 17 Oct 2024 14:04:30 -0700 Subject: [PATCH 361/875] Initialize member variables to avoid using uninitialized values Bug: 350102910 Bug: 353978074 Test: atest --host bluetooth_le_audio_client_test:GmapClientTest Flag: com.android.bluetooth.flags.leaudio_gmap_client Change-Id: I4e8dc89718b0b2fd126a6235a08305dac377de32 --- system/bta/le_audio/gmap_client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/bta/le_audio/gmap_client.h b/system/bta/le_audio/gmap_client.h index b1167b5bcd4..c1e8c320ca7 100644 --- a/system/bta/le_audio/gmap_client.h +++ b/system/bta/le_audio/gmap_client.h @@ -34,7 +34,7 @@ public: static void UpdateGmapOffloaderSupport(bool value); - GmapClient(const RawAddress& addr) : addr_(addr) {} + GmapClient(const RawAddress& addr) : role_handle_(0), UGT_feature_handle_(0), addr_(addr) {} bool parseAndSaveGmapRole(uint16_t len, const uint8_t* value); -- GitLab From 690e731348f779524d91957693b5ef3e4a12f68e Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Fri, 18 Oct 2024 11:34:00 +0800 Subject: [PATCH 362/875] floss: SCO: Avoid use after free The unique_ptr sco_uipc could be overwritten without calling UIPC_Close, this could leave the UIPC thread alive and access the UIPC structure while is already freed. Bug: 373228946 Tag: #floss Test: mmm packages/modules/Bluetooth Test: bluetooth_AdapterAUHealth.all_floss Flag: EXEMPT, Floss-only change Change-Id: I085e70db774310118b9b7a2e9a4325c41ed71900 --- system/stack/btm/btm_sco_hci.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/system/stack/btm/btm_sco_hci.cc b/system/stack/btm/btm_sco_hci.cc index a7f5e152ace..81fadb5cdc4 100644 --- a/system/stack/btm/btm_sco_hci.cc +++ b/system/stack/btm/btm_sco_hci.cc @@ -99,6 +99,7 @@ namespace sco { void open() { if (sco_uipc != nullptr) { log::warn("Re-opening UIPC that is already running"); + cleanup(); } sco_uipc = UIPC_Init(); -- GitLab From bd308ffbf9191bbd959426fab535030f60934c45 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Wed, 16 Oct 2024 04:12:38 +0000 Subject: [PATCH 363/875] Ensure UpdateNotificationThread being terminated There are cases where the NotificationUpdateThread continues running after a test finishes. This can interfere with susequent tests and potentially cause failures. Ensure the thread is terminated to prevent these issuse. Flag: EXEMPT, test change Bug: 369936658 Test: atest BluetoothOppServiceCleanupTest BluetoothOppServiceTest --iterations 100 Change-Id: Iaddd50df409c335019213de3b21d741808e4d2ec --- .../bluetooth/opp/BluetoothOppNotification.java | 2 +- .../android/bluetooth/opp/BluetoothOppService.java | 2 +- .../bluetooth/opp/BluetoothOppServiceCleanupTest.java | 11 +++++++++-- .../bluetooth/opp/BluetoothOppServiceTest.java | 4 ++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java index 87145b17d06..8cbd32cfba8 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java @@ -141,7 +141,7 @@ class BluetoothOppNotification { private final HashMap mNotifications = new HashMap<>(); - private NotificationUpdateThread mUpdateNotificationThread; + @VisibleForTesting NotificationUpdateThread mUpdateNotificationThread; private int mPendingUpdate = 0; diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java index 559654de4fa..a8c653db5ce 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java @@ -135,7 +135,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti private BluetoothShareContentObserver mObserver; /** Class to handle Notification Manager updates */ - private BluetoothOppNotification mNotifier; + @VisibleForTesting BluetoothOppNotification mNotifier; private boolean mPendingUpdate; diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java index d2db49fbc50..2183c193470 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java @@ -46,7 +46,7 @@ public class BluetoothOppServiceCleanupTest { @Test @UiThreadTest - public void testStopAndCleanup() { + public void testStopAndCleanup() throws Exception { AdapterService adapterService = new AdapterService(mTargetContext); // Don't need to disable again since it will be handled in OppService.stop @@ -58,8 +58,9 @@ public class BluetoothOppServiceCleanupTest { mTargetContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values); } + BluetoothOppService service = null; try { - BluetoothOppService service = new BluetoothOppService(adapterService); + service = new BluetoothOppService(adapterService); service.start(); service.setAvailable(true); @@ -67,6 +68,12 @@ public class BluetoothOppServiceCleanupTest { service.stop(); service.cleanup(); } finally { + if (service != null) { + Thread updateNotificationThread = service.mNotifier.mUpdateNotificationThread; + if (updateNotificationThread != null) { + updateNotificationThread.join(); + } + } mTargetContext.getContentResolver().delete(BluetoothShare.CONTENT_URI, null, null); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java index 22affe39cf2..4b5bd234652 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java @@ -107,6 +107,10 @@ public class BluetoothOppServiceTest { BluetoothOppService service = mService; if (service != null) { service.mUpdateThread = null; + Thread updateNotificationThread = service.mNotifier.mUpdateNotificationThread; + if (updateNotificationThread != null) { + updateNotificationThread.join(); + } } BluetoothMethodProxy.setInstanceForTesting(null); -- GitLab From f8220c540fbf2f37b94430044d80546f5db48e16 Mon Sep 17 00:00:00 2001 From: Zhengping Jiang Date: Wed, 25 Sep 2024 15:13:43 -0700 Subject: [PATCH 364/875] bluetooth: acquire wakelock when connection is complete Acquire a wakelock when receving a connection request during system suspend. Wait for a timeout to release the wakelock, so the bluetooth device has time to send input events and wake up the system. If bluetooth resumes first, also release the wakelock. The timeout is defined with sysprop. If the timeout is zero, the request for wakelock is ignored. Bug: 369686962 Bug: 366432079 Test: m -j, suspend system and wake up with mouse Flag: adapter_suspend_mgmt Change-Id: Ia6aab33857d4d7a2ddc7c5ff8e182ab42cb77825 --- system/btif/src/stack_manager.cc | 3 +- system/main/Android.bp | 1 + system/main/shim/acl.cc | 73 ++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc index e3e4f3ba0b6..93407fc08ca 100644 --- a/system/btif/src/stack_manager.cc +++ b/system/btif/src/stack_manager.cc @@ -430,10 +430,11 @@ static void event_clean_up_stack(std::promise promise, ProfileStopCallback module_clean_up(get_local_module(BTIF_CONFIG_MODULE)); module_clean_up(get_local_module(DEVICE_IOT_CONFIG_MODULE)); - module_clean_up(get_local_module(OSI_MODULE)); info("Gd shim module disabled"); module_shut_down(get_local_module(GD_SHIM_MODULE)); + module_clean_up(get_local_module(OSI_MODULE)); + main_thread_shut_down(); module_management_stop(); diff --git a/system/main/Android.bp b/system/main/Android.bp index 629735a233e..454dd794008 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -166,6 +166,7 @@ cc_test { ":BluetoothOsSources_host", ":TestCommonMainHandler", ":TestCommonMockFunctions", + ":TestFakeOsi", ":TestMockBta", ":TestMockBtif", ":TestMockBtu", diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc index 7f33da446fa..3321bd7a836 100644 --- a/system/main/shim/acl.cc +++ b/system/main/shim/acl.cc @@ -57,7 +57,10 @@ #include "main/shim/stack.h" #include "metrics/bluetooth_event.h" #include "os/handler.h" +#include "os/wakelock_manager.h" +#include "osi/include/alarm.h" #include "osi/include/allocator.h" +#include "osi/include/properties.h" #include "stack/acl/acl.h" #include "stack/btm/btm_int_types.h" #include "stack/include/bt_hdr.h" @@ -72,6 +75,7 @@ extern tBTM_CB btm_cb; using namespace bluetooth; +using ::bluetooth::os::WakelockManager; class ConnectAddressWithType : public bluetooth::common::IRedactableLoggable { public: @@ -132,6 +136,51 @@ struct formatter : formatter { namespace { +static void wakelock_release_cb(void*) { + log::debug("Wakelock released on timeout"); + WakelockManager::Get().Release(); +} + +struct timed_wakelock { + timed_wakelock() { timer_ = alarm_new("bluetooth_wakelock_timer"); } + ~timed_wakelock() { + if (alarm_is_scheduled(timer_)) { + log::debug("Wakelock released"); + WakelockManager::Get().Release(); + } + alarm_free(timer_); + } + + // Acquire wakelock for a fixed time. + // Acquiring again resets the timer. Wakelock is released after the time. + void acquire(uint64_t timeout_ms) { + // Ignore request if timeout is 0. + if (timeout_ms == 0) { + return; + } + if (!alarm_is_scheduled(timer_)) { + log::debug("Wakelock acquired"); + WakelockManager::Get().Acquire(); + } else { + alarm_cancel(timer_); + } + log::debug("Alarm set for {} ms", timeout_ms); + alarm_set_on_mloop(timer_, timeout_ms, wakelock_release_cb, nullptr); + } + + // Cancel timer and release wakelock. + void release() { + if (alarm_is_scheduled(timer_)) { + log::debug("Wakelock released early. Time left: {} ms", alarm_get_remaining_ms(timer_)); + alarm_cancel(timer_); + WakelockManager::Get().Release(); + } + } + +private: + alarm_t* timer_ = nullptr; // wakelock state is given by alarm_is_scheduled +}; // timed_wakelock + constexpr uint32_t kRunicBjarkan = 0x0016D2; constexpr uint32_t kRunicHagall = 0x0016BC; @@ -142,6 +191,7 @@ using CreationTime = std::chrono::time_point; using TeardownTime = std::chrono::time_point; constexpr char kBtmLogTag[] = "ACL"; +constexpr char kWakelockTimeoutMsSysprop[] = "bluetooth.core.acl.wakelock_timeout"; using SendDataUpwards = void (*const)(BT_HDR*); using OnDisconnect = std::function; @@ -834,6 +884,9 @@ struct shim::Acl::impl { ShadowAcceptlist shadow_acceptlist_; ShadowAddressResolutionList shadow_address_resolution_list_; + struct timed_wakelock wakeup_wakelock_; + bool system_suspend_ = false; + bool IsClassicAcl(HciHandle handle) { return handle_to_classic_connection_map_.find(handle) != handle_to_classic_connection_map_.end(); @@ -1465,6 +1518,13 @@ void shim::Acl::OnConnectRequest(hci::Address address, hci::ClassOfDevice cod) { const RawAddress bd_addr = ToRawAddress(address); const DEV_CLASS dev_class = ToDevClass(cod); + if (com::android::bluetooth::flags::adapter_suspend_mgmt()) { + if (pimpl_->system_suspend_) { + pimpl_->wakeup_wakelock_.acquire( + (uint64_t)osi_property_get_int32(kWakelockTimeoutMsSysprop, 0)); + } + } + TRY_POSTING_ON_MAIN(acl_interface_.connection.classic.on_connect_request, bd_addr, cod); log::debug("Received connect request remote:{} gd_cod:{} legacy_dev_class:{}", address, cod.ToString(), dev_class_text(dev_class)); @@ -1488,6 +1548,13 @@ void shim::Acl::OnLeConnectSuccess(hci::AddressWithType address_with_type, log::assert_that(connection != nullptr, "assert failed: connection != nullptr"); auto handle = connection->GetHandle(); + if (com::android::bluetooth::flags::adapter_suspend_mgmt()) { + if (pimpl_->system_suspend_) { + pimpl_->wakeup_wakelock_.acquire( + (uint64_t)osi_property_get_int32(kWakelockTimeoutMsSysprop, 0)); + } + } + // Save the peer address, if any hci::AddressWithType peer_address_with_type = connection->peer_address_with_type_; @@ -1684,5 +1751,11 @@ void shim::Acl::ClearAddressResolution() { } void shim::Acl::SetSystemSuspendState(bool suspended) { + if (com::android::bluetooth::flags::adapter_suspend_mgmt()) { + pimpl_->system_suspend_ = suspended; + if (!suspended) { + pimpl_->wakeup_wakelock_.release(); + } + } handler_->CallOn(pimpl_.get(), &Acl::impl::SetSystemSuspendState, suspended); } -- GitLab From ef6c5b5592d8efa988b4142e379827cbb055378e Mon Sep 17 00:00:00 2001 From: Yun-Hao Chung Date: Fri, 18 Oct 2024 07:40:23 +0000 Subject: [PATCH 365/875] Floss: Increase the manager timeout to 15 seconds If btmanagerd start timeout is shorter than stack start timeout, it is possible that the stack is still initializing but btmanagerd terminates the process because of timeout. This could also cause crash because no gurantee to the order of freeing memory. Bug: 374017641 Bug: 304997914 Tag: #floss Test: mmm packages/modules/Bluetooth Flag: EXEMPT, Floss-only changes Change-Id: I40daf5a05a81783ef381ceaa9c42db8e77f59a28 --- system/gd/rust/linux/mgmt/src/state_machine.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/gd/rust/linux/mgmt/src/state_machine.rs b/system/gd/rust/linux/mgmt/src/state_machine.rs index 679c9e4b4a5..2df9e7c16ce 100644 --- a/system/gd/rust/linux/mgmt/src/state_machine.rs +++ b/system/gd/rust/linux/mgmt/src/state_machine.rs @@ -174,8 +174,9 @@ pub struct StateMachineProxy { const TX_SEND_TIMEOUT_DURATION: Duration = Duration::from_secs(3); /// Duration to use for timeouts when starting/stopping adapters. -/// Some adapters take a while to load firmware so use a sufficiently long timeout here. -const COMMAND_TIMEOUT_DURATION: Duration = Duration::from_secs(7); +/// GD start timeout is set for 12 seconds. This timeout needs to be longer than that otherwise +/// Floss could crash. +const COMMAND_TIMEOUT_DURATION: Duration = Duration::from_secs(15); impl StateMachineProxy { pub fn start_bluetooth(&self, hci: VirtualHciIndex) { -- GitLab From 8cc34b9fe803eb6b837246a0a452c069dc9ebb95 Mon Sep 17 00:00:00 2001 From: Yun-Hao Chung Date: Fri, 18 Oct 2024 07:44:36 +0000 Subject: [PATCH 366/875] Floss: Don't disconnect unbonded HID when disconnected or disconnecting Don't disconnect the incoming HID connection from an unbonded device when the state is disconnected or disconnecting, otherwise we will disconnect it twice. Bug: 374242303 Tag: #floss Test: mmm packages/modules/Bluetooth Flag: EXEMPT, Floss-only changes Change-Id: Id2c6cab895e1ed9fea6d7f2e4cfdde224572ce3f --- system/gd/rust/linux/stack/src/bluetooth.rs | 5 ++++- system/gd/rust/topshim/src/profiles/hid_host.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index 57b12c63af4..3868212fc0f 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -3047,7 +3047,10 @@ impl BtifHHCallbacks for Bluetooth { state as u32, ); - if BtBondState::Bonded != self.get_bond_state_by_addr(&address) { + if BtBondState::Bonded != self.get_bond_state_by_addr(&address) + && (state != BthhConnectionState::Disconnecting + && state != BthhConnectionState::Disconnected) + { warn!( "[{}]: Rejecting a unbonded device's attempt to connect to HID/HOG profiles", DisplayAddress(&address) diff --git a/system/gd/rust/topshim/src/profiles/hid_host.rs b/system/gd/rust/topshim/src/profiles/hid_host.rs index 77434af058d..c4e04e70492 100644 --- a/system/gd/rust/topshim/src/profiles/hid_host.rs +++ b/system/gd/rust/topshim/src/profiles/hid_host.rs @@ -15,7 +15,7 @@ use topshim_macros::{cb_variant, profile_enabled_or}; use log::warn; -#[derive(Debug, FromPrimitive, PartialEq, PartialOrd)] +#[derive(Debug, FromPrimitive, PartialEq, PartialOrd, Copy, Clone)] #[repr(u32)] pub enum BthhConnectionState { Connected = 0, -- GitLab From 32ef60b9fe6f9b5b915a4c2de14f684f4ad2791b Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Fri, 18 Oct 2024 18:35:31 +0800 Subject: [PATCH 367/875] hh: Don't print unhandled event error on data output callback Even though we don't need to do anything after sending data output via ATT Write Command, we shouldn't print error as well. Bug: 373632219 Test: m -j Flag: EXEMPT, logging change Change-Id: Iae5df7e67e7cec8778bc0763466afe80f788a61a --- system/btif/src/btif_hh.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index 2de9feb1ed0..e01e2d8d75d 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -1283,6 +1283,9 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) { case BTA_HH_API_ERR_EVT: log::error("BTA_HH API_ERR"); break; + case BTA_HH_DATA_EVT: + // data output is sent - do nothing. + break; default: log::warn("Unhandled event: {}", event); break; -- GitLab From 0f4dffa48f1c4f5c7806b62ae85fdb13b0b5ed4f Mon Sep 17 00:00:00 2001 From: Sarvesh Kalwit Date: Thu, 3 Oct 2024 16:39:13 +0000 Subject: [PATCH 368/875] Implement MSFT extension logic in ScanManager Bug: 360387731 Bug: 360392001 Bug: 365787977 Flag: com.android.bluetooth.flags.le_scan_msft_support Test: atest BluetoothInstrumentationTests:ScanManagerTest Change-Id: I7ef0770537d126c1ec1012353317ba968d6c8a1b --- .../app/jni/com_android_bluetooth_gatt.cpp | 2 +- .../bluetooth/le_scan/ScanManager.java | 109 +++++++++++++++++- .../le_scan/ScanNativeInterface.java | 54 ++++++++- .../le_scan/TransitionalScanHelper.java | 45 ++++++++ .../bluetooth/le_scan/ScanManagerTest.java | 50 ++++++++ 5 files changed, 254 insertions(+), 6 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index 71325ee0c74..0264da919f1 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -2829,7 +2829,7 @@ static int register_com_android_bluetooth_gatt_scan(JNIEnv* env) { {"gattClientScanFilterEnableNative", "(IZ)V", (void*)gattClientScanFilterEnableNative}, {"gattSetScanParametersNative", "(IIII)V", (void*)gattSetScanParametersNative}, // MSFT HCI Extension functions. - {"gattClientIsMsftSupportedNative", "()Z", (void*)gattClientIsMsftSupportedNative}, + {"gattClientIsMsftSupportedNative", "()Z", (bool*)gattClientIsMsftSupportedNative}, {"gattClientMsftAdvMonitorAddNative", "(Lcom/android/bluetooth/le_scan/MsftAdvMonitor$Monitor;[Lcom/android/bluetooth/le_scan/" "MsftAdvMonitor$Pattern;Lcom/android/bluetooth/le_scan/MsftAdvMonitor$Address;I)V", 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 e513e185009..128490598d5 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java @@ -39,6 +39,7 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; +import android.os.SystemProperties; import android.provider.Settings; import android.util.Log; import android.util.SparseBooleanArray; @@ -1005,6 +1006,12 @@ public class ScanManager { // The logic is AND for each filter field. private static final int LIST_LOGIC_TYPE = 0x1111111; private static final int FILTER_LOGIC_TYPE = 1; + + // MSFT-based hardware scan offload sysprop + private static final String MSFT_HCI_EXT_ENABLED = "bluetooth.core.le.use_msft_hci_ext"; + // Hardcoded min number of hardware adv monitor slots for MSFT-enabled controllers + private static final int MIN_NUM_MSFT_MONITOR_SLOTS = 20; + // Filter indices that are available to user. It's sad we need to maintain filter index. private final Deque mFilterIndexStack; // Map of scannerId and Filter indices used by client. @@ -1020,6 +1027,11 @@ public class ScanManager { private final PendingIntent mBatchScanIntervalIntent; private final ScanNativeInterface mNativeInterface; + // Whether or not MSFT-based scanning hardware offload is available on this device + private final boolean mIsMsftSupported; + // Whether or not MSFT-based scanning is currently enabled in the controller + private boolean scanEnabledMsft = false; + ScanNative(TransitionalScanHelper scanHelper) { mNativeInterface = ScanObjectsFactory.getInstance().getScanNativeInterface(); mNativeInterface.init(scanHelper); @@ -1053,6 +1065,11 @@ public class ScanManager { } }); mContext.registerReceiver(mBatchAlarmReceiver.get(), filter); + + mIsMsftSupported = + Flags.leScanMsftSupport() + && SystemProperties.getBoolean(MSFT_HCI_EXT_ENABLED, false) + && mNativeInterface.gattClientIsMsftSupported(); } private void callbackDone(int scannerId, int status) { @@ -1147,14 +1164,17 @@ public class ScanManager { } void startRegularScan(ScanClient client) { - if (isFilteringSupported() + if ((isFilteringSupported() || mIsMsftSupported) && mFilterIndexStack.isEmpty() && mClientFilterIndexMap.isEmpty()) { initFilterIndexStack(); } if (isFilteringSupported()) { configureScanFilters(client); + } else if (mIsMsftSupported) { + addFiltersMsft(client); } + // Start scan native only for the first client. if (numRegularScanClients() == 1 && client.settings != null @@ -1402,7 +1422,12 @@ public class ScanManager { Log.w(TAG, "There is no scan radio to stop"); } } - removeScanFilters(client.scannerId); + + if (!mIsMsftSupported) { + removeScanFilters(client.scannerId); + } else { + removeFiltersMsft(client); + } } void regularScanTimeout(ScanClient client) { @@ -1692,6 +1717,11 @@ public class ScanManager { private void initFilterIndexStack() { int maxFiltersSupported = AdapterService.getAdapterService().getNumOfOffloadedScanFilterSupported(); + if (!isFilteringSupported() && mIsMsftSupported) { + // Hardcoded minimum number of hardware adv monitor slots, because this value + // cannot be queried from the controller for MSFT enabled devices + maxFiltersSupported = MIN_NUM_MSFT_MONITOR_SLOTS; + } // Start from index 4 as: // index 0 is reserved for ALL_PASS filter in Settings app. // index 1 is reserved for ALL_PASS filter for regular scan apps. @@ -1954,6 +1984,81 @@ public class ScanManager { private void unregisterScanner(int scannerId) { mNativeInterface.unregisterScanner(scannerId); } + + private void addFiltersMsft(ScanClient client) { + // Do not add any filters set by opportunistic scan clients + if (isOpportunisticScanClient(client)) { + return; + } + + if (client == null + || client.filters == null + || client.filters.isEmpty() + || client.filters.size() > mFilterIndexStack.size()) { + // Use all-pass filter + updateScanMsft(); + return; + } + + Deque clientFilterIndices = new ArrayDeque<>(); + for (ScanFilter filter : client.filters) { + int filterIndex = mFilterIndexStack.pop(); + MsftAdvMonitor monitor = new MsftAdvMonitor(filter); + + resetCountDownLatch(); + mNativeInterface.gattClientMsftAdvMonitorAdd( + monitor.getMonitor(), + monitor.getPatterns(), + monitor.getAddress(), + filterIndex); + waitForCallback(); + + clientFilterIndices.add(filterIndex); + } + mClientFilterIndexMap.put(client.scannerId, clientFilterIndices); + + updateScanMsft(); + } + + private void removeFiltersMsft(ScanClient client) { + Deque clientFilterIndices = mClientFilterIndexMap.remove(client.scannerId); + if (clientFilterIndices != null) { + mFilterIndexStack.addAll(clientFilterIndices); + for (int filterIndex : clientFilterIndices) { + resetCountDownLatch(); + mNativeInterface.gattClientMsftAdvMonitorRemove(filterIndex); + waitForCallback(); + } + } + + updateScanMsft(); + } + + private void updateScanMsft() { + boolean shouldEnableScanMsft = + !mRegularScanClients.stream() + .anyMatch( + c -> + c.settings != null + && c.settings.getScanMode() + != ScanSettings.SCAN_MODE_OPPORTUNISTIC + && !this.mClientFilterIndexMap.containsKey( + c.scannerId)); + if (scanEnabledMsft != shouldEnableScanMsft) { + resetCountDownLatch(); + mNativeInterface.gattClientMsftAdvMonitorEnable(shouldEnableScanMsft); + waitForCallback(); + scanEnabledMsft = shouldEnableScanMsft; + + // Restart scanning, since enabling/disabling may have changed + // the filter policy + Log.d(TAG, "Restarting MSFT scan"); + mNativeInterface.gattClientScan(false); + if (numRegularScanClients() > 0) { + mNativeInterface.gattClientScan(true); + } + } + } } @VisibleForTesting diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java index c2581a5cbea..9f0ebcc9790 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java @@ -182,6 +182,36 @@ public class ScanNativeInterface { gattClientScanFilterEnableNative(clientIf, enable); } + /** Check if MSFT HCI extension is supported */ + public boolean gattClientIsMsftSupported() { + return gattClientIsMsftSupportedNative(); + } + + /** Add a MSFT Advertisement Monitor */ + public void gattClientMsftAdvMonitorAdd( + MsftAdvMonitor.Monitor msft_adv_monitor, + MsftAdvMonitor.Pattern[] msft_adv_monitor_patterns, + MsftAdvMonitor.Address msft_adv_monitor_address, + int filter_index) { + gattClientMsftAdvMonitorAddNative( + msft_adv_monitor, + msft_adv_monitor_patterns, + msft_adv_monitor_address, + filter_index); + } + + /** Remove a MSFT Advertisement Monitor */ + public void gattClientMsftAdvMonitorRemove(int filter_index) { + int monitor_handle = mScanHelper.msftMonitorHandleFromFilterIndex(filter_index); + if (monitor_handle < 0) return; + gattClientMsftAdvMonitorRemoveNative(filter_index, monitor_handle); + } + + /** Enable a MSFT Advertisement Monitor */ + public void gattClientMsftAdvMonitorEnable(boolean enable) { + gattClientMsftAdvMonitorEnableNative(enable); + } + /** Configure BLE batch scan storage */ public void gattClientConfigBatchScanStorage( int clientIf, @@ -385,9 +415,27 @@ public class ScanNativeInterface { mScanHelper.onScanParamSetupCompleted(status, scannerId); } - void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) {} + void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) { + if (mScanHelper == null) { + Log.e(TAG, "Scan helper is null!"); + return; + } + mScanHelper.onMsftAdvMonitorAdd(filter_index, monitor_handle, status); + } - void onMsftAdvMonitorRemove(int filter_index, int status) {} + void onMsftAdvMonitorRemove(int filter_index, int status) { + if (mScanHelper == null) { + Log.e(TAG, "Scan helper is null!"); + return; + } + mScanHelper.onMsftAdvMonitorRemove(filter_index, status); + } - void onMsftAdvMonitorEnable(int status) {} + void onMsftAdvMonitorEnable(int status) { + if (mScanHelper == null) { + Log.e(TAG, "Scan helper is null!"); + return; + } + mScanHelper.onMsftAdvMonitorEnable(status); + } } diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java index b164b06693f..573b4f49d22 100644 --- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java +++ b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java @@ -67,6 +67,7 @@ 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.List; import java.util.Set; @@ -142,6 +143,7 @@ public class TransitionalScanHelper { private AdapterService mAdapterService; private ScannerMap mScannerMap = new ScannerMap(); + private HashMap mFilterIndexToMsftAdvMonitorMap = new HashMap<>(); private String mExposureNotificationPackage; public ScannerMap getScannerMap() { @@ -1048,6 +1050,49 @@ public class TransitionalScanHelper { } } + public int msftMonitorHandleFromFilterIndex(int filter_index) { + if (!mFilterIndexToMsftAdvMonitorMap.containsKey(filter_index)) { + Log.e(TAG, "Monitor with filter_index'" + filter_index + "' does not exist"); + return -1; + } + return mFilterIndexToMsftAdvMonitorMap.get(filter_index); + } + + public void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) { + if (status != 0) { + Log.e( + TAG, + "Error adding advertisement monitor with filter index '" + filter_index + "'"); + return; + } + if (mFilterIndexToMsftAdvMonitorMap.containsKey(filter_index)) { + Log.e(TAG, "Monitor with filter_index'" + filter_index + "' already added"); + return; + } + mFilterIndexToMsftAdvMonitorMap.put(filter_index, monitor_handle); + } + + public void onMsftAdvMonitorRemove(int filter_index, int status) { + if (status != 0) { + Log.e( + TAG, + "Error removing advertisement monitor with filter index '" + + filter_index + + "'"); + } + if (!mFilterIndexToMsftAdvMonitorMap.containsKey(filter_index)) { + Log.e(TAG, "Monitor with filter_index'" + filter_index + "' does not exist"); + return; + } + mFilterIndexToMsftAdvMonitorMap.remove(filter_index); + } + + public void onMsftAdvMonitorEnable(int status) { + if (status != 0) { + Log.e(TAG, "Error enabling advertisement monitor"); + } + } + /************************************************************************** * GATT Service functions - Shared CLIENT/SERVER *************************************************************************/ 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 ca9c0f87832..a6692a31942 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 @@ -36,6 +36,7 @@ import static com.android.bluetooth.le_scan.ScanManager.SCAN_MODE_SCREEN_OFF_LOW import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; @@ -63,6 +64,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.SystemProperties; import android.os.WorkSource; import android.os.test.TestLooper; import android.platform.test.annotations.EnableFlags; @@ -127,6 +129,9 @@ public class ScanManagerTest { private static final String TEST_APP_NAME = "Test"; private static final String TEST_PACKAGE_NAME = "com.test.package"; + // MSFT-based hardware scan offload sysprop + private static final String MSFT_HCI_EXT_ENABLED = "bluetooth.core.le.use_msft_hci_ext"; + private Context mTargetContext; private ScanManager mScanManager; private Handler mHandler; @@ -2142,4 +2147,49 @@ public class ScanManagerTest { .gattSetScanParameters(anyInt(), anyInt(), anyInt(), eq(expectedPhy)); } } + + @Test + @EnableFlags(Flags.FLAG_LE_SCAN_MSFT_SUPPORT) + public void testMsftScan() { + final boolean isFiltered = true; + final boolean isEmptyFilter = false; + + boolean isMsftEnabled = SystemProperties.getBoolean(MSFT_HCI_EXT_ENABLED, false); + SystemProperties.set(MSFT_HCI_EXT_ENABLED, Boolean.toString(true)); + try { + when(mScanNativeInterface.gattClientIsMsftSupported()).thenReturn(true); + when(mBluetoothAdapterProxy.isOffloadedScanFilteringSupported()).thenReturn(false); + + // Create new ScanManager since sysprop and MSFT support are only checked when + // ScanManager + // is created + mScanManager = + new ScanManager( + mMockGattService, + mMockScanHelper, + mAdapterService, + mBluetoothAdapterProxy, + mTestLooper.getLooper()); + mHandler = mScanManager.getClientHandler(); + assertThat(mHandler).isNotNull(); + + // Turn on screen + sendMessageWaitForProcessed(createScreenOnOffMessage(true)); + // Create scan client + ScanClient client = createScanClient(0, isFiltered, isEmptyFilter, SCAN_MODE_LOW_POWER); + // Start scan + sendMessageWaitForProcessed(createStartStopScanMessage(true, client)); + + // Verify MSFT APIs + verify(mScanNativeInterface, atLeastOnce()) + .gattClientMsftAdvMonitorAdd( + any(MsftAdvMonitor.Monitor.class), + any(MsftAdvMonitor.Pattern[].class), + any(MsftAdvMonitor.Address.class), + anyInt()); + verify(mScanNativeInterface, atLeastOnce()).gattClientMsftAdvMonitorEnable(eq(true)); + } finally { + SystemProperties.set(MSFT_HCI_EXT_ENABLED, Boolean.toString(isMsftEnabled)); + } + } } -- GitLab From 34019dd83de9627e97dfbfbc941478a8547abac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 18 Oct 2024 17:09:16 +0000 Subject: [PATCH 369/875] flags: Add adm_fix_disconnect_of_set_member Bug: 374320313 Bug: 315241296 Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.adm_fix_disconnect_of_set_member Change-Id: Idc7218924e769584e57365809472ce2797761eca --- flags/active_device_manager.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/active_device_manager.aconfig b/flags/active_device_manager.aconfig index dcbd6c154cd..fefcdd1d87e 100644 --- a/flags/active_device_manager.aconfig +++ b/flags/active_device_manager.aconfig @@ -29,4 +29,14 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +flag { + name: "adm_fix_disconnect_of_set_member" + namespace: "bluetooth" + description: "Fix disconnecting of the set member device. Make sure the other set member is not considered as fallback device." + bug: "374320313" + metadata { + purpose: PURPOSE_BUGFIX + } } \ No newline at end of file -- GitLab From 594ba09fa1dd0fd2aabf6a7e73ca7fe1765a6ef7 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 18 Oct 2024 12:13:08 -0700 Subject: [PATCH 370/875] Allow cts/car to use the cts-bluetooth utils lib Bug: 373884504 Flag: TEST_ONLY Test: atest CtsCarTestCases Change-Id: I24139b41fb9028f69d212bfda49f863d619e2c90 --- framework/tests/util/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/tests/util/Android.bp b/framework/tests/util/Android.bp index a7d4371f2cb..f1e942f4c67 100644 --- a/framework/tests/util/Android.bp +++ b/framework/tests/util/Android.bp @@ -34,6 +34,7 @@ java_library { sdk_version: "test_current", visibility: [ "//cts/tests/tests/bluetooth", + "//cts/tests/tests/car", "//packages/modules/Bluetooth/framework/tests/bumble", // TODO: b/339938196 -- remove export for other modules and test -- GitLab From aa078cb504a5fa9a125d90ed250f1e7c38c3e4d3 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Tue, 1 Oct 2024 22:06:43 +0000 Subject: [PATCH 371/875] Remove metadata_api_inactive_audio_device_upon_connection flag Bug: 322387487 Test: m com.android.btservices Change-Id: Ib1a905e95264b4cb7f5cf7618188b57e6b0299ce --- framework/api/system-current.txt | 10 +++++----- framework/java/android/bluetooth/BluetoothDevice.java | 5 ----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index f7e87588ba4..ae7d382dad1 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -191,7 +191,7 @@ package android.bluetooth { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true) public boolean fetchUuidsWithSdp(int); - method @FlaggedApi("com.android.bluetooth.flags.metadata_api_inactive_audio_device_upon_connection") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getActiveAudioDevicePolicy(); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getActiveAudioDevicePolicy(); method @NonNull public String getAnonymizedAddress(); method @IntRange(from=0xffffff9c, to=100) @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBatteryLevel(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionHandle(int); @@ -210,7 +210,7 @@ package android.bluetooth { method public void prepareToEnterProcess(@NonNull android.content.AttributionSource); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeBond(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int requestAudioPolicyAsSink(@NonNull android.bluetooth.BluetoothSinkAudioPolicy); - method @FlaggedApi("com.android.bluetooth.flags.metadata_api_inactive_audio_device_upon_connection") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setActiveAudioDevicePolicy(int); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setActiveAudioDevicePolicy(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setLowLatencyAudioAllowed(boolean); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMessageAccessPermission(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMetadata(int, @NonNull byte[]); @@ -229,9 +229,9 @@ package android.bluetooth { field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PAIRING_CANCEL = "android.bluetooth.device.action.PAIRING_CANCEL"; field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED"; field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_SWITCH_BUFFER_SIZE = "android.bluetooth.device.action.SWITCH_BUFFER_SIZE"; - field @FlaggedApi("com.android.bluetooth.flags.metadata_api_inactive_audio_device_upon_connection") public static final int ACTIVE_AUDIO_DEVICE_POLICY_ALL_PROFILES_ACTIVE_UPON_CONNECTION = 1; // 0x1 - field @FlaggedApi("com.android.bluetooth.flags.metadata_api_inactive_audio_device_upon_connection") public static final int ACTIVE_AUDIO_DEVICE_POLICY_ALL_PROFILES_INACTIVE_UPON_CONNECTION = 2; // 0x2 - field @FlaggedApi("com.android.bluetooth.flags.metadata_api_inactive_audio_device_upon_connection") public static final int ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT = 0; // 0x0 + field public static final int ACTIVE_AUDIO_DEVICE_POLICY_ALL_PROFILES_ACTIVE_UPON_CONNECTION = 1; // 0x1 + field public static final int ACTIVE_AUDIO_DEVICE_POLICY_ALL_PROFILES_INACTIVE_UPON_CONNECTION = 2; // 0x2 + field public static final int ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT = 0; // 0x0 field public static final int BATTERY_LEVEL_BLUETOOTH_OFF = -100; // 0xffffff9c field public static final int BATTERY_LEVEL_UNKNOWN = -1; // 0xffffffff field public static final int CONNECTION_ACCESS_NO = 2; // 0x2 diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 4da94af0d80..9bd547d33a9 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -1361,7 +1361,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * * @hide */ - @FlaggedApi(Flags.FLAG_METADATA_API_INACTIVE_AUDIO_DEVICE_UPON_CONNECTION) @SystemApi public static final int ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT = 0; @@ -1372,7 +1371,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * * @hide */ - @FlaggedApi(Flags.FLAG_METADATA_API_INACTIVE_AUDIO_DEVICE_UPON_CONNECTION) @SystemApi public static final int ACTIVE_AUDIO_DEVICE_POLICY_ALL_PROFILES_ACTIVE_UPON_CONNECTION = 1; @@ -1383,7 +1381,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * * @hide */ - @FlaggedApi(Flags.FLAG_METADATA_API_INACTIVE_AUDIO_DEVICE_UPON_CONNECTION) @SystemApi public static final int ACTIVE_AUDIO_DEVICE_POLICY_ALL_PROFILES_INACTIVE_UPON_CONNECTION = 2; @@ -3460,7 +3457,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * @throws IllegalArgumentException if this BluetoothDevice object has an invalid address * @hide */ - @FlaggedApi(Flags.FLAG_METADATA_API_INACTIVE_AUDIO_DEVICE_UPON_CONNECTION) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) @@ -3492,7 +3488,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * @return active audio device policy of the device * @hide */ - @FlaggedApi(Flags.FLAG_METADATA_API_INACTIVE_AUDIO_DEVICE_UPON_CONNECTION) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) -- GitLab From c1571d8634653080758c06c67b06f1eacb31f21b Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 17 Oct 2024 17:46:40 -0700 Subject: [PATCH 372/875] VolumeControl: rm impossible null handler Use final & injected dependency Update test to TestLooper & truth Split test to actionable smaller test Apply up to date java recommendation Bug: 368527278 Bug: 367133232 Test: atest BluetoothInstrumentationTests:VolumeControlServiceTest Test: atest BluetoothInstrumentationTests:VolumeControlStateMachineTest Flag: Exempt refactor no-op Change-Id: I15a9122a10abbd4ed598a1af5b8a8902967b9135 --- .../bluetooth/vc/VolumeControlService.java | 238 ++-- .../bluetooth/vc/VolumeControlStackEvent.java | 34 +- .../vc/VolumeControlStateMachine.java | 340 ++--- .../vc/VolumeControlNativeInterfaceTest.java | 4 +- .../vc/VolumeControlServiceTest.java | 1158 ++++++----------- .../vc/VolumeControlStateMachineTest.java | 520 +++----- system/include/hardware/bt_vc.h | 1 + 7 files changed, 820 insertions(+), 1475 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 5ebd46026b7..8932ae28d92 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -19,6 +19,14 @@ 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; +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; import static java.util.Objects.requireNonNull; @@ -31,7 +39,6 @@ import android.bluetooth.IBluetoothLeAudio; import android.bluetooth.IBluetoothVolumeControl; import android.bluetooth.IBluetoothVolumeControlCallback; import android.content.AttributionSource; -import android.content.Context; import android.media.AudioManager; import android.os.Handler; import android.os.HandlerThread; @@ -70,27 +77,28 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class VolumeControlService extends ProfileService { - private static final String TAG = "VolumeControlService"; + private static final String TAG = VolumeControlService.class.getSimpleName(); - // Timeout for state machine thread join, to prevent potential ANR. private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; - private static final int LE_AUDIO_MAX_VOL = 255; + /* As defined by Volume Control Service 1.0.1, 3.3.1. Volume Flags behavior. + * User Set Volume Setting means that remote keeps volume in its cache. */ + @VisibleForTesting static final int VOLUME_FLAGS_PERSISTED_USER_SET_VOLUME_MASK = 0x01; private static VolumeControlService sVolumeControlService; - private AdapterService mAdapterService; - private DatabaseManager mDatabaseManager; - private HandlerThread mStateMachinesThread; - private Handler mHandler = null; - @VisibleForTesting @GuardedBy("mCallbacks") final RemoteCallbackList mCallbacks = new RemoteCallbackList<>(); - VolumeControlNativeInterface mVolumeControlNativeInterface; - @VisibleForTesting AudioManager mAudioManager; + private final AdapterService mAdapterService; + private final AudioManager mAudioManager; + private final DatabaseManager mDatabaseManager; + private final Handler mHandler; + private final HandlerThread mStateMachinesThread; + private final Looper mStateMachinesLooper; + private final VolumeControlNativeInterface mNativeInterface; private final Map mStateMachines = new HashMap<>(); private final Map mAudioOffsets = @@ -100,15 +108,34 @@ public class VolumeControlService extends ProfileService { private final Map mGroupMuteCache = new HashMap<>(); private final Map mDeviceVolumeCache = new HashMap<>(); - /* As defined by Volume Control Service 1.0.1, 3.3.1. Volume Flags behavior. - * User Set Volume Setting means that remote keeps volume in its cache. - */ - @VisibleForTesting static final int VOLUME_FLAGS_PERSISTED_USER_SET_VOLUME_MASK = 0x01; - @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); - public VolumeControlService(Context ctx) { - super(ctx); + public VolumeControlService(AdapterService adapterService) { + this(adapterService, null, VolumeControlNativeInterface.getInstance()); + } + + @VisibleForTesting + VolumeControlService( + AdapterService adapterService, + Looper looper, + VolumeControlNativeInterface nativeInterface) { + super(requireNonNull(adapterService)); + mAdapterService = adapterService; + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); + mNativeInterface = requireNonNull(nativeInterface); + mAudioManager = requireNonNull(getSystemService(AudioManager.class)); + if (looper == null) { + mHandler = new Handler(requireNonNull(Looper.getMainLooper())); + mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines"); + mStateMachinesThread.start(); + mStateMachinesLooper = mStateMachinesThread.getLooper(); + } else { + mHandler = new Handler(looper); + mStateMachinesThread = null; + mStateMachinesLooper = looper; + } + setVolumeControlService(this); + mNativeInterface.init(); } public static boolean isEnabled() { @@ -120,45 +147,9 @@ public class VolumeControlService extends ProfileService { return new BluetoothVolumeControlBinder(this); } - @Override - public void start() { - Log.d(TAG, "start()"); - if (sVolumeControlService != null) { - throw new IllegalStateException("start() called twice"); - } - - // Get AdapterService, VolumeControlNativeInterface, DatabaseManager, AudioManager. - // None of them can be null. - mAdapterService = requireNonNull(AdapterService.getAdapterService()); - mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); - mVolumeControlNativeInterface = requireNonNull(VolumeControlNativeInterface.getInstance()); - mAudioManager = requireNonNull(getSystemService(AudioManager.class)); - - // Start handler thread for state machines - mHandler = new Handler(Looper.getMainLooper()); - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines"); - mStateMachinesThread.start(); - - mAudioOffsets.clear(); - mGroupVolumeCache.clear(); - mGroupMuteCache.clear(); - mDeviceVolumeCache.clear(); - - // Mark service as started - setVolumeControlService(this); - - // Initialize native interface - mVolumeControlNativeInterface.init(); - } - @Override public void stop() { Log.d(TAG, "stop()"); - if (sVolumeControlService == null) { - Log.w(TAG, "stop() called before start()"); - return; - } // Mark service as stopped setVolumeControlService(null); @@ -167,7 +158,6 @@ public class VolumeControlService extends ProfileService { synchronized (mStateMachines) { for (VolumeControlStateMachine sm : mStateMachines.values()) { sm.doQuit(); - sm.cleanup(); } mStateMachines.clear(); } @@ -176,44 +166,26 @@ public class VolumeControlService extends ProfileService { try { mStateMachinesThread.quitSafely(); mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); - mStateMachinesThread = null; } catch (InterruptedException e) { // Do not rethrow as we are shutting down anyway } } - // Unregister handler and remove all queued messages. - if (mHandler != null) { - mHandler.removeCallbacksAndMessages(null); - mHandler = null; - } + mHandler.removeCallbacksAndMessages(null); // Cleanup native interface - mVolumeControlNativeInterface.cleanup(); - mVolumeControlNativeInterface = null; + mNativeInterface.cleanup(); mAudioOffsets.clear(); mGroupVolumeCache.clear(); mGroupMuteCache.clear(); mDeviceVolumeCache.clear(); - // Clear AdapterService, VolumeControlNativeInterface - mAudioManager = null; - mVolumeControlNativeInterface = null; - mAdapterService = null; - synchronized (mCallbacks) { - if (mCallbacks != null) { - mCallbacks.kill(); - } + mCallbacks.kill(); } } - @Override - public void cleanup() { - Log.d(TAG, "cleanup()"); - } - /** * Get the VolumeControlService instance * @@ -244,7 +216,7 @@ public class VolumeControlService extends ProfileService { return false; } - if (getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { + if (getConnectionPolicy(device) == CONNECTION_POLICY_FORBIDDEN) { return false; } final ParcelUuid[] featureUuids = mAdapterService.getRemoteUuids(device); @@ -260,7 +232,7 @@ public class VolumeControlService extends ProfileService { if (smConnect == null) { Log.e(TAG, "Cannot connect to " + device + " : no state machine"); } - smConnect.sendMessage(VolumeControlStateMachine.CONNECT); + smConnect.sendMessage(VolumeControlStateMachine.MESSAGE_CONNECT); } return true; @@ -274,7 +246,7 @@ public class VolumeControlService extends ProfileService { synchronized (mStateMachines) { VolumeControlStateMachine sm = getOrCreateStateMachine(device); if (sm != null) { - sm.sendMessage(VolumeControlStateMachine.DISCONNECT); + sm.sendMessage(VolumeControlStateMachine.MESSAGE_DISCONNECT); } } @@ -317,11 +289,11 @@ public class VolumeControlService extends ProfileService { int bondState = mAdapterService.getBondState(device); // 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) { + if (bondState != BOND_BONDED) { Log.w(TAG, "okToConnect: return false, bondState=" + bondState); return false; - } else if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_UNKNOWN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { + } else if (connectionPolicy != CONNECTION_POLICY_UNKNOWN + && connectionPolicy != CONNECTION_POLICY_ALLOWED) { // Otherwise, reject the connection if connectionPolicy is not valid. Log.w(TAG, "okToConnect: return false, connectionPolicy=" + connectionPolicy); return false; @@ -344,7 +316,7 @@ public class VolumeControlService extends ProfileService { if (!Utils.arrayContains(featureUuids, BluetoothUuid.VOLUME_CONTROL)) { continue; } - int connectionState = BluetoothProfile.STATE_DISCONNECTED; + int connectionState = STATE_DISCONNECTED; VolumeControlStateMachine sm = mStateMachines.get(device); if (sm != null) { connectionState = sm.getConnectionState(); @@ -380,7 +352,7 @@ public class VolumeControlService extends ProfileService { synchronized (mStateMachines) { VolumeControlStateMachine sm = mStateMachines.get(device); if (sm == null) { - return BluetoothProfile.STATE_DISCONNECTED; + return STATE_DISCONNECTED; } return sm.getConnectionState(); } @@ -404,9 +376,9 @@ public class VolumeControlService extends ProfileService { Log.d(TAG, "Saved connectionPolicy " + device + " = " + connectionPolicy); mDatabaseManager.setProfileConnectionPolicy( device, BluetoothProfile.VOLUME_CONTROL, connectionPolicy); - if (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { + if (connectionPolicy == CONNECTION_POLICY_ALLOWED) { connect(device); - } else if (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { + } else if (connectionPolicy == CONNECTION_POLICY_FORBIDDEN) { disconnect(device); } return true; @@ -465,7 +437,7 @@ public class VolumeControlService extends ProfileService { return; } - mVolumeControlNativeInterface.setExtAudioOutVolumeOffset(device, instanceId, volumeOffset); + mNativeInterface.setExtAudioOutVolumeOffset(device, instanceId, volumeOffset); } void setDeviceVolume(BluetoothDevice device, int volume, boolean isGroupOp) { @@ -489,7 +461,7 @@ public class VolumeControlService extends ProfileService { } else { Log.i(TAG, "Setting individual device volume"); mDeviceVolumeCache.put(device, volume); - mVolumeControlNativeInterface.setVolume(device, volume); + mNativeInterface.setVolume(device, volume); } } @@ -500,7 +472,7 @@ public class VolumeControlService extends ProfileService { } mGroupVolumeCache.put(groupId, volume); - mVolumeControlNativeInterface.setGroupVolume(groupId, volume); + mNativeInterface.setGroupVolume(groupId, volume); // We only receive the volume change and mute state needs to be acquired manually Boolean isGroupMute = mGroupMuteCache.getOrDefault(groupId, false); @@ -508,7 +480,7 @@ public class VolumeControlService extends ProfileService { /* Note: AudioService keeps volume levels for each stream and for each device type, * however it stores the mute state only for the stream type but not for each individual - * device type. When active device changes, it's volume level gets aplied, but mute state + * device type. When active device changes, it's volume level gets applied, but mute state * is not, but can be either derived from the volume level or just unmuted like for A2DP. * Also setting volume level > 0 to audio system will implicitly unmute the stream. * However LeAudio devices can keep their volume level high, while keeping it mute so we @@ -580,21 +552,21 @@ public class VolumeControlService extends ProfileService { } public void mute(BluetoothDevice device) { - mVolumeControlNativeInterface.mute(device); + mNativeInterface.mute(device); } public void muteGroup(int groupId) { mGroupMuteCache.put(groupId, true); - mVolumeControlNativeInterface.muteGroup(groupId); + mNativeInterface.muteGroup(groupId); } public void unmute(BluetoothDevice device) { - mVolumeControlNativeInterface.unmute(device); + mNativeInterface.unmute(device); } public void unmuteGroup(int groupId) { mGroupMuteCache.put(groupId, false); - mVolumeControlNativeInterface.unmuteGroup(groupId); + mNativeInterface.unmuteGroup(groupId); } void notifyNewCallbackOfKnownVolumeInfo(IBluetoothVolumeControlCallback callback) { @@ -670,7 +642,7 @@ public class VolumeControlService extends ProfileService { if (sm == null) { return; } - if (sm.getConnectionState() != BluetoothProfile.STATE_CONNECTED) { + if (sm.getConnectionState() != STATE_CONNECTED) { return; } } @@ -680,7 +652,7 @@ public class VolumeControlService extends ProfileService { synchronized (mStateMachines) { VolumeControlStateMachine sm = mStateMachines.get(device); if (sm != null) { - can_change_volume = (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED); + can_change_volume = (sm.getConnectionState() == STATE_CONNECTED); } } @@ -691,15 +663,15 @@ public class VolumeControlService extends ProfileService { groupId, IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME); if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) { Log.i(TAG, "Setting value:" + groupVolume + " to " + device); - mVolumeControlNativeInterface.setVolume(device, groupVolume); + mNativeInterface.setVolume(device, groupVolume); } Boolean isGroupMuted = mGroupMuteCache.getOrDefault(groupId, false); Log.i(TAG, "Setting mute:" + isGroupMuted + " to " + device); if (isGroupMuted) { - mVolumeControlNativeInterface.mute(device); + mNativeInterface.mute(device); } else { - mVolumeControlNativeInterface.unmute(device); + mNativeInterface.unmute(device); } } } @@ -865,21 +837,20 @@ public class VolumeControlService extends ProfileService { synchronized (mStateMachines) { VolumeControlStateMachine sm = mStateMachines.get(device); if (sm != null) { - can_change_volume = - (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED); + can_change_volume = (sm.getConnectionState() == STATE_CONNECTED); } } if (can_change_volume && (groupVolume != volume)) { Log.i(TAG, "Setting value:" + groupVolume + " to " + device); - mVolumeControlNativeInterface.setVolume(device, groupVolume); + mNativeInterface.setVolume(device, groupVolume); } if (can_change_volume && (groupMute != mute)) { Log.i(TAG, "Setting mute:" + groupMute + " to " + device); if (groupMute) { - mVolumeControlNativeInterface.mute(device); + mNativeInterface.mute(device); } else { - mVolumeControlNativeInterface.unmute(device); + mNativeInterface.unmute(device); } } } else { @@ -925,19 +896,16 @@ public class VolumeControlService extends ProfileService { Log.d(TAG, "Volume mode: " + mode + "0: normal, 1: ring, 2,3: call"); - switch (mode) { - case AudioManager.MODE_IN_COMMUNICATION: - case AudioManager.MODE_IN_CALL: - return AudioManager.STREAM_VOICE_CALL; - case AudioManager.MODE_RINGTONE: + return switch (mode) { + case AudioManager.MODE_IN_CALL, AudioManager.MODE_IN_COMMUNICATION -> { + yield AudioManager.STREAM_VOICE_CALL; + } + case AudioManager.MODE_RINGTONE -> { Log.d(TAG, " Update during ringtone applied to voice call"); - return AudioManager.STREAM_VOICE_CALL; - case AudioManager.MODE_NORMAL: - default: - // other conditions will influence the stream type choice, read on... - break; - } - return AudioManager.STREAM_MUSIC; + yield AudioManager.STREAM_VOICE_CALL; + } + default -> AudioManager.STREAM_MUSIC; + }; } void handleExternalOutputs(BluetoothDevice device, int numberOfExternalOutputs) { @@ -1277,12 +1245,9 @@ public class VolumeControlService extends ProfileService { if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { switch (stackEvent.valueInt1) { - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTED: - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTING: + case STATE_CONNECTED, STATE_CONNECTING -> { sm = getOrCreateStateMachine(device); - break; - default: - break; + } } } } @@ -1290,7 +1255,7 @@ public class VolumeControlService extends ProfileService { Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); return; } - sm.sendMessage(VolumeControlStateMachine.STACK_EVENT, stackEvent); + sm.sendMessage(VolumeControlStateMachine.MESSAGE_STACK_EVENT, stackEvent); } } @@ -1307,11 +1272,9 @@ public class VolumeControlService extends ProfileService { Log.d(TAG, "Creating a new state machine for " + device); sm = - VolumeControlStateMachine.make( - device, - this, - mVolumeControlNativeInterface, - mStateMachinesThread.getLooper()); + new VolumeControlStateMachine( + this, device, mNativeInterface, mStateMachinesLooper); + sm.start(); mStateMachines.put(device, sm); return sm; } @@ -1392,7 +1355,7 @@ public class VolumeControlService extends ProfileService { void bondStateChanged(BluetoothDevice device, int bondState) { Log.d(TAG, "Bond state changed for device: " + device + " state: " + bondState); // Remove state machine if the bonding for a device is removed - if (bondState != BluetoothDevice.BOND_NONE) { + if (bondState != BOND_NONE) { return; } @@ -1401,7 +1364,7 @@ public class VolumeControlService extends ProfileService { if (sm == null) { return; } - if (sm.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) { + if (sm.getConnectionState() != STATE_DISCONNECTED) { Log.i(TAG, "Disconnecting device because it was unbonded."); disconnect(device); return; @@ -1421,7 +1384,6 @@ public class VolumeControlService extends ProfileService { } Log.i(TAG, "removeStateMachine: removing state machine for device: " + device); sm.doQuit(); - sm.cleanup(); mStateMachines.remove(device); } } @@ -1450,13 +1412,13 @@ public class VolumeControlService extends ProfileService { } // Check if the device is disconnected - if unbond, remove the state machine - if (toState == BluetoothProfile.STATE_DISCONNECTED) { + if (toState == STATE_DISCONNECTED) { int bondState = mAdapterService.getBondState(device); - if (bondState == BluetoothDevice.BOND_NONE) { + if (bondState == BOND_NONE) { Log.d(TAG, device + " is unbond. Remove state machine"); removeStateMachine(device); } - } else if (toState == BluetoothProfile.STATE_CONNECTED) { + } else if (toState == STATE_CONNECTED) { // Restore the group volume if it was changed while the device was not yet connected. CsipSetCoordinatorService csipClient = mFactory.getCsipSetCoordinatorService(); if (csipClient != null) { @@ -1466,14 +1428,14 @@ public class VolumeControlService extends ProfileService { mGroupVolumeCache.getOrDefault( groupId, IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME); if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) { - mVolumeControlNativeInterface.setVolume(device, groupVolume); + mNativeInterface.setVolume(device, groupVolume); } Boolean groupMute = mGroupMuteCache.getOrDefault(groupId, false); if (groupMute) { - mVolumeControlNativeInterface.mute(device); + mNativeInterface.mute(device); } else { - mVolumeControlNativeInterface.unmute(device); + mNativeInterface.unmute(device); } } } else { @@ -1554,7 +1516,7 @@ public class VolumeControlService extends ProfileService { VolumeControlService service = getService(source); if (service == null) { - return BluetoothProfile.STATE_DISCONNECTED; + return STATE_DISCONNECTED; } return service.getConnectionState(device); @@ -1580,7 +1542,7 @@ public class VolumeControlService extends ProfileService { VolumeControlService service = getService(source); if (service == null) { - return BluetoothProfile.CONNECTION_POLICY_UNKNOWN; + return CONNECTION_POLICY_UNKNOWN; } service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index 62f8b702d70..d102952d272 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -18,6 +18,7 @@ package com.android.bluetooth.vc; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; public class VolumeControlStackEvent { // Event types for STACK_EVENT message (coming from native) @@ -34,13 +35,6 @@ public class VolumeControlStackEvent { public static final int EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED = 10; public static final int EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED = 11; - // Do not modify without updating the HAL bt_vc_aid.h files. - // Match up with enum class ConnectionState of bt_vc_aid.h. - static final int CONNECTION_STATE_DISCONNECTED = 0; - static final int CONNECTION_STATE_CONNECTING = 1; - static final int CONNECTION_STATE_CONNECTED = 2; - static final int CONNECTION_STATE_DISCONNECTING = 3; - public int type; public BluetoothDevice device; public int valueInt1; @@ -108,18 +102,7 @@ public class VolumeControlStackEvent { private static String eventTypeValue1ToString(int type, int value) { switch (type) { case EVENT_TYPE_CONNECTION_STATE_CHANGED: - switch (value) { - case CONNECTION_STATE_DISCONNECTED: - return "CONNECTION_STATE_DISCONNECTED"; - case CONNECTION_STATE_CONNECTING: - return "CONNECTION_STATE_CONNECTING"; - case CONNECTION_STATE_CONNECTED: - return "CONNECTION_STATE_CONNECTED"; - case CONNECTION_STATE_DISCONNECTING: - return "CONNECTION_STATE_DISCONNECTING"; - default: - return "UNKNOWN"; - } + return BluetoothProfile.getConnectionStateName(value); case EVENT_TYPE_VOLUME_STATE_CHANGED: return "{group_id:" + value + "}"; case EVENT_TYPE_DEVICE_AVAILABLE: @@ -143,18 +126,7 @@ public class VolumeControlStackEvent { private static String eventTypeValue2ToString(int type, int value) { switch (type) { case EVENT_TYPE_CONNECTION_STATE_CHANGED: - switch (value) { - case CONNECTION_STATE_DISCONNECTED: - return "CONNECTION_STATE_DISCONNECTED"; - case CONNECTION_STATE_CONNECTING: - return "CONNECTION_STATE_CONNECTING"; - case CONNECTION_STATE_CONNECTED: - return "CONNECTION_STATE_CONNECTED"; - case CONNECTION_STATE_DISCONNECTING: - return "CONNECTION_STATE_DISCONNECTING"; - default: - return "UNKNOWN"; - } + return BluetoothProfile.getConnectionStateName(value); case EVENT_TYPE_VOLUME_STATE_CHANGED: return "{volume:" + value + "}"; case EVENT_TYPE_DEVICE_AVAILABLE: diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java index 4a68e8f337f..1e1ca9aa167 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java @@ -18,6 +18,11 @@ package com.android.bluetooth.vc; 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 android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; +import static android.bluetooth.BluetoothProfile.getConnectionStateName; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; @@ -35,37 +40,34 @@ import com.android.internal.util.StateMachine; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Duration; import java.util.Scanner; -public class VolumeControlStateMachine extends StateMachine { +class VolumeControlStateMachine extends StateMachine { + private static final String TAG = VolumeControlStateMachine.class.getSimpleName(); - private static final String TAG = "VolumeControlStateMachine"; + static final int MESSAGE_CONNECT = 1; + static final int MESSAGE_DISCONNECT = 2; + static final int MESSAGE_STACK_EVENT = 101; + @VisibleForTesting static final int MESSAGE_CONNECT_TIMEOUT = 201; - static final int CONNECT = 1; - static final int DISCONNECT = 2; - @VisibleForTesting static final int STACK_EVENT = 101; - @VisibleForTesting static final int CONNECT_TIMEOUT = 201; + @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(30); - // NOTE: the value is not "final" - it is modified in the unit tests - @VisibleForTesting static int sConnectTimeoutMs = 30000; // 30s + private final Disconnected mDisconnected; + private final Connecting mConnecting; + private final Disconnecting mDisconnecting; + private final Connected mConnected; + private final VolumeControlService mService; + private final VolumeControlNativeInterface mNativeInterface; + private final BluetoothDevice mDevice; - private Disconnected mDisconnected; - private Connecting mConnecting; - private Disconnecting mDisconnecting; - private Connected mConnected; private int mLastConnectionState = -1; - private VolumeControlService mService; - private VolumeControlNativeInterface mNativeInterface; - - private final BluetoothDevice mDevice; - VolumeControlStateMachine( - BluetoothDevice device, VolumeControlService svc, + BluetoothDevice device, VolumeControlNativeInterface nativeInterface, Looper looper) { - super(TAG, looper); mDevice = device; mService = svc; @@ -84,27 +86,11 @@ public class VolumeControlStateMachine extends StateMachine { setInitialState(mDisconnected); } - static VolumeControlStateMachine make( - BluetoothDevice device, - VolumeControlService svc, - VolumeControlNativeInterface nativeInterface, - Looper looper) { - Log.i(TAG, "make for device " + device); - VolumeControlStateMachine VolumeControlSm = - new VolumeControlStateMachine(device, svc, nativeInterface, looper); - VolumeControlSm.start(); - return VolumeControlSm; - } - public void doQuit() { log("doQuit for device " + mDevice); quitNow(); } - public void cleanup() { - log("cleanup for device " + mDevice); - } - @VisibleForTesting class Disconnected extends State { @Override @@ -116,11 +102,11 @@ public class VolumeControlStateMachine extends StateMachine { + "): " + messageWhatToString(getCurrentMessage().what)); - removeDeferredMessages(DISCONNECT); + removeDeferredMessages(MESSAGE_DISCONNECT); if (mLastConnectionState != -1) { // Don't broadcast during startup - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED, mLastConnectionState); + broadcastConnectionState(STATE_DISCONNECTED, mLastConnectionState); } } @@ -131,7 +117,7 @@ public class VolumeControlStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; + mLastConnectionState = STATE_DISCONNECTED; } @Override @@ -143,7 +129,7 @@ public class VolumeControlStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: + case MESSAGE_CONNECT -> { log("Connecting to " + mDevice); if (!mNativeInterface.connectVolumeControl(mDevice)) { Log.e(TAG, "Disconnected: error connecting to " + mDevice); @@ -157,27 +143,26 @@ public class VolumeControlStateMachine extends StateMachine { TAG, "Outgoing VolumeControl Connecting request rejected: " + mDevice); } - break; - case DISCONNECT: + } + case MESSAGE_DISCONNECT -> { Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { VolumeControlStackEvent event = (VolumeControlStackEvent) message.obj; Log.d(TAG, "Disconnected: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, "Disconnected: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -185,10 +170,7 @@ public class VolumeControlStateMachine extends StateMachine { // in Disconnected state private void processConnectionEvent(int state) { switch (state) { - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Ignore VolumeControl DISCONNECTED event: " + mDevice); - break; - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTING: + case STATE_CONNECTING -> { if (mService.okToConnect(mDevice)) { Log.i( TAG, @@ -201,8 +183,8 @@ public class VolumeControlStateMachine extends StateMachine { "Incoming Volume Control Connecting request rejected: " + mDevice); mNativeInterface.disconnectVolumeControl(mDevice); } - break; - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { Log.w(TAG, "VolumeControl Connected from Disconnected state: " + mDevice); if (mService.okToConnect(mDevice)) { Log.i( @@ -214,13 +196,8 @@ public class VolumeControlStateMachine extends StateMachine { Log.w(TAG, "Incoming VolumeControl Connected request rejected: " + mDevice); mNativeInterface.disconnectVolumeControl(mDevice); } - break; - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Ignore VolumeControl DISCONNECTING event: " + mDevice); - break; - default: - Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); - break; + } + default -> Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); } } } @@ -235,8 +212,8 @@ public class VolumeControlStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTING, mLastConnectionState); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + broadcastConnectionState(STATE_CONNECTING, mLastConnectionState); } @Override @@ -246,8 +223,8 @@ public class VolumeControlStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; - removeMessages(CONNECT_TIMEOUT); + mLastConnectionState = STATE_CONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override @@ -259,42 +236,38 @@ public class VolumeControlStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: + case MESSAGE_CONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { Log.w(TAG, "Connecting connection timeout: " + mDevice); mNativeInterface.disconnectVolumeControl(mDevice); VolumeControlStackEvent disconnectEvent = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = - VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - case DISCONNECT: + disconnectEvent.valueInt1 = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, disconnectEvent); + } + case MESSAGE_DISCONNECT -> { log("Connecting: connection canceled to " + mDevice); mNativeInterface.disconnectVolumeControl(mDevice); transitionTo(mDisconnected); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { VolumeControlStackEvent event = (VolumeControlStackEvent) message.obj; log("Connecting: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Connecting: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, "Connecting: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -302,41 +275,29 @@ public class VolumeControlStateMachine extends StateMachine { // in Connecting state private void processConnectionEvent(int state) { switch (state) { - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.w(TAG, "Connecting device disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTING: - break; - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTING: + } + case STATE_CONNECTED -> transitionTo(mConnected); + case STATE_DISCONNECTING -> { Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; + } + default -> Log.e(TAG, "Incorrect state: " + state); } } } int getConnectionState() { String currentState = getCurrentState().getName(); - switch (currentState) { - case "Disconnected": - return BluetoothProfile.STATE_DISCONNECTED; - case "Connecting": - return BluetoothProfile.STATE_CONNECTING; - case "Connected": - return BluetoothProfile.STATE_CONNECTED; - case "Disconnecting": - return BluetoothProfile.STATE_DISCONNECTING; - default: - Log.e(TAG, "Bad currentState: " + currentState); - return BluetoothProfile.STATE_DISCONNECTED; - } + return switch (currentState) { + case "Disconnected" -> STATE_DISCONNECTED; + case "Connecting" -> STATE_CONNECTING; + case "Connected" -> STATE_CONNECTED; + case "Disconnecting" -> STATE_DISCONNECTING; + default -> STATE_DISCONNECTED; + }; } @VisibleForTesting @@ -349,8 +310,8 @@ public class VolumeControlStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTING, mLastConnectionState); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + broadcastConnectionState(STATE_DISCONNECTING, mLastConnectionState); } @Override @@ -360,8 +321,8 @@ public class VolumeControlStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); + mLastConnectionState = STATE_DISCONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override @@ -373,43 +334,33 @@ public class VolumeControlStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - { - Log.w(TAG, "Disconnecting connection timeout: " + mDevice); - mNativeInterface.disconnectVolumeControl(mDevice); - VolumeControlStackEvent disconnectEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent - .EVENT_TYPE_CONNECTION_STATE_CHANGED); - disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = - VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - } - case DISCONNECT: - deferMessage(message); - break; - case STACK_EVENT: + case MESSAGE_CONNECT, MESSAGE_DISCONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { + Log.w(TAG, "Disconnecting connection timeout: " + mDevice); + mNativeInterface.disconnectVolumeControl(mDevice); + VolumeControlStackEvent disconnectEvent = + new VolumeControlStackEvent( + VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + disconnectEvent.device = mDevice; + disconnectEvent.valueInt1 = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, disconnectEvent); + } + case MESSAGE_STACK_EVENT -> { VolumeControlStackEvent event = (VolumeControlStackEvent) message.obj; log("Disconnecting: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnecting: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, "Disconnecting: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -417,11 +368,11 @@ public class VolumeControlStateMachine extends StateMachine { // in Disconnecting state private void processConnectionEvent(int state) { switch (state) { - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { if (mService.okToConnect(mDevice)) { Log.w(TAG, "Disconnecting interrupted: device is connected: " + mDevice); transitionTo(mConnected); @@ -430,8 +381,8 @@ public class VolumeControlStateMachine extends StateMachine { Log.w(TAG, "Incoming VolumeControl Connected request rejected: " + mDevice); mNativeInterface.disconnectVolumeControl(mDevice); } - break; - case VolumeControlStackEvent.CONNECTION_STATE_CONNECTING: + } + case STATE_CONNECTING -> { if (mService.okToConnect(mDevice)) { Log.i(TAG, "Disconnecting interrupted: try to reconnect: " + mDevice); transitionTo(mConnecting); @@ -442,12 +393,8 @@ public class VolumeControlStateMachine extends StateMachine { "Incoming VolumeControl Connecting request rejected: " + mDevice); mNativeInterface.disconnectVolumeControl(mDevice); } - break; - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTING: - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; + } + default -> Log.e(TAG, "Incorrect state: " + state); } } } @@ -462,8 +409,8 @@ public class VolumeControlStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - removeDeferredMessages(CONNECT); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTED, mLastConnectionState); + removeDeferredMessages(MESSAGE_CONNECT); + broadcastConnectionState(STATE_CONNECTED, mLastConnectionState); } @Override @@ -473,7 +420,7 @@ public class VolumeControlStateMachine extends StateMachine { + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; + mLastConnectionState = STATE_CONNECTED; } @Override @@ -481,10 +428,10 @@ public class VolumeControlStateMachine extends StateMachine { log("Connected process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: + case MESSAGE_CONNECT -> { Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); - break; - case DISCONNECT: + } + case MESSAGE_DISCONNECT -> { log("Disconnecting from " + mDevice); if (!mNativeInterface.disconnectVolumeControl(mDevice)) { // If error in the native stack, transition directly to Disconnected state. @@ -493,24 +440,25 @@ public class VolumeControlStateMachine extends StateMachine { break; } transitionTo(mDisconnecting); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { VolumeControlStackEvent event = (VolumeControlStackEvent) message.obj; log("Connected: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: + } + default -> { Log.e(TAG, "Connected: ignoring stack event: " + event); - break; + } } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -518,17 +466,16 @@ public class VolumeControlStateMachine extends StateMachine { // in Connected state private void processConnectionEvent(int state) { switch (state) { - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected from " + mDevice); transitionTo(mDisconnected); - break; - case VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTING: + } + case STATE_DISCONNECTING -> { Log.i(TAG, "Disconnecting from " + mDevice); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state); - break; + } + default -> + Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state); } } } @@ -547,9 +494,9 @@ public class VolumeControlStateMachine extends StateMachine { "Connection state " + mDevice + ": " - + profileStateToString(prevState) + + getConnectionStateName(prevState) + "->" - + profileStateToString(newState)); + + getConnectionStateName(newState)); mService.handleConnectionStateChanged(mDevice, prevState, newState); Intent intent = new Intent(BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED); @@ -563,35 +510,13 @@ public class VolumeControlStateMachine extends StateMachine { } private static String messageWhatToString(int what) { - switch (what) { - case CONNECT: - return "CONNECT"; - case DISCONNECT: - return "DISCONNECT"; - case STACK_EVENT: - return "STACK_EVENT"; - case CONNECT_TIMEOUT: - return "CONNECT_TIMEOUT"; - default: - break; - } - return Integer.toString(what); - } - - private static String profileStateToString(int state) { - switch (state) { - case BluetoothProfile.STATE_DISCONNECTED: - return "DISCONNECTED"; - case BluetoothProfile.STATE_CONNECTING: - return "CONNECTING"; - case BluetoothProfile.STATE_CONNECTED: - return "CONNECTED"; - case BluetoothProfile.STATE_DISCONNECTING: - return "DISCONNECTING"; - default: - break; - } - return Integer.toString(state); + return switch (what) { + case MESSAGE_CONNECT -> "CONNECT"; + case MESSAGE_DISCONNECT -> "DISCONNECT"; + case MESSAGE_STACK_EVENT -> "STACK_EVENT"; + case MESSAGE_CONNECT_TIMEOUT -> "CONNECT_TIMEOUT"; + default -> Integer.toString(what); + }; } public void dump(StringBuilder sb) { @@ -611,9 +536,4 @@ public class VolumeControlStateMachine extends StateMachine { } scanner.close(); } - - @Override - protected void log(String msg) { - super.log(msg); - } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java index 2f734f585ff..9b0aa48c62d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java @@ -21,6 +21,8 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.bluetooth.BluetoothProfile; + import androidx.test.runner.AndroidJUnit4; import org.junit.After; @@ -55,7 +57,7 @@ public class VolumeControlNativeInterfaceTest { @Test public void onConnectionStateChanged() { - int state = VolumeControlStackEvent.CONNECTION_STATE_CONNECTED; + int state = BluetoothProfile.STATE_CONNECTED; byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; mNativeInterface.onConnectionStateChanged(state, address); 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 22ec653e36e..a89342a3970 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 @@ -17,9 +17,32 @@ package com.android.bluetooth.vc; +import static android.bluetooth.BluetoothDevice.BOND_BONDED; +import static android.bluetooth.BluetoothDevice.BOND_BONDING; +import static android.bluetooth.BluetoothDevice.BOND_NONE; +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; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; -import static org.mockito.Mockito.*; +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 static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -28,20 +51,16 @@ import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothVolumeControl; import android.bluetooth.IBluetoothVolumeControlCallback; import android.content.AttributionSource; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.media.AudioManager; import android.os.Binder; -import android.os.Looper; import android.os.ParcelUuid; +import android.os.test.TestLooper; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.MediumTest; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; @@ -53,46 +72,31 @@ import com.android.bluetooth.csip.CsipSetCoordinatorService; import com.android.bluetooth.flags.Flags; import com.android.bluetooth.le_audio.LeAudioService; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.IntStream; @MediumTest @RunWith(AndroidJUnit4.class) public class VolumeControlServiceTest { - private BluetoothAdapter mAdapter; - private AttributionSource mAttributionSource; - private Context mTargetContext; - private VolumeControlService mService; - private VolumeControlService.BluetoothVolumeControlBinder mServiceBinder; - private BluetoothDevice mDevice; - private BluetoothDevice mDeviceTwo; - private HashMap> mDeviceQueueMap; - private static final int TIMEOUT_MS = 1000; - private static final int BT_LE_AUDIO_MAX_VOL = 255; - private static final int MEDIA_MIN_VOL = 0; - private static final int MEDIA_MAX_VOL = 25; - private static final int CALL_MIN_VOL = 1; - private static final int CALL_MAX_VOL = 8; - private static final int TEST_GROUP_ID = 1; - - private BroadcastReceiver mVolumeControlIntentReceiver; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private AdapterService mAdapterService; @Mock private BassClientService mBassClientService; @@ -103,22 +107,41 @@ public class VolumeControlServiceTest { @Mock private ServiceFactory mServiceFactory; @Mock private CsipSetCoordinatorService mCsipService; - @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private static final int BT_LE_AUDIO_MAX_VOL = 255; + private static final int MEDIA_MIN_VOL = 0; + private static final int MEDIA_MAX_VOL = 25; + private static final int CALL_MIN_VOL = 1; + private static final int CALL_MAX_VOL = 8; + private static final int TEST_GROUP_ID = 1; + + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 134); + private final BluetoothDevice mDeviceTwo = TestUtils.getTestDevice(mAdapter, 231); + + private AttributionSource mAttributionSource; + private VolumeControlService mService; + private VolumeControlService.BluetoothVolumeControlBinder mBinder; + private InOrder mInOrder; + private TestLooper mLooper; @Before - public void setUp() throws Exception { - mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + public void setUp() { + doReturn(true).when(mNativeInterface).connectVolumeControl(any()); + doReturn(true).when(mNativeInterface).disconnectVolumeControl(any()); - if (Looper.myLooper() == null) { - Looper.prepare(); - } + doReturn(CONNECTION_POLICY_ALLOWED) + .when(mDatabaseManager) + .getProfileConnectionPolicy(any(), anyInt()); - TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); + doReturn(BOND_BONDED).when(mAdapterService).getBondState(any()); + doReturn(new ParcelUuid[] {BluetoothUuid.VOLUME_CONTROL}) + .when(mAdapterService) + .getRemoteUuids(any(BluetoothDevice.class)); - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mAttributionSource = mAdapter.getAttributionSource(); + doReturn(mCsipService).when(mServiceFactory).getCsipSetCoordinatorService(); + doReturn(mLeAudioService).when(mServiceFactory).getLeAudioService(); + doReturn(mBassClientService).when(mServiceFactory).getBassClientService(); doReturn(MEDIA_MIN_VOL) .when(mAudioManager) @@ -132,432 +155,243 @@ public class VolumeControlServiceTest { doReturn(CALL_MAX_VOL) .when(mAudioManager) .getStreamMaxVolume(eq(AudioManager.STREAM_VOICE_CALL)); + TestUtils.mockGetSystemService( + mAdapterService, Context.AUDIO_SERVICE, AudioManager.class, mAudioManager); + + mInOrder = inOrder(mAdapterService); + mLooper = new TestLooper(); - VolumeControlNativeInterface.setInstance(mNativeInterface); - mService = new VolumeControlService(mTargetContext); - mService.start(); + mAttributionSource = mAdapter.getAttributionSource(); + mService = new VolumeControlService(mAdapterService, mLooper.getLooper(), mNativeInterface); mService.setAvailable(true); - mService.mAudioManager = mAudioManager; mService.mFactory = mServiceFactory; - mServiceBinder = (VolumeControlService.BluetoothVolumeControlBinder) mService.initBinder(); - - doReturn(mCsipService).when(mServiceFactory).getCsipSetCoordinatorService(); - doReturn(mLeAudioService).when(mServiceFactory).getLeAudioService(); - doReturn(mBassClientService).when(mServiceFactory).getBassClientService(); - - // Override the timeout value to speed up the test - VolumeControlStateMachine.sConnectTimeoutMs = TIMEOUT_MS; // 1s - - // Set up the Connection State Changed receiver - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction(BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED); + mBinder = (VolumeControlService.BluetoothVolumeControlBinder) mService.initBinder(); + } - mVolumeControlIntentReceiver = new VolumeControlIntentReceiver(); - mTargetContext.registerReceiver(mVolumeControlIntentReceiver, filter); + @After + public void tearDown() { + assertThat(mLooper.nextMessage()).isNull(); + mService.stop(); + mLooper.dispatchAll(); + assertThat(VolumeControlService.getVolumeControlService()).isNull(); + } - // Get a device for testing - mDevice = TestUtils.getTestDevice(mAdapter, 0); - mDeviceTwo = TestUtils.getTestDevice(mAdapter, 1); - mDeviceQueueMap = new HashMap<>(); - mDeviceQueueMap.put(mDevice, new LinkedBlockingQueue<>()); - mDeviceQueueMap.put(mDeviceTwo, new LinkedBlockingQueue<>()); - doReturn(BluetoothDevice.BOND_BONDED) - .when(mAdapterService) - .getBondState(any(BluetoothDevice.class)); - doReturn(new ParcelUuid[] {BluetoothUuid.VOLUME_CONTROL}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); + @Test + public void getVolumeControlService() { + assertThat(VolumeControlService.getVolumeControlService()).isEqualTo(mService); } - @After - public void tearDown() throws Exception { - if (mService == null) { - return; + @Test + public void getConnectionPolicy() { + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.getConnectionPolicy(mDevice)).isEqualTo(policy); } - - mService.stop(); - VolumeControlNativeInterface.setInstance(null); - mTargetContext.unregisterReceiver(mVolumeControlIntentReceiver); - mDeviceQueueMap.clear(); - TestUtils.clearAdapterService(mAdapterService); - reset(mAudioManager); } - private class VolumeControlIntentReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - try { - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - Assert.assertNotNull(device); - LinkedBlockingQueue queue = mDeviceQueueMap.get(device); - Assert.assertNotNull(queue); - queue.put(intent); - } catch (InterruptedException e) { - Assert.fail("Cannot add Intent to the Connection State queue: " + e.getMessage()); + @Test + public void canConnect_whenNotBonded_returnFalse() { + int badPolicyValue = 1024; + int badBondState = 42; + for (int bondState : List.of(BOND_NONE, BOND_BONDING, badBondState)) { + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED, + badPolicyValue)) { + doReturn(bondState).when(mAdapterService).getBondState(any()); + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mDevice)).isEqualTo(false); } } } - private void verifyConnectionStateIntent( - int timeoutMs, BluetoothDevice device, int newState, int prevState) { - Intent intent = TestUtils.waitForIntent(timeoutMs, mDeviceQueueMap.get(device)); - Assert.assertNotNull(intent); - Assert.assertEquals( - BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED, intent.getAction()); - Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(newState, intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertEquals( - prevState, intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)); - } + @Test + public void canConnect_whenBonded() { + int badPolicyValue = 1024; + doReturn(BOND_BONDED).when(mAdapterService).getBondState(any()); - private void verifyNoConnectionStateIntent(int timeoutMs, BluetoothDevice device) { - Intent intent = TestUtils.waitForNoIntent(timeoutMs, mDeviceQueueMap.get(device)); - Assert.assertNull(intent); + for (int policy : List.of(CONNECTION_POLICY_FORBIDDEN, badPolicyValue)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mDevice)).isEqualTo(false); + } + for (int policy : List.of(CONNECTION_POLICY_UNKNOWN, CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mDevice)).isEqualTo(true); + } } - /** Test getting VolumeControl Service: getVolumeControlService() */ @Test - public void testGetVolumeControlService() { - Assert.assertEquals(mService, VolumeControlService.getVolumeControlService()); + public void connectToDevice_whenUuidIsMissing_returnFalse() { + // Return No UUID + doReturn(new ParcelUuid[] {}) + .when(mAdapterService) + .getRemoteUuids(any(BluetoothDevice.class)); + + assertThat(mService.connect(mDevice)).isFalse(); } - /** Test stop VolumeControl Service */ @Test - public void testStopVolumeControlService() throws Exception { - // Prepare: connect - connectDevice(mDevice); - // VolumeControl Service is already running: test stop(). - // Note: must be done on the main thread - InstrumentationRegistry.getInstrumentation().runOnMainSync(mService::stop); - // Try to restart the service. Note: must be done on the main thread - InstrumentationRegistry.getInstrumentation().runOnMainSync(mService::start); + public void disconnect_whenConnecting_isDisconnectedWithBroadcast() { + assertThat(mService.connect(mDevice)).isTrue(); + mLooper.dispatchAll(); + verifyConnectionStateIntent(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + + assertThat(mService.disconnect(mDevice)).isTrue(); + mLooper.dispatchAll(); + verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTING); } - /** Test get/set policy for BluetoothDevice */ @Test - public void testGetSetPolicy() { - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - Assert.assertEquals( - "Initial device policy", - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - mService.getConnectionPolicy(mDevice)); - - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); + public void connectToDevice_whenPolicyForbid_returnFalse() { when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - Assert.assertEquals( - "Setting device policy to POLICY_FORBIDDEN", - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - mService.getConnectionPolicy(mDevice)); + .thenReturn(CONNECTION_POLICY_FORBIDDEN); - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - Assert.assertEquals( - "Setting device policy to POLICY_ALLOWED", - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - mService.getConnectionPolicy(mDevice)); + assertThat(mService.connect(mDevice)).isFalse(); } - /** Test if getProfileConnectionPolicy works after the service is stopped. */ @Test - public void testGetPolicyAfterStopped() throws Exception { - mService.stop(); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - int policy = mServiceBinder.getConnectionPolicy(mDevice, mAttributionSource); - Assert.assertEquals( - "Initial device policy", BluetoothProfile.CONNECTION_POLICY_UNKNOWN, policy); + public void outgoingConnect_whenTimeOut_isDisconnected() { + assertThat(mService.connect(mDevice)).isTrue(); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + + mLooper.moveTimeForward(VolumeControlStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTING); } - /** Test okToConnect method using various test cases */ @Test - public void testOkToConnect() { - int badPolicyValue = 1024; - int badBondState = 42; - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testOkToConnectCase(mDevice, BluetoothDevice.BOND_NONE, badPolicyValue, false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testOkToConnectCase(mDevice, BluetoothDevice.BOND_BONDING, badPolicyValue, false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - true); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - true); - testOkToConnectCase(mDevice, BluetoothDevice.BOND_BONDED, badPolicyValue, false); - testOkToConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, false); - testOkToConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, false); - testOkToConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_ALLOWED, false); - testOkToConnectCase(mDevice, badBondState, badPolicyValue, false); + public void incomingConnecting_whenNoDevice_createStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getDevices()).contains(mDevice); } - /** - * Test that an outgoing connection to device that does not have Volume Control UUID is rejected - */ @Test - public void testOutgoingConnectMissingVolumeControlUuid() { - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - // Return No UUID - doReturn(new ParcelUuid[] {}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); + public void incomingDisconnect_whenConnectingDevice_keepStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); - // Send a connect request - Assert.assertFalse("Connect expected to fail", mService.connect(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mService.getDevices()).contains(mDevice); } - /** Test that an outgoing connection to device that have Volume Control UUID is successful */ @Test - public void testOutgoingConnectDisconnectExistingVolumeControlUuid() throws Exception { - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - // Return Volume Control UUID - doReturn(new ParcelUuid[] {BluetoothUuid.VOLUME_CONTROL}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - - // Send a connect request - Assert.assertTrue("Connect expected to succeed", mService.connect(mDevice)); - - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - TIMEOUT_MS, - mDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - - // Send a disconnect request - Assert.assertTrue("Disconnect expected to succeed", mService.disconnect(mDevice)); - - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - TIMEOUT_MS, - mDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); + public void incomingConnect_whenNoDevice_createStateMachine() { + // Theoretically impossible case + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); } - /** Test that an outgoing connection to device with POLICY_FORBIDDEN is rejected */ @Test - public void testOutgoingConnectPolicyForbidden() { - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); + public void incomingDisconnect_whenConnectedDevice_keepStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); - // Set the device policy to POLICY_FORBIDDEN so connect() should fail - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTED, STATE_CONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); + assertThat(mService.getDevices()).contains(mDevice); + } - // Send a connect request - Assert.assertFalse("Connect expected to fail", mService.connect(mDevice)); + @Test + public void incomingDisconnecting_whenNoDevice_noStateMachine() { + generateUnexpectedConnectionMessageFromNative(mDevice, STATE_DISCONNECTING); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); + assertThat(mService.getDevices()).doesNotContain(mDevice); } - /** Test that an outgoing connection times out */ @Test - public void testOutgoingConnectTimeout() throws Exception { - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); + public void incomingDisconnect_whenNoDevice_noStateMachine() { + generateUnexpectedConnectionMessageFromNative(mDevice, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); + assertThat(mService.getDevices()).doesNotContain(mDevice); + } - // Send a connect request - Assert.assertTrue("Connect failed", mService.connect(mDevice)); + @Test + public void unBondDevice_whenConnecting_keepStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTING); + assertThat(mService.getDevices()).contains(mDevice); + + mService.bondStateChanged(mDevice, BOND_NONE); + assertThat(mService.getDevices()).contains(mDevice); + assertThat(mLooper.nextMessage().what) + .isEqualTo(VolumeControlStateMachine.MESSAGE_DISCONNECT); + } - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - TIMEOUT_MS, - mDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(mDevice)); - - // Verify the connection state broadcast, and that we are in Disconnected state - verifyConnectionStateIntent( - VolumeControlStateMachine.sConnectTimeoutMs * 2, - mDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); + @Test + public void unBondDevice_whenConnected_keepStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_CONNECTING); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); + + mService.bondStateChanged(mDevice, BOND_NONE); + assertThat(mService.getDevices()).contains(mDevice); + assertThat(mLooper.nextMessage().what) + .isEqualTo(VolumeControlStateMachine.MESSAGE_DISCONNECT); + } - int state = mServiceBinder.getConnectionState(mDevice, mAttributionSource); - Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, state); + @Test + public void unBondDevice_whenDisconnecting_keepStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTING, STATE_CONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTING); + assertThat(mService.getDevices()).contains(mDevice); + + mService.bondStateChanged(mDevice, BOND_NONE); + assertThat(mService.getDevices()).contains(mDevice); + assertThat(mLooper.nextMessage().what) + .isEqualTo(VolumeControlStateMachine.MESSAGE_DISCONNECT); } - /** - * Test that only CONNECTION_STATE_CONNECTED or CONNECTION_STATE_CONNECTING Volume Control stack - * events will create a state machine. - */ @Test - public void testCreateStateMachineStackEvents() { - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - // stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - mService.bondStateChanged(mDevice, BluetoothDevice.BOND_NONE); - Assert.assertFalse(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_CONNECTED - state machine should be created - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - mService.bondStateChanged(mDevice, BluetoothDevice.BOND_NONE); - Assert.assertFalse(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_DISCONNECTING - state machine should not be created - generateUnexpectedConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_DISCONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mService.getConnectionState(mDevice)); - Assert.assertFalse(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_DISCONNECTED - state machine should not be created - generateUnexpectedConnectionMessageFromNative(mDevice, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mService.getConnectionState(mDevice)); - Assert.assertFalse(mService.getDevices().contains(mDevice)); + public void unBondDevice_whenDisconnected_removeStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTING, STATE_CONNECTED); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); + assertThat(mService.getDevices()).contains(mDevice); + + mService.bondStateChanged(mDevice, BOND_NONE); + mLooper.dispatchAll(); + assertThat(mService.getDevices()).doesNotContain(mDevice); } - /** - * Test that a CONNECTION_STATE_DISCONNECTED Volume Control stack event will remove the state - * machine only if the device is unbond. - */ @Test - public void testDeleteStateMachineDisconnectEvents() { - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - // stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_CONNECTING - state machine remains - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - - // device bond state marked as unbond - state machine is not removed - doReturn(BluetoothDevice.BOND_NONE) - .when(mAdapterService) - .getBondState(any(BluetoothDevice.class)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - - // stack event: CONNECTION_STATE_DISCONNECTED - state machine is removed - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mService.getConnectionState(mDevice)); - Assert.assertFalse(mService.getDevices().contains(mDevice)); + public void disconnect_whenBonded_keepStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTING, STATE_CONNECTED); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); + assertThat(mService.getDevices()).contains(mDevice); } - /** Test that various Volume Control stack events will broadcast related states. */ @Test - public void testVolumeControlStackEvents() { - int group_id = -1; - int volume = 6; - int flags = 0; - boolean mute = false; - boolean isAutonomous = false; + public void disconnect_whenUnBonded_removeStateMachine() { + generateConnectionMessageFromNative(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTING, STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); - // Send a message to trigger volume state changed broadcast - generateVolumeStateChanged(mDevice, group_id, volume, flags, mute, isAutonomous); + doReturn(BOND_NONE).when(mAdapterService).getBondState(any()); + mService.bondStateChanged(mDevice, BOND_NONE); + assertThat(mService.getDevices()).contains(mDevice); + + generateConnectionMessageFromNative(mDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_DISCONNECTED); + assertThat(mService.getDevices()).doesNotContain(mDevice); } int getLeAudioVolume(int index, int minIndex, int maxIndex, int streamType) { @@ -591,7 +425,7 @@ public class VolumeControlServiceTest { } @Test - public void testAutonomousVolumeStateChange() { + public void incomingAutonomousVolumeStateChange_isApplied() { // Make device Active now. This will trigger setting volume to AF when(mLeAudioService.getActiveGroupId()).thenReturn(TEST_GROUP_ID); @@ -602,9 +436,8 @@ public class VolumeControlServiceTest { testVolumeCalculations(AudioManager.STREAM_MUSIC, MEDIA_MIN_VOL, MEDIA_MAX_VOL); } - /** Test if autonomous Mute/Unmute propagates the event to audio manager. */ @Test - public void testAutonomousMuteUnmute() { + public void incomingAutonomousMuteUnmute_isApplied() { int streamType = AudioManager.STREAM_MUSIC; int streamVol = getLeAudioVolume(19, MEDIA_MIN_VOL, MEDIA_MAX_VOL, streamType); @@ -626,43 +459,41 @@ public class VolumeControlServiceTest { .adjustStreamVolume(eq(streamType), eq(AudioManager.ADJUST_UNMUTE), anyInt()); } - /** Test Volume Control cache. */ @Test - public void testVolumeCache() throws Exception { + public void volumeCache() { int groupId = 1; int volume = 6; - Assert.assertEquals(-1, mService.getGroupVolume(groupId)); - mServiceBinder.setGroupVolume(groupId, volume, mAttributionSource); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(-1); + mBinder.setGroupVolume(groupId, volume, mAttributionSource); - int groupVolume = mServiceBinder.getGroupVolume(groupId, mAttributionSource); - Assert.assertEquals(volume, groupVolume); + int groupVolume = mBinder.getGroupVolume(groupId, mAttributionSource); + assertThat(groupVolume).isEqualTo(volume); volume = 10; // Send autonomous volume change. generateVolumeStateChanged(null, groupId, volume, 0, false, true); - Assert.assertEquals(volume, mService.getGroupVolume(groupId)); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(volume); } - /** Test Active Group change */ @Test - public void testActiveGroupChange() throws Exception { + public void activeGroupChange() { int groupId_1 = 1; int volume_groupId_1 = 6; int groupId_2 = 2; int volume_groupId_2 = 20; - Assert.assertEquals(-1, mService.getGroupVolume(groupId_1)); - Assert.assertEquals(-1, mService.getGroupVolume(groupId_2)); - mServiceBinder.setGroupVolume(groupId_1, volume_groupId_1, mAttributionSource); + assertThat(mService.getGroupVolume(groupId_1)).isEqualTo(-1); + assertThat(mService.getGroupVolume(groupId_2)).isEqualTo(-1); + mBinder.setGroupVolume(groupId_1, volume_groupId_1, mAttributionSource); - mServiceBinder.setGroupVolume(groupId_2, volume_groupId_2, mAttributionSource); + mBinder.setGroupVolume(groupId_2, volume_groupId_2, mAttributionSource); // Make device Active now. This will trigger setting volume to AF when(mLeAudioService.getActiveGroupId()).thenReturn(groupId_1); - mServiceBinder.setGroupActive(groupId_1, true, mAttributionSource); + mBinder.setGroupActive(groupId_1, true, mAttributionSource); // Expected index for STREAM_MUSIC int expectedVol = @@ -671,77 +502,76 @@ public class VolumeControlServiceTest { // Make device Active now. This will trigger setting volume to AF when(mLeAudioService.getActiveGroupId()).thenReturn(groupId_2); - mServiceBinder.setGroupActive(groupId_2, true, mAttributionSource); + mBinder.setGroupActive(groupId_2, true, mAttributionSource); expectedVol = (int) Math.round((double) (volume_groupId_2 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedVol), anyInt()); } - /** Test Volume Control Mute cache. */ @Test - public void testMuteCache() throws Exception { + public void muteCache() { int groupId = 1; int volume = 6; - Assert.assertEquals(false, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isFalse(); // Send autonomous volume change generateVolumeStateChanged(null, groupId, volume, 0, false, true); // Mute - mServiceBinder.muteGroup(groupId, mAttributionSource); - Assert.assertEquals(true, mService.getGroupMute(groupId)); + mBinder.muteGroup(groupId, mAttributionSource); + assertThat(mService.getGroupMute(groupId)).isTrue(); // Make sure the volume is kept even when muted - Assert.assertEquals(volume, mService.getGroupVolume(groupId)); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(volume); // Send autonomous unmute generateVolumeStateChanged(null, groupId, volume, 0, false, true); - Assert.assertEquals(false, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isFalse(); } /** Test Volume Control with muted stream. */ @Test - public void testVolumeChangeWhileMuted() throws Exception { + public void volumeChangeWhileMuted() { int groupId = 1; int volume = 6; - Assert.assertEquals(false, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isFalse(); generateVolumeStateChanged(null, groupId, volume, 0, false, true); // Mute mService.muteGroup(groupId); - Assert.assertEquals(true, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isTrue(); verify(mNativeInterface).muteGroup(eq(groupId)); // Make sure the volume is kept even when muted doReturn(true).when(mAudioManager).isStreamMute(eq(AudioManager.STREAM_MUSIC)); - Assert.assertEquals(volume, mService.getGroupVolume(groupId)); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(volume); // Lower the volume and keep it mute mService.setGroupVolume(groupId, --volume); - Assert.assertEquals(true, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isTrue(); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); - verify(mNativeInterface, times(0)).unmuteGroup(eq(groupId)); + verify(mNativeInterface, never()).unmuteGroup(eq(groupId)); // Don't unmute on consecutive calls either mService.setGroupVolume(groupId, --volume); - Assert.assertEquals(true, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isTrue(); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); - verify(mNativeInterface, times(0)).unmuteGroup(eq(groupId)); + verify(mNativeInterface, never()).unmuteGroup(eq(groupId)); // Raise the volume and unmute volume += 10; // avoid previous volume levels and simplify mock verification doReturn(false).when(mAudioManager).isStreamMute(eq(AudioManager.STREAM_MUSIC)); mService.setGroupVolume(groupId, ++volume); - Assert.assertEquals(false, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isFalse(); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); // Verify the number of unmute calls after the second volume change mService.setGroupVolume(groupId, ++volume); - Assert.assertEquals(false, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isFalse(); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); // Make sure we unmuted only once verify(mNativeInterface).unmuteGroup(eq(groupId)); @@ -750,7 +580,7 @@ public class VolumeControlServiceTest { /** Test if phone will set volume which is read from the buds */ @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_PRIMARY_GROUP_ONLY) - public void testConnectedDeviceWithUserPersistFlagSet() throws Exception { + public void connectedDeviceWithUserPersistFlagSet() { int groupId = 1; int volumeDevice = 56; int volumeDeviceTwo = 100; @@ -762,29 +592,20 @@ public class VolumeControlServiceTest { when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - generateDeviceAvailableMessageFromNative(mDevice, 1); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); when(mBassClientService.getSyncedBroadcastSinks()).thenReturn(new ArrayList<>()); // Group is not active unicast and not active primary broadcast, AF will not be notified generateVolumeStateChanged( mDevice, groupId, volumeDevice, flags, initialMuteState, initialAutonomousFlag); - verify(mAudioManager, times(0)).setStreamVolume(anyInt(), anyInt(), anyInt()); + verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt()); // Make device Active now. This will trigger setting volume to AF when(mLeAudioService.getActiveGroupId()).thenReturn(groupId); - mServiceBinder.setGroupActive(groupId, true, mAttributionSource); + mBinder.setGroupActive(groupId, true, mAttributionSource); int expectedAfVol = (int) Math.round((double) (volumeDevice * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); @@ -792,11 +613,9 @@ public class VolumeControlServiceTest { // Connect second device and read different volume. Expect it will be set to AF and to // another set member generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); // Group is now active, AF will be notified. Native will take care to sync the volume generateVolumeStateChanged( @@ -828,19 +647,10 @@ public class VolumeControlServiceTest { when(mAudioManager.getStreamVolume(anyInt())).thenReturn(streamVolume); when(mAudioManager.getStreamMaxVolume(anyInt())).thenReturn(streamMaxVolume); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - generateDeviceAvailableMessageFromNative(mDevice, 1); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); int expectedAfVol = (int) Math.round((double) streamVolume * BT_LE_AUDIO_MAX_VOL / streamMaxVolume); @@ -853,11 +663,11 @@ public class VolumeControlServiceTest { resetFlag, initialMuteState, initialAutonomousFlag); - verify(mAudioManager, times(0)).setStreamVolume(anyInt(), anyInt(), anyInt()); + verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt()); // Make device Active now. This will trigger setting volume to AF when(mLeAudioService.getActiveGroupId()).thenReturn(groupId); - mServiceBinder.setGroupActive(groupId, true, mAttributionSource); + mBinder.setGroupActive(groupId, true, mAttributionSource); verify(mAudioManager).setStreamVolume(anyInt(), eq(streamVolume), anyInt()); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(expectedAfVol)); @@ -865,11 +675,9 @@ public class VolumeControlServiceTest { // Connect second device and read different volume. Expect it will be set to AF and to // another set member generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); // Group is now active, AF will be notified. Native will take care to sync the volume generateVolumeStateChanged( @@ -886,13 +694,13 @@ public class VolumeControlServiceTest { /** Test if phone will set volume which is read from the buds */ @Test - public void testConnectedDeviceWithResetFlagSetWithNonZeroVolume() throws Exception { + public void connectedDeviceWithResetFlagSetWithNonZeroVolume() { testConnectedDeviceWithResetFlag(56, 100); } /** Test if phone will set volume to buds which has no volume */ @Test - public void testConnectedDeviceWithResetFlagSetWithZeroVolume() throws Exception { + public void connectedDeviceWithResetFlagSetWithZeroVolume() { testConnectedDeviceWithResetFlag(0, 0); } @@ -901,7 +709,7 @@ public class VolumeControlServiceTest { * already changed and cached. */ @Test - public void testLateConnectingDevice() throws Exception { + public void lateConnectingDevice() { int groupId = 1; int groupVolume = 56; @@ -909,29 +717,18 @@ public class VolumeControlServiceTest { when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); mService.setGroupVolume(groupId, groupVolume); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); - verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(groupVolume)); + verify(mNativeInterface, never()).setVolume(eq(mDeviceTwo), eq(groupVolume)); // Verify that second device gets the proper group volume level when connected - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); } @@ -940,7 +737,7 @@ public class VolumeControlServiceTest { * group was already changed and cached. */ @Test - public void testLateDiscoveredGroupMember() throws Exception { + public void lateDiscoveredGroupMember() { int groupId = 1; int groupVolume = 56; @@ -948,29 +745,18 @@ public class VolumeControlServiceTest { when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(-1); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); // Set the group volume mService.setGroupVolume(groupId, groupVolume); // Verify that second device will not get the group volume level if it is not a group member - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); - verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(groupVolume)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); + verify(mNativeInterface, never()).setVolume(eq(mDeviceTwo), eq(groupVolume)); // But gets the volume when it becomes the group member when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); @@ -984,7 +770,7 @@ public class VolumeControlServiceTest { * telephony, thus setting volume level to 0 is considered as muting. */ @Test - public void testMuteLateConnectingDevice() throws Exception { + public void muteLateConnectingDevice() { int groupId = 1; int volume = 100; @@ -992,36 +778,25 @@ public class VolumeControlServiceTest { when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); // Set the initial volume and mute conditions doReturn(true).when(mAudioManager).isStreamMute(anyInt()); mService.setGroupVolume(groupId, volume); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); - verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(volume)); + verify(mNativeInterface, never()).setVolume(eq(mDeviceTwo), eq(volume)); // Check if it was muted verify(mNativeInterface).muteGroup(eq(groupId)); - Assert.assertEquals(true, mService.getGroupMute(groupId)); + assertThat(mService.getGroupMute(groupId)).isTrue(); // Verify that second device gets the proper group volume level when connected - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(volume)); // Check if new device was muted verify(mNativeInterface).mute(eq(mDeviceTwo)); @@ -1033,7 +808,7 @@ public class VolumeControlServiceTest { * than telephony, thus setting volume level to 0 is considered as muting. */ @Test - public void testMuteLateDiscoveredGroupMember() throws Exception { + public void muteLateDiscoveredGroupMember() { int groupId = 1; int volume = 100; @@ -1041,32 +816,21 @@ public class VolumeControlServiceTest { when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(-1); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); // Set the initial volume and mute conditions doReturn(true).when(mAudioManager).isStreamMute(anyInt()); mService.setGroupVolume(groupId, volume); // Verify that second device will not get the group volume level if it is not a group member - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); - verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(volume)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); + verify(mNativeInterface, never()).setVolume(eq(mDeviceTwo), eq(volume)); // Check if it was not muted - verify(mNativeInterface, times(0)).mute(eq(mDeviceTwo)); + verify(mNativeInterface, never()).mute(eq(mDeviceTwo)); // But gets the volume when it becomes the group member when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); @@ -1076,43 +840,40 @@ public class VolumeControlServiceTest { } @Test - public void testServiceBinderGetDevicesMatchingConnectionStates() throws Exception { - List devices = - mServiceBinder.getDevicesMatchingConnectionStates(null, mAttributionSource); - Assert.assertEquals(0, devices.size()); + public void serviceBinderGetDevicesMatchingConnectionStates() { + assertThat(mBinder.getDevicesMatchingConnectionStates(null, mAttributionSource)).isEmpty(); } @Test - public void testServiceBinderSetConnectionPolicy() throws Exception { - Assert.assertTrue( - mServiceBinder.setConnectionPolicy( - mDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, mAttributionSource)); + public void serviceBinderSetConnectionPolicy() { + assertThat( + mBinder.setConnectionPolicy( + mDevice, CONNECTION_POLICY_UNKNOWN, mAttributionSource)) + .isTrue(); verify(mDatabaseManager) .setProfileConnectionPolicy( - mDevice, - BluetoothProfile.VOLUME_CONTROL, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN); + mDevice, BluetoothProfile.VOLUME_CONTROL, CONNECTION_POLICY_UNKNOWN); } @Test - public void testServiceBinderVolumeOffsetMethods() throws Exception { + public void serviceBinderVolumeOffsetMethods() { // Send a message to trigger connection completed generateDeviceAvailableMessageFromNative(mDevice, 2); - Assert.assertTrue(mServiceBinder.isVolumeOffsetAvailable(mDevice, mAttributionSource)); + assertThat(mBinder.isVolumeOffsetAvailable(mDevice, mAttributionSource)).isTrue(); int numberOfInstances = - mServiceBinder.getNumberOfVolumeOffsetInstances(mDevice, mAttributionSource); - Assert.assertEquals(2, numberOfInstances); + mBinder.getNumberOfVolumeOffsetInstances(mDevice, mAttributionSource); + assertThat(numberOfInstances).isEqualTo(2); int id = 1; int volumeOffset = 100; - mServiceBinder.setVolumeOffset(mDevice, id, volumeOffset, mAttributionSource); + mBinder.setVolumeOffset(mDevice, id, volumeOffset, mAttributionSource); verify(mNativeInterface).setExtAudioOutVolumeOffset(mDevice, id, volumeOffset); } @Test - public void testServiceBinderSetDeviceVolumeMethods() throws Exception { + public void serviceBinderSetDeviceVolumeMethods() { int groupId = 1; int groupVolume = 56; int deviceOneVolume = 46; @@ -1122,37 +883,28 @@ public class VolumeControlServiceTest { when(mLeAudioService.getGroupId(mDevice)).thenReturn(groupId); when(mLeAudioService.getGroupId(mDeviceTwo)).thenReturn(groupId); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - generateDeviceAvailableMessageFromNative(mDevice, 1); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); - mServiceBinder.setDeviceVolume(mDevice, groupVolume, true, mAttributionSource); + mBinder.setDeviceVolume(mDevice, groupVolume, true, mAttributionSource); verify(mNativeInterface).setGroupVolume(groupId, groupVolume); - Assert.assertEquals(groupVolume, mService.getGroupVolume(groupId)); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(groupVolume); - mServiceBinder.setDeviceVolume(mDevice, deviceOneVolume, false, mAttributionSource); + mBinder.setDeviceVolume(mDevice, deviceOneVolume, false, mAttributionSource); verify(mNativeInterface).setVolume(mDevice, deviceOneVolume); - Assert.assertEquals(deviceOneVolume, mService.getDeviceVolume(mDevice)); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(deviceOneVolume); Assert.assertNotEquals(deviceOneVolume, mService.getDeviceVolume(mDeviceTwo)); - mServiceBinder.setDeviceVolume(mDeviceTwo, deviceTwoVolume, false, mAttributionSource); + mBinder.setDeviceVolume(mDeviceTwo, deviceTwoVolume, false, mAttributionSource); verify(mNativeInterface).setVolume(mDeviceTwo, deviceTwoVolume); - Assert.assertEquals(deviceTwoVolume, mService.getDeviceVolume(mDeviceTwo)); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(deviceTwoVolume); Assert.assertNotEquals(deviceTwoVolume, mService.getDeviceVolume(mDevice)); } @Test - public void testServiceBinderRegisterUnregisterCallback() throws Exception { + public void serviceBinderRegisterUnregisterCallback() { IBluetoothVolumeControlCallback callback = Mockito.mock(IBluetoothVolumeControlCallback.class); Binder binder = Mockito.mock(Binder.class); @@ -1161,15 +913,15 @@ public class VolumeControlServiceTest { synchronized (mService.mCallbacks) { int size = mService.mCallbacks.getRegisteredCallbackCount(); mService.registerCallback(callback); - Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1); mService.unregisterCallback(callback); - Assert.assertEquals(size, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size); } } @Test - public void testServiceBinderRegisterCallbackWhenDeviceAlreadyConnected() throws Exception { + public void serviceBinderRegisterCallbackWhenDeviceAlreadyConnected() throws Exception { int groupId = 1; int groupVolume = 56; @@ -1177,31 +929,20 @@ public class VolumeControlServiceTest { when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - generateDeviceAvailableMessageFromNative(mDevice, 2); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); mService.setGroupVolume(groupId, groupVolume); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); - verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(groupVolume)); + verify(mNativeInterface, never()).setVolume(eq(mDeviceTwo), eq(groupVolume)); // Verify that second device gets the proper group volume level when connected generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); // Generate events for both devices @@ -1229,7 +970,7 @@ public class VolumeControlServiceTest { synchronized (mService.mCallbacks) { int size = mService.mCallbacks.getRegisteredCallbackCount(); mService.registerCallback(callback); - Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1); } verify(callback).onVolumeOffsetChanged(eq(mDevice), eq(1), eq(100)); @@ -1259,35 +1000,25 @@ public class VolumeControlServiceTest { } @Test - public void testServiceBinderRegisterVolumeChangedCallbackWhenDeviceAlreadyConnected() + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES) + public void serviceBinderRegisterVolumeChangedCallbackWhenDeviceAlreadyConnected() throws Exception { int groupId = 1; int deviceOneVolume = 46; int deviceTwoVolume = 36; - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - generateDeviceAvailableMessageFromNative(mDevice, 1); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); mService.setDeviceVolume(mDevice, deviceOneVolume, false); verify(mNativeInterface).setVolume(eq(mDevice), eq(deviceOneVolume)); // Verify that second device gets the proper group volume level when connected generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); mService.setDeviceVolume(mDeviceTwo, deviceTwoVolume, false); verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(deviceTwoVolume)); @@ -1304,7 +1035,7 @@ public class VolumeControlServiceTest { synchronized (mService.mCallbacks) { int size = mService.mCallbacks.getRegisteredCallbackCount(); mService.registerCallback(callback); - Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1); } verify(callback).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); @@ -1312,34 +1043,23 @@ public class VolumeControlServiceTest { } @Test - public void testServiceBinderTestNotifyNewRegisteredCallback() throws Exception { + public void serviceBinderTestNotifyNewRegisteredCallback() throws Exception { int groupId = 1; int deviceOneVolume = 46; int deviceTwoVolume = 36; - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - generateDeviceAvailableMessageFromNative(mDevice, 1); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); mService.setDeviceVolume(mDevice, deviceOneVolume, false); verify(mNativeInterface).setVolume(eq(mDevice), eq(deviceOneVolume)); // Verify that second device gets the proper group volume level when connected generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); + generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDeviceTwo); mService.setDeviceVolume(mDeviceTwo, deviceTwoVolume, false); verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(deviceTwoVolume)); @@ -1357,7 +1077,7 @@ public class VolumeControlServiceTest { synchronized (mService.mCallbacks) { size = mService.mCallbacks.getRegisteredCallbackCount(); mService.registerCallback(callback); - Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1); } IBluetoothVolumeControlCallback callback_new_client = @@ -1365,47 +1085,47 @@ public class VolumeControlServiceTest { Binder binder_new_client = Mockito.mock(Binder.class); when(callback_new_client.asBinder()).thenReturn(binder_new_client); - mServiceBinder.notifyNewRegisteredCallback(callback_new_client, mAttributionSource); + mLooper.startAutoDispatch(); + mBinder.notifyNewRegisteredCallback(callback_new_client, mAttributionSource); + mLooper.stopAutoDispatch(); + synchronized (mService.mCallbacks) { - Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1); } // This shall be done only once after mService.registerCallback verify(callback).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); verify(callback).onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); - // This shall be done only once after mServiceBinder.updateNewRegisteredCallback + // This shall be done only once after mBinder.updateNewRegisteredCallback verify(callback_new_client).onDeviceVolumeChanged(eq(mDevice), eq(deviceOneVolume)); verify(callback_new_client).onDeviceVolumeChanged(eq(mDeviceTwo), eq(deviceTwoVolume)); } @Test - public void testServiceBinderMuteMethods() throws Exception { - mServiceBinder.mute(mDevice, mAttributionSource); + public void serviceBinderMuteMethods() { + mBinder.mute(mDevice, mAttributionSource); verify(mNativeInterface).mute(mDevice); - mServiceBinder.unmute(mDevice, mAttributionSource); + mBinder.unmute(mDevice, mAttributionSource); verify(mNativeInterface).unmute(mDevice); int groupId = 1; - mServiceBinder.muteGroup(groupId, mAttributionSource); + mBinder.muteGroup(groupId, mAttributionSource); verify(mNativeInterface).muteGroup(groupId); - mServiceBinder.unmuteGroup(groupId, mAttributionSource); + mBinder.unmuteGroup(groupId, mAttributionSource); verify(mNativeInterface).unmuteGroup(groupId); } @Test - public void testDump_doesNotCrash() throws Exception { - connectDevice(mDevice); - + public void dump_doesNotCrash() { StringBuilder sb = new StringBuilder(); mService.dump(sb); } - /** Test Volume Control changed callback. */ @Test - public void testVolumeControlChangedCallback() throws Exception { + public void volumeControlChangedCallback() throws Exception { int groupId = 1; int groupVolume = 56; int deviceOneVolume = 46; @@ -1417,7 +1137,7 @@ public class VolumeControlServiceTest { // Send a message to trigger connection completed generateDeviceAvailableMessageFromNative(mDevice, 2); - mServiceBinder.setDeviceVolume(mDevice, groupVolume, true, mAttributionSource); + mBinder.setDeviceVolume(mDevice, groupVolume, true, mAttributionSource); verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); // Register callback and verify it is called with known devices @@ -1429,7 +1149,7 @@ public class VolumeControlServiceTest { synchronized (mService.mCallbacks) { int size = mService.mCallbacks.getRegisteredCallbackCount(); mService.registerCallback(callback); - Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1); } when(mLeAudioService.getGroupDevices(groupId)) @@ -1451,7 +1171,7 @@ public class VolumeControlServiceTest { /** Test Volume Control changed for broadcast primary group. */ @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_PRIMARY_GROUP_ONLY) - public void testVolumeControlChangedForBroadcastPrimaryGroup() throws Exception { + public void volumeControlChangedForBroadcastPrimaryGroup() { int groupId = 1; int groupVolume = 30; @@ -1461,19 +1181,10 @@ public class VolumeControlServiceTest { when(mAudioManager.getStreamVolume(anyInt())).thenReturn(groupVolume); - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - generateDeviceAvailableMessageFromNative(mDevice, 1); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); + generateConnectionMessageFromNative(mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice)).isEqualTo(STATE_CONNECTED); + assertThat(mService.getDevices()).contains(mDevice); // Make active group as null and broadcast active when(mLeAudioService.getActiveGroupId()).thenReturn(LE_AUDIO_GROUP_ID_INVALID); @@ -1481,7 +1192,7 @@ public class VolumeControlServiceTest { // Group is broadcast primary group, AF will not be notified generateVolumeStateChanged(null, groupId, groupVolume, 0, false, true); - verify(mAudioManager, times(0)).setStreamVolume(anyInt(), anyInt(), anyInt()); + verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt()); // Make active group as null and broadcast active when(mLeAudioService.getActiveGroupId()).thenReturn(LE_AUDIO_GROUP_ID_INVALID); @@ -1496,55 +1207,6 @@ public class VolumeControlServiceTest { verify(mAudioManager).setStreamVolume(anyInt(), anyInt(), anyInt()); } - private void connectDevice(BluetoothDevice device) throws Exception { - VolumeControlStackEvent connCompletedEvent; - - List prevConnectedDevices = mService.getConnectedDevices(); - - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(device); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(device); - - // Send a connect request - Assert.assertTrue("Connect failed", mService.connect(device)); - - // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - TIMEOUT_MS, - device, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(device)); - - // Send a message to trigger connection completed - connCompletedEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = device; - connCompletedEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(connCompletedEvent); - - // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - TIMEOUT_MS, - device, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(device)); - - // Verify that the device is in the list of connected devices - List connectedDevices = - mServiceBinder.getConnectedDevices(mAttributionSource); - Assert.assertTrue(connectedDevices.contains(device)); - // Verify the list of previously connected devices - for (BluetoothDevice prevDevice : prevConnectedDevices) { - Assert.assertTrue(connectedDevices.contains(prevDevice)); - } - } - private void generateConnectionMessageFromNative( BluetoothDevice device, int newConnectionState, int oldConnectionState) { VolumeControlStackEvent stackEvent = @@ -1553,8 +1215,9 @@ public class VolumeControlServiceTest { stackEvent.device = device; stackEvent.valueInt1 = newConnectionState; mService.messageFromNative(stackEvent); - // Verify the connection state broadcast - verifyConnectionStateIntent(TIMEOUT_MS, device, newConnectionState, oldConnectionState); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(device, newConnectionState, oldConnectionState); } private void generateUnexpectedConnectionMessageFromNative( @@ -1565,8 +1228,9 @@ public class VolumeControlServiceTest { stackEvent.device = device; stackEvent.valueInt1 = newConnectionState; mService.messageFromNative(stackEvent); - // Verify the connection state broadcast - verifyNoConnectionStateIntent(TIMEOUT_MS, device); + mLooper.dispatchAll(); + + mInOrder.verify(mAdapterService, never()).sendBroadcast(any(), any()); } private void generateDeviceAvailableMessageFromNative( @@ -1634,20 +1298,18 @@ public class VolumeControlServiceTest { mService.messageFromNative(event); } - /** - * Helper function to test okToConnect() method - * - * @param device test device - * @param bondState bond state value, could be invalid - * @param policy value, could be invalid - * @param expected expected result from okToConnect() - */ - private void testOkToConnectCase( - BluetoothDevice device, int bondState, int policy, boolean expected) { - doReturn(bondState).when(mAdapterService).getBondState(device); - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.VOLUME_CONTROL)) - .thenReturn(policy); - Assert.assertEquals(expected, mService.okToConnect(device)); + @SafeVarargs + private void verifyIntentSent(Matcher... matchers) { + mInOrder.verify(mAdapterService) + .sendBroadcast(MockitoHamcrest.argThat(AllOf.allOf(matchers)), any()); + } + + private void verifyConnectionStateIntent(BluetoothDevice device, int newState, int prevState) { + verifyIntentSent( + hasAction(BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(BluetoothProfile.EXTRA_STATE, newState), + hasExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState)); + assertThat(mService.getConnectionState(device)).isEqualTo(newState); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java index 11c59e1425a..c7cca51983d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java @@ -17,412 +17,238 @@ package com.android.bluetooth.vc; -import static org.mockito.Mockito.after; +import static android.bluetooth.BluetoothProfile.EXTRA_PREVIOUS_STATE; +import static android.bluetooth.BluetoothProfile.EXTRA_STATE; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; +import static android.bluetooth.BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED; + +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; + +import static com.android.bluetooth.vc.VolumeControlStateMachine.MESSAGE_CONNECT; +import static com.android.bluetooth.vc.VolumeControlStateMachine.MESSAGE_CONNECT_TIMEOUT; +import static com.android.bluetooth.vc.VolumeControlStateMachine.MESSAGE_DISCONNECT; +import static com.android.bluetooth.vc.VolumeControlStateMachine.MESSAGE_STACK_EVENT; + +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; import android.content.Intent; -import android.os.HandlerThread; -import android.os.Message; +import android.os.test.TestLooper; 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.btservice.AdapterService; -import org.hamcrest.core.IsInstanceOf; -import org.junit.After; -import org.junit.Assert; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; 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.Mockito; +import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) public class VolumeControlStateMachineTest { - private BluetoothAdapter mAdapter; - private HandlerThread mHandlerThread = null; - private VolumeControlStateMachine mVolumeControlStateMachine; - private BluetoothDevice mTestDevice; - private static final int TIMEOUT_MS = 1000; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock private AdapterService mAdapterService; - @Mock private VolumeControlService mVolumeControlService; - @Mock private VolumeControlNativeInterface mVolumeControlNativeInterface; + @Mock private VolumeControlService mService; + @Mock private VolumeControlNativeInterface mNativeInterface; - boolean mIsAdapterServiceSet; + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 39); + + private VolumeControlStateMachine mStateMachine; + private InOrder mInOrder; + private TestLooper mLooper; @Before - public void setUp() throws Exception { - InstrumentationRegistry.getInstrumentation() - .getUiAutomation() - .adoptShellPermissionIdentity(); - TestUtils.setAdapterService(mAdapterService); - - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mIsAdapterServiceSet = true; - - // Get a device for testing - mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); - - // Set up thread and looper - mHandlerThread = new HandlerThread("VolumeControlStateMachineTestHandlerThread"); - mHandlerThread.start(); - mVolumeControlStateMachine = - new VolumeControlStateMachine( - mTestDevice, - mVolumeControlService, - mVolumeControlNativeInterface, - mHandlerThread.getLooper()); - // Override the timeout value to speed up the test - mVolumeControlStateMachine.sConnectTimeoutMs = 1000; // 1s - mVolumeControlStateMachine.start(); - } + public void setUp() { + doReturn(true).when(mService).okToConnect(any()); - @After - public void tearDown() throws Exception { - if (mHandlerThread != null) { - mHandlerThread.quit(); - } - if (mIsAdapterServiceSet) { - TestUtils.clearAdapterService(mAdapterService); - } - } + doReturn(true).when(mNativeInterface).connectVolumeControl(any()); + doReturn(true).when(mNativeInterface).disconnectVolumeControl(any()); - /** Test that default state is disconnected */ - @Test - public void testDefaultDisconnectedState() { - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mVolumeControlStateMachine.getConnectionState()); + mInOrder = inOrder(mService); + mLooper = new TestLooper(); + + mStateMachine = + new VolumeControlStateMachine( + mService, mDevice, mNativeInterface, mLooper.getLooper()); + mStateMachine.start(); } - /** - * Allow/disallow connection to any device. - * - * @param allow if true, connection is allowed - */ - private void allowConnection(boolean allow) { - doReturn(allow).when(mVolumeControlService).okToConnect(any(BluetoothDevice.class)); + @Test + public void initialState_isDisconnected() { + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } - /** Test that an incoming connection with policy forbidding connection is rejected */ @Test - public void testIncomingPolicyReject() { - allowConnection(false); + public void incomingConnect_whenNotOkToConnect_isRejected() { + doReturn(false).when(mService).okToConnect(any()); // Inject an event for when incoming connection is requested VolumeControlStackEvent connStCh = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTED; - mVolumeControlStateMachine.sendMessage(VolumeControlStateMachine.STACK_EVENT, connStCh); - - // Verify that no connection state broadcast is executed - verify(mVolumeControlService, after(TIMEOUT_MS).never()) - .sendBroadcast(any(Intent.class), anyString()); - // Check that we are in Disconnected state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Disconnected.class)); + connStCh.device = mDevice; + connStCh.valueInt1 = STATE_CONNECTED; + sendAndDispatchMessage(MESSAGE_STACK_EVENT, connStCh); + + verify(mService, never()).sendBroadcast(any(Intent.class), anyString()); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Disconnected.class); } - /** Test that an incoming connection with policy allowing connection is accepted */ @Test - public void testIncomingPolicyAccept() { - allowConnection(true); + public void incomingConnect_whenOkToConnect_isConnected() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Connecting.class); + + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Connected.class); + } - // Inject an event for when incoming connection is requested - VolumeControlStackEvent connStCh = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTING; - mVolumeControlStateMachine.sendMessage(VolumeControlStateMachine.STACK_EVENT, connStCh); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mVolumeControlService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Connecting.class)); - - // Send a message to trigger connection completed - VolumeControlStackEvent connCompletedEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mTestDevice; - connCompletedEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTED; - mVolumeControlStateMachine.sendMessage( - VolumeControlStateMachine.STACK_EVENT, connCompletedEvent); - - // Verify that the expected number of broadcasts are executed: - // - two calls to broadcastConnectionState(): Disconnected -> Connecting -> Connected - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mVolumeControlService, timeout(TIMEOUT_MS).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString()); - // Check that we are in Connected state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Connected.class)); + @Test + public void outgoingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { + sendAndDispatchMessage(MESSAGE_CONNECT, mDevice); + verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Connecting.class); + + mLooper.moveTimeForward(VolumeControlStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Disconnected.class); + + verify(mNativeInterface).disconnectVolumeControl(eq(mDevice)); } - /** Test that an outgoing connection times out */ @Test - public void testOutgoingTimeout() { - allowConnection(true); - doReturn(true) - .when(mVolumeControlNativeInterface) - .connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true) - .when(mVolumeControlNativeInterface) - .disconnectVolumeControl(any(BluetoothDevice.class)); - - // Send a connect request - mVolumeControlStateMachine.sendMessage(VolumeControlStateMachine.CONNECT, mTestDevice); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mVolumeControlService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Connecting.class)); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify( - mVolumeControlService, - timeout(VolumeControlStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString()); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Disconnected state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Disconnected.class)); - verify(mVolumeControlNativeInterface).disconnectVolumeControl(eq(mTestDevice)); + public void incomingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Connecting.class); + + mLooper.moveTimeForward(VolumeControlStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Disconnected.class); + verify(mNativeInterface).disconnectVolumeControl(eq(mDevice)); } - /** Test that an incoming connection times out */ @Test - public void testIncomingTimeout() { - allowConnection(true); - doReturn(true) - .when(mVolumeControlNativeInterface) - .connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true) - .when(mVolumeControlNativeInterface) - .disconnectVolumeControl(any(BluetoothDevice.class)); + public void disconnect_whenDisconnected_isDisconnectedWithoutBroadcast() { + sendAndDispatchMessage(MESSAGE_DISCONNECT); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(VolumeControlStateMachine.Disconnected.class); + verify(mService, never()).sendBroadcast(any(), any()); + } - // Inject an event for when incoming connection is requested - VolumeControlStackEvent connStCh = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTING; - mVolumeControlStateMachine.sendMessage(VolumeControlStateMachine.STACK_EVENT, connStCh); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mVolumeControlService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Connecting.class)); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify( - mVolumeControlService, - timeout(VolumeControlStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString()); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Disconnected state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Disconnected.class)); - verify(mVolumeControlNativeInterface).disconnectVolumeControl(eq(mTestDevice)); + @Test + public void disconnect_whenConnecting_isDisconnectedWithBroadcast() { + sendAndDispatchMessage(MESSAGE_CONNECT); + verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED); + sendAndDispatchMessage(MESSAGE_CONNECT_TIMEOUT); + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } @Test - public void testStatesChangesWithMessages() { - allowConnection(true); - doReturn(true) - .when(mVolumeControlNativeInterface) - .connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true) - .when(mVolumeControlNativeInterface) - .disconnectVolumeControl(any(BluetoothDevice.class)); - - // Check that we are in Disconnected state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Disconnected.class)); - - mVolumeControlStateMachine.sendMessage(mVolumeControlStateMachine.DISCONNECT); - // Check that we are in Disconnected state - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(VolumeControlStateMachine.Disconnected.class)); - - // disconnected -> connecting - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage(mVolumeControlStateMachine.CONNECT), - VolumeControlStateMachine.Connecting.class); - // connecting -> disconnected - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage(VolumeControlStateMachine.CONNECT_TIMEOUT), - VolumeControlStateMachine.Disconnected.class); - - // disconnected -> connecting - VolumeControlStackEvent stackEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTING; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - mVolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Connecting.class); - - // connecting -> disconnected - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage(mVolumeControlStateMachine.DISCONNECT), - VolumeControlStateMachine.Disconnected.class); - - // disconnected -> connecting - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage(mVolumeControlStateMachine.CONNECT), - VolumeControlStateMachine.Connecting.class); - // connecting -> disconnecting - stackEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTING; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - mVolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Disconnecting.class); - // disconnecting -> connecting - stackEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTING; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - mVolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Connecting.class); - // connecting -> connected - stackEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTED; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - mVolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Connected.class); - // connected -> disconnecting - stackEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTING; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - mVolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Disconnecting.class); - // disconnecting -> disconnected - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage(VolumeControlStateMachine.CONNECT_TIMEOUT), - VolumeControlStateMachine.Disconnected.class); - - // disconnected -> connected - stackEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTED; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - mVolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Connected.class); - // connected -> disconnected - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage(mVolumeControlStateMachine.DISCONNECT), - VolumeControlStateMachine.Disconnecting.class); - - // disconnecting -> connected - stackEvent = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_CONNECTED; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - mVolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Connected.class); - // connected -> disconnected - stackEvent = + public void disconnect_whenIncomingConnecting_isDisconnectedWithBroadcast() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + sendAndDispatchMessage(MESSAGE_DISCONNECT); + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); + } + + @Test + public void timeout_whenDisconnecting_isDisconnected() { + sendAndDispatchMessage(MESSAGE_CONNECT); + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTING); + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTING); + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTED); + sendAndDispatchMessage(MESSAGE_CONNECT_TIMEOUT); + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); + } + + @Test + public void incomingConnect_whenDisconnected_isConnected() { + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTED); + } + + @Test + public void incomingConnect_whenDisconnecting_isConnected() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING); + sendAndDispatchMessage(MESSAGE_DISCONNECT); + + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTING); + + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_DISCONNECTING); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTED); + } + + private void sendAndDispatchMessage(int what, Object obj) { + mStateMachine.sendMessage(what, obj); + mLooper.dispatchAll(); + } + + private void sendAndDispatchMessage(int what) { + sendAndDispatchMessage(what, null); + } + + @SafeVarargs + private void verifyIntentSent(Matcher... matchers) { + mInOrder.verify(mService) + .sendBroadcast(MockitoHamcrest.argThat(AllOf.allOf(matchers)), any()); + } + + private void verifyConnectionStateIntent(int newState, int oldState) { + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(EXTRA_STATE, newState), + hasExtra(EXTRA_PREVIOUS_STATE, oldState)); + assertThat(mStateMachine.getConnectionState()).isEqualTo(newState); + } + + private void generateConnectionMessageFromNative(int newState, int oldState) { + VolumeControlStackEvent event = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - stackEvent.device = mTestDevice; - stackEvent.valueInt1 = VolumeControlStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessageAndVerifyTransition( - mVolumeControlStateMachine.obtainMessage( - VolumeControlStateMachine.STACK_EVENT, stackEvent), - VolumeControlStateMachine.Disconnected.class); - } + event.device = mDevice; + event.valueInt1 = newState; - private void sendMessageAndVerifyTransition(Message msg, Class type) { - Mockito.clearInvocations(mVolumeControlService); - mVolumeControlStateMachine.sendMessage(msg); - // Verify that one connection state broadcast is executed - verify(mVolumeControlService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(any(Intent.class), anyString()); - Assert.assertThat( - mVolumeControlStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); + sendAndDispatchMessage(MESSAGE_STACK_EVENT, event); + verifyConnectionStateIntent(newState, oldState); } } diff --git a/system/include/hardware/bt_vc.h b/system/include/hardware/bt_vc.h index 420e91778b5..7d24a075438 100644 --- a/system/include/hardware/bt_vc.h +++ b/system/include/hardware/bt_vc.h @@ -26,6 +26,7 @@ namespace bluetooth { namespace vc { +// Must be kept in sync with BluetoothProfile.java enum class ConnectionState { DISCONNECTED = 0, CONNECTING, CONNECTED, DISCONNECTING }; /* Audio input types */ -- GitLab From 5b5399e6f04703319e64dcc43ffb5d40e3aa11b1 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Fri, 18 Oct 2024 09:12:04 +0000 Subject: [PATCH 373/875] CS: Update defalut parameters Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 369478354 Test: m com.android.btservice Change-Id: Ic7b3c926b4f07111dd0676b03fff7de0843cd0b8 --- system/gd/hci/distance_measurement_manager.cc | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index b5761e7afa3..021fbd81867 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -47,7 +47,7 @@ const ModuleFactory DistanceMeasurementManager::Factory = static constexpr uint16_t kIllegalConnectionHandle = 0xffff; static constexpr uint8_t kTxPowerNotAvailable = 0xfe; static constexpr int8_t kRSSIDropOffAt1M = 41; -static constexpr uint8_t kCsMaxTxPower = 12; // 12 dBm +static constexpr uint8_t kCsMaxTxPower = 10; // 10 dBm static constexpr CsSyncAntennaSelection kCsSyncAntennaSelection = CsSyncAntennaSelection::ANTENNA_2; static constexpr uint8_t kConfigId = 0x01; // Use 0x01 to create config and enable procedure static constexpr uint8_t kMinMainModeSteps = 0x02; @@ -57,7 +57,7 @@ static constexpr uint8_t kMode0Steps = 0x03; // Maximum number of mode-0 steps to increase success subevent rate static constexpr uint8_t kChannelMapRepetition = 0x01; // No repetition static constexpr uint8_t kCh3cJump = 0x03; // Skip 3 Channels -static constexpr uint16_t kMaxProcedureLen = 0x4E20; // 12.5s +static constexpr uint16_t kMaxProcedureLen = 0x2710; // 6.25s static constexpr uint16_t kMinProcedureInterval = 0x01; static constexpr uint16_t kMaxProcedureInterval = 0xFF; static constexpr uint16_t kMaxProcedureCount = 0x01; @@ -70,6 +70,7 @@ static constexpr uint16_t kMtuForRasData = 507; // 512 - 5 static constexpr uint16_t kRangingCounterMask = 0x0FFF; static constexpr uint8_t kInvalidConfigId = 0xFF; static constexpr uint16_t kDefaultIntervalMs = 1000; // 1s +static constexpr uint8_t kPreferredPeerAntennaValue = 0x01; // Use first ordered antenna element struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { struct CsProcedureData { @@ -590,14 +591,21 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { connection_handle, config_id, CsCreateContext::BOTH_LOCAL_AND_REMOTE_CONTROLLER, CsMainModeType::MODE_2, CsSubModeType::UNUSED, kMinMainModeSteps, kMaxMainModeSteps, kMainModeRepetition, kMode0Steps, CsRole::INITIATOR, - CsConfigRttType::RTT_WITH_128_BIT_RANDOM_SEQUENCE, CsSyncPhy::LE_1M_PHY, - channel_map, kChannelMapRepetition, CsChannelSelectionType::TYPE_3B, - CsCh3cShape::HAT_SHAPE, kCh3cJump), + CsConfigRttType::RTT_AA_COARSE, CsSyncPhy::LE_1M_PHY, channel_map, + kChannelMapRepetition, CsChannelSelectionType::TYPE_3B, CsCh3cShape::HAT_SHAPE, + kCh3cJump), handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); } void send_le_cs_set_procedure_parameters(uint16_t connection_handle, uint8_t config_id) { CsPreferredPeerAntenna preferred_peer_antenna; + preferred_peer_antenna.use_first_ordered_antenna_element_ = kPreferredPeerAntennaValue & 0x01; + preferred_peer_antenna.use_second_ordered_antenna_element_ = + (kPreferredPeerAntennaValue >> 1) & 0x01; + preferred_peer_antenna.use_third_ordered_antenna_element_ = + (kPreferredPeerAntennaValue >> 2) & 0x01; + preferred_peer_antenna.use_fourth_ordered_antenna_element_ = + (kPreferredPeerAntennaValue >> 3) & 0x01; hci_layer_->EnqueueCommand( LeCsSetProcedureParametersBuilder::Create( connection_handle, config_id, kMaxProcedureLen, kMinProcedureInterval, -- GitLab From 14d18d535480f1a1ee4fe66d259c9bf0d971aae9 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Fri, 18 Oct 2024 16:40:56 +0000 Subject: [PATCH 374/875] CS: Update PDL based on core spec 6.0 Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 373755855 Test: m com.android.btservice Change-Id: Ib09f7785dc8deef042cd84b351ab94a5790d28d6 --- system/gd/hci/distance_measurement_manager.cc | 2 +- system/pdl/hci/hci_packets.pdl | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 021fbd81867..d448de62649 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -591,7 +591,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { connection_handle, config_id, CsCreateContext::BOTH_LOCAL_AND_REMOTE_CONTROLLER, CsMainModeType::MODE_2, CsSubModeType::UNUSED, kMinMainModeSteps, kMaxMainModeSteps, kMainModeRepetition, kMode0Steps, CsRole::INITIATOR, - CsConfigRttType::RTT_AA_COARSE, CsSyncPhy::LE_1M_PHY, channel_map, + CsConfigRttType::RTT_AA_ONLY, CsSyncPhy::LE_1M_PHY, channel_map, kChannelMapRepetition, CsChannelSelectionType::TYPE_3B, CsCh3cShape::HAT_SHAPE, kCh3cJump), handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); diff --git a/system/pdl/hci/hci_packets.pdl b/system/pdl/hci/hci_packets.pdl index df7c47db2a2..76673e2aaed 100644 --- a/system/pdl/hci/hci_packets.pdl +++ b/system/pdl/hci/hci_packets.pdl @@ -4943,7 +4943,7 @@ struct CsOptionalCsSyncPhysSupported { } struct CsOptionalSubfeaturesSupported { - companion_signal : 1, + _reserved_ : 1, frequency_actuation_error : 1, channel_selection_algorithm : 1, phase_based_ranging : 1, @@ -5129,7 +5129,7 @@ enum CsRole : 8 { } enum CsConfigRttType : 8 { - RTT_AA_COARSE = 0x00, + RTT_AA_ONLY = 0x00, RTT_WITH_32_BIT_SOUNDING_SEQUENCE = 0x01, RTT_WITH_96_BIT_SOUNDING_SEQUENCE = 0x02, RTT_WITH_32_BIT_RANDOM_SEQUENCE = 0x03, @@ -6879,6 +6879,7 @@ packet LeCsProcedureEnableComplete : LeMetaEvent (subevent_code = LE_CS_PROCEDUR event_interval : 16, procedure_interval : 16, procedure_count : 16, + max_procedure_len : 16, } struct LeCsMode0InitatorData { -- GitLab From 813b6f284798882f219ec2394a6e4295016d4e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 11 Oct 2024 13:34:02 +0000 Subject: [PATCH 375/875] l2cap: Upper tester implementation This upper tester implemetation is dedicated to L2CAP/FOC/BV-04-C and L2CAP/FOC/BV-05-C where it is expected that Android will change in rounds FCS options. As by default Android uses FCS Option 0x01 when needed, but above testcases also verifies different configuration. Therefore there is a need to implement Upper Tester for those test cases To enable Upper tester for test case BV-04 following prop needs to be set to 4 setprop bluetooth.pts.l2cap.foc.bv.test 4 if test case BV-05-C is executed it should be bluetooth.pts.l2cap.foc.bv.test 5 Bug: 371948052 Flag: Exempt, test only behind the define Test: mmm packages/modules/Bluetooth Test: manual PTS testcases Change-Id: I6aadc1792dcc4f75af988ca9945bb439efd21b88 --- system/internal_include/bt_target.h | 5 ++- system/stack/l2cap/l2c_csm.cc | 65 ++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/system/internal_include/bt_target.h b/system/internal_include/bt_target.h index 24e1cb32e0d..a1c1d28bf04 100644 --- a/system/internal_include/bt_target.h +++ b/system/internal_include/bt_target.h @@ -311,7 +311,10 @@ #endif /* Used for conformance testing ONLY: When TRUE lets scriptwrapper overwrite - * info response */ + * info response. + * For testcases L2CAP/FOC/BV-{04,05}-C set property bluetooth.pts.l2cap.foc.bv.test to 4 and + * 5 respectively + */ #ifndef L2CAP_CONFORMANCE_TESTING #define L2CAP_CONFORMANCE_TESTING FALSE #endif diff --git a/system/stack/l2cap/l2c_csm.cc b/system/stack/l2cap/l2c_csm.cc index 1c7021ffc70..0189ee59007 100644 --- a/system/stack/l2cap/l2c_csm.cc +++ b/system/stack/l2cap/l2c_csm.cc @@ -66,6 +66,69 @@ static void l2c_csm_send_connect_rsp(tL2C_CCB* p_ccb) { l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP, NULL); } +#if (L2CAP_CONFORMANCE_TESTING == TRUE) +#include "osi/include/properties.h" + +/* FCS Flag configuration for L2CAP/FOC/BV-04 and L2CAP/FOC/BV-05 + * Upper tester implementation for above two testcases where + * different FCS options need to be used in different steps. + */ + +/* L2CAP.TSp38, table 4.13 */ +static uint8_t pts_fcs_option_bv_04_c[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + +/* L2CAP.TSp38, table 4.68 */ +static uint8_t pts_fcs_option_bv_05_c[] = {0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + +static uint8_t pts_foc_bv_test_id_property; + +static uint8_t pts_get_fcs_option(void) { + static size_t fcs_opt_iter = 0; + uint8_t* fcs_test_options = nullptr; + uint8_t iter_cnt = 0; + + uint8_t test_id = osi_property_get_int32("bluetooth.pts.l2cap.foc.bv.test", 0); + if (pts_foc_bv_test_id_property != test_id) { + pts_foc_bv_test_id_property = test_id; + fcs_opt_iter = 0; + } + + switch (test_id) { + case 4: + log::info("Proceed test L2CAP/FOC/BV-04-C"); + fcs_test_options = &pts_fcs_option_bv_04_c[0]; + iter_cnt = sizeof(pts_fcs_option_bv_04_c); + break; + case 5: + log::info("Proceed test L2CAP/FOC/BV-05-C"); + fcs_test_options = &pts_fcs_option_bv_05_c[0]; + iter_cnt = sizeof(pts_fcs_option_bv_05_c); + break; + default: + log::info("Proceed unknown test"); + return 1; + } + + log::info("fcs_opt_iter: {}, fcs option: {}", fcs_opt_iter, + fcs_opt_iter < iter_cnt ? fcs_test_options[fcs_opt_iter] : -1); + + if (fcs_opt_iter < iter_cnt) { + return fcs_test_options[fcs_opt_iter++]; + } + + log::info("Too many iterations: {}, return fcs = 0x01", fcs_opt_iter); + return 1; +} +#endif + +static uint8_t get_fcs_option(void) { +#if (L2CAP_CONFORMANCE_TESTING == TRUE) + return pts_get_fcs_option(); +#else + return 0x01; +#endif +} + // Send a config request and adjust the state machine static void l2c_csm_send_config_req(tL2C_CCB* p_ccb) { tL2CAP_CFG_INFO config{}; @@ -80,7 +143,7 @@ static void l2c_csm_send_config_req(tL2C_CCB* p_ccb) { /* Later l2cu_process_our_cfg_req() will check if remote supports it, and if not, it will be * cleared as per spec. */ config.fcs_present = true; - config.fcs = 1; + config.fcs = get_fcs_option(); } } p_ccb->our_cfg = config; -- GitLab From 9db247bde5a1d20618b95dad4d7fbb5d009a04c4 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Mon, 21 Oct 2024 02:48:35 +0000 Subject: [PATCH 376/875] Add assumption to test SmsManager.isImsSmsSupported() requires the FEATURE_TELEPHONY_MESSAGING feature. This commit adds an assumption to disable the test on environments lacking this feature. Bug: 374010452 Flag: EXEMPT, test only change Test: atest BluetoothMapbMessageSmsTest Change-Id: Id30ef44afdeaa7ed5d95207c806d400f01fcb60f --- .../android/bluetooth/map/BluetoothMapbMessageSmsTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java index e55117a037e..a43c63d033e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java @@ -16,9 +16,12 @@ package com.android.bluetooth.map; +import static android.content.pm.PackageManager.FEATURE_TELEPHONY_MESSAGING; + import static com.google.common.truth.Truth.assertThat; import android.content.Context; +import android.content.pm.PackageManager; import android.telephony.SmsManager; import androidx.test.InstrumentationRegistry; @@ -50,7 +53,11 @@ public class BluetoothMapbMessageSmsTest { @Before public void setUp() throws Exception { // Do not run test if sms is not supported + PackageManager packageManager = + InstrumentationRegistry.getTargetContext().getPackageManager(); + Assume.assumeTrue(packageManager.isPackageAvailable(FEATURE_TELEPHONY_MESSAGING)); Assume.assumeTrue(mSmsManager.isImsSmsSupported()); + mTargetContext = InstrumentationRegistry.getTargetContext(); TEST_SMS_BODY_PDUS = BluetoothMapSmsPdu.getSubmitPdus(mTargetContext, TEST_MESSAGE, TEST_ADDRESS); -- GitLab From c9b05fc53c3c9254421bb925baa29b2de524d5ca Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Mon, 15 Jul 2024 06:01:03 +0000 Subject: [PATCH 377/875] Remove le_scan_fix_remote_exception flag Bug: 320402249 Test: atest TransitionalScanHelperTest Change-Id: I93b09d93e01c5bfbd4da7fde781626cb2de2eb52 --- .../le_scan/TransitionalScanHelper.java | 24 +++---------------- .../le_scan/TransitionalScanHelperTest.java | 1 - flags/gap.aconfig | 7 ------ 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java index 573b4f49d22..09f3626ad7c 100644 --- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java +++ b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java @@ -463,12 +463,7 @@ public class TransitionalScanHelper { } } catch (RemoteException | PendingIntent.CanceledException e) { Log.e(TAG, "Exception: " + e); - if (Flags.leScanFixRemoteException()) { - handleDeadScanClient(client); - } else { - mScannerMap.remove(client.scannerId); - mScanManager.stopScan(client.scannerId); - } + handleDeadScanClient(client); } } } @@ -772,12 +767,7 @@ public class TransitionalScanHelper { } } catch (RemoteException | PendingIntent.CanceledException e) { Log.e(TAG, "Exception: " + e); - if (Flags.leScanFixRemoteException()) { - handleDeadScanClient(client); - } else { - mScannerMap.remove(client.scannerId); - mScanManager.stopScan(client.scannerId); - } + handleDeadScanClient(client); } } @@ -1518,15 +1508,7 @@ public class TransitionalScanHelper { ScanClient client = getScanClient(mScannerId); if (client != null) { - if (Flags.leScanFixRemoteException()) { - handleDeadScanClient(client); - } else { - client.appDied = true; - if (client.stats != null) { - client.stats.isAppDead = true; - } - stopScanInternal(client.scannerId); - } + handleDeadScanClient(client); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java index f49529c65e5..3176c78f6a0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java @@ -291,7 +291,6 @@ public class TransitionalScanHelperTest { @Test public void onScanResult_remoteException_clientDied() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_LE_SCAN_FIX_REMOTE_EXCEPTION); int scannerId = 1; int eventType = 0; diff --git a/flags/gap.aconfig b/flags/gap.aconfig index 396b5a496b0..c28f1b67298 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -29,13 +29,6 @@ flag { bug: "317128464" } -flag { - name: "le_scan_fix_remote_exception" - namespace: "bluetooth" - description: "Fix handling remote exception for LE scanners" - bug: "320402249" -} - flag { name: "gatt_fix_device_busy" namespace: "bluetooth" -- GitLab From 27175c3ab9b8f78fe302190627029f4096b92c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 11 Oct 2024 13:41:37 +0000 Subject: [PATCH 378/875] l2cap: Workaround for PTS issue Android is sending L2CAP_CONFIGURATION_REQ just after connection, which is fine by spec, however PTS does not catch it sometimes. Adding 5 sec delay helps. Note that the BT specification allows max 120 sec configuration timeout. There is issue reported to PTS and once this is fixed on their side, this can be reverted. Bug: 371948052 Flag: Exempt, test code befind define Test: mmm packages/modules/Bluetooth Test: manual PTS L2CAP/FOC/BV-05-C Change-Id: Ia0af0ea7777668c41130573cd8fcd89fa2d311c7 --- system/stack/l2cap/l2c_csm.cc | 12 ++++++++++++ system/stack/l2cap/l2c_int.h | 5 +++++ system/stack/l2cap/l2c_utils.cc | 10 ++++++++++ 3 files changed, 27 insertions(+) diff --git a/system/stack/l2cap/l2c_csm.cc b/system/stack/l2cap/l2c_csm.cc index 0189ee59007..776596a6f50 100644 --- a/system/stack/l2cap/l2c_csm.cc +++ b/system/stack/l2cap/l2c_csm.cc @@ -119,6 +119,12 @@ static uint8_t pts_get_fcs_option(void) { log::info("Too many iterations: {}, return fcs = 0x01", fcs_opt_iter); return 1; } + +static void l2c_csm_send_config_req(tL2C_CCB* p_ccb); +static void l2c_ccb_pts_delay_config_timeout(void* data) { + tL2C_CCB* p_ccb = (tL2C_CCB*)data; + l2c_csm_send_config_req(p_ccb); +} #endif static uint8_t get_fcs_option(void) { @@ -569,7 +575,13 @@ static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, tL2CEVT event, void* p_dat if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) { log::debug("Not LE connection, sending configure request"); l2c_csm_send_connect_rsp(p_ccb); +#if (L2CAP_CONFORMANCE_TESTING == TRUE) + // TODO: when b/374014194 is solved on PTS side, revert change adding this delay. + alarm_set_on_mloop(p_ccb->pts_config_delay_timer, 5000, l2c_ccb_pts_delay_config_timeout, + p_ccb); +#else l2c_csm_send_config_req(p_ccb); +#endif } else { if (p_ccb->ecoc) { /* Handle Credit Based Connection */ diff --git a/system/stack/l2cap/l2c_int.h b/system/stack/l2cap/l2c_int.h index 94396b7577e..2a43844dd7f 100644 --- a/system/stack/l2cap/l2c_int.h +++ b/system/stack/l2cap/l2c_int.h @@ -282,6 +282,11 @@ struct tL2C_CCB { alarm_t* l2c_ccb_timer; /* CCB Timer Entry */ +#if (L2CAP_CONFORMANCE_TESTING == TRUE) + alarm_t* pts_config_delay_timer; /* Used to delay sending CONFIGURATION_REQ to overcome PTS issue + */ +#endif + tL2C_RCB* p_rcb; /* Registration CB for this Channel */ #define IB_CFG_DONE 0x01 diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index 6497bb1c370..612b9418958 100644 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -1466,6 +1466,11 @@ tL2C_CCB* l2cu_allocate_ccb(tL2C_LCB* p_lcb, uint16_t cid, bool is_eatt) { alarm_free(p_ccb->l2c_ccb_timer); p_ccb->l2c_ccb_timer = alarm_new("l2c.l2c_ccb_timer"); +#if (L2CAP_CONFORMANCE_TESTING == TRUE) + alarm_free(p_ccb->pts_config_delay_timer); + p_ccb->pts_config_delay_timer = alarm_new("pts.delay"); +#endif + l2c_link_adjust_chnl_allocation(); if (p_lcb != NULL) { @@ -1575,6 +1580,11 @@ void l2cu_release_ccb(tL2C_CCB* p_ccb) { alarm_free(p_ccb->l2c_ccb_timer); p_ccb->l2c_ccb_timer = NULL; +#if (L2CAP_CONFORMANCE_TESTING == TRUE) + alarm_free(p_ccb->pts_config_delay_timer); + p_ccb->pts_config_delay_timer = NULL; +#endif + fixed_queue_free(p_ccb->xmit_hold_q, osi_free); p_ccb->xmit_hold_q = NULL; -- GitLab From 4a2fbefd080835a02899e4f4074060bb142be810 Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Mon, 21 Oct 2024 07:01:01 +0000 Subject: [PATCH 379/875] Csip: Improve multithreaded access to state machines Add the missing synchronizations to prevent race conditions. Bug: 372092997 Test: atest GoogleBluetoothInstrumentationTests Flag: Exempt; no functional change Change-Id: Ia19743a17cbcb8bf19d4afa72797629887e3898e --- .../bluetooth/csip/CsipSetCoordinatorService.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java index 62b191a8765..9febc119543 100644 --- a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java +++ b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java @@ -51,6 +51,7 @@ import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.le_audio.LeAudioService; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; @@ -85,6 +86,7 @@ public class CsipSetCoordinatorService extends ProfileService { @VisibleForTesting CsipSetCoordinatorNativeInterface mCsipSetCoordinatorNativeInterface; + @GuardedBy("mStateMachines") private final Map mStateMachines = new HashMap<>(); @@ -143,8 +145,11 @@ public class CsipSetCoordinatorService extends ProfileService { // Get LE Audio service (can be null) mLeAudioService = mServiceFactory.getLeAudioService(); + synchronized (mStateMachines) { + mStateMachines.clear(); + } + // Start handler thread for state machines - mStateMachines.clear(); mStateMachinesThread = new HandlerThread("CsipSetCoordinatorService.StateMachines"); mStateMachinesThread.start(); @@ -1181,8 +1186,10 @@ public class CsipSetCoordinatorService extends ProfileService { @Override public void dump(StringBuilder sb) { super.dump(sb); - for (CsipSetCoordinatorStateMachine sm : mStateMachines.values()) { - sm.dump(sb); + synchronized (mStateMachines) { + for (CsipSetCoordinatorStateMachine sm : mStateMachines.values()) { + sm.dump(sb); + } } ProfileService.println(sb, "mFoundSetMemberToGroupId: "); for (Map.Entry entry : mFoundSetMemberToGroupId.entrySet()) { -- GitLab From 09f669415a5af02c504c25ee6f3f152548f0f451 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 21 Oct 2024 16:25:43 +0000 Subject: [PATCH 380/875] Revert "CS: Update PDL based on core spec 6.0" This reverts commit 14d18d535480f1a1ee4fe66d259c9bf0d971aae9. Reason for revert: Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 373755855 Test: m com.android.btservice Change-Id: If2df0dbba7ac4d8e7b13df910dcafa3c59607781 --- system/gd/hci/distance_measurement_manager.cc | 2 +- system/pdl/hci/hci_packets.pdl | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index d448de62649..021fbd81867 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -591,7 +591,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { connection_handle, config_id, CsCreateContext::BOTH_LOCAL_AND_REMOTE_CONTROLLER, CsMainModeType::MODE_2, CsSubModeType::UNUSED, kMinMainModeSteps, kMaxMainModeSteps, kMainModeRepetition, kMode0Steps, CsRole::INITIATOR, - CsConfigRttType::RTT_AA_ONLY, CsSyncPhy::LE_1M_PHY, channel_map, + CsConfigRttType::RTT_AA_COARSE, CsSyncPhy::LE_1M_PHY, channel_map, kChannelMapRepetition, CsChannelSelectionType::TYPE_3B, CsCh3cShape::HAT_SHAPE, kCh3cJump), handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); diff --git a/system/pdl/hci/hci_packets.pdl b/system/pdl/hci/hci_packets.pdl index 76673e2aaed..df7c47db2a2 100644 --- a/system/pdl/hci/hci_packets.pdl +++ b/system/pdl/hci/hci_packets.pdl @@ -4943,7 +4943,7 @@ struct CsOptionalCsSyncPhysSupported { } struct CsOptionalSubfeaturesSupported { - _reserved_ : 1, + companion_signal : 1, frequency_actuation_error : 1, channel_selection_algorithm : 1, phase_based_ranging : 1, @@ -5129,7 +5129,7 @@ enum CsRole : 8 { } enum CsConfigRttType : 8 { - RTT_AA_ONLY = 0x00, + RTT_AA_COARSE = 0x00, RTT_WITH_32_BIT_SOUNDING_SEQUENCE = 0x01, RTT_WITH_96_BIT_SOUNDING_SEQUENCE = 0x02, RTT_WITH_32_BIT_RANDOM_SEQUENCE = 0x03, @@ -6879,7 +6879,6 @@ packet LeCsProcedureEnableComplete : LeMetaEvent (subevent_code = LE_CS_PROCEDUR event_interval : 16, procedure_interval : 16, procedure_count : 16, - max_procedure_len : 16, } struct LeCsMode0InitatorData { -- GitLab From 1f6e690e71278c25a3b89d1523e4630121a58cf9 Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Fri, 18 Oct 2024 22:52:16 +0000 Subject: [PATCH 381/875] Add flag btsec_le_oob_pairing Test: m libbluetooth Bug: 374376990 Bug: 315241296 Flag: com.android.bluetooth.flags.btsec_le_oob_pairing Ignore-AOSP-First: security Tag: #security Change-Id: Ie35bb3daa7a52fe54ef96a5eec25535afe7214aa --- flags/security.aconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/flags/security.aconfig b/flags/security.aconfig index 73cdb6cbc5f..5a8b5791f19 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -64,3 +64,14 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "btsec_le_oob_pairing" + namespace: "bluetooth" + description: "Drop connection if a peer claims it has OOB data but no local OOB data is stored" + bug: "374376990" + metadata { + purpose: PURPOSE_BUGFIX + } +} + -- GitLab From 44f7d82e9a5c0c0c8483312b74b51b5773276cc0 Mon Sep 17 00:00:00 2001 From: Bhakthavatsala Raghavendra Date: Fri, 18 Oct 2024 20:32:05 +0000 Subject: [PATCH 382/875] Flag to have socket setting interface Socket settings interfaces allows user to create sockets with different security levels Bug: 374358112 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: I4604a8c3d7897ee1d7a63af129c1dd05fc6edbbe --- flags/sockets.aconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flags/sockets.aconfig b/flags/sockets.aconfig index d0ba2d2a5f4..b27b6a53fdc 100644 --- a/flags/sockets.aconfig +++ b/flags/sockets.aconfig @@ -44,3 +44,11 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "socket_settings_api" + namespace: "bluetooth" + description: "Adds new socket settings interface which allows creation of encryption only socket" + bug: "374358112" + is_exported: true +} -- GitLab From 31dba778fca246a40e4fe5a6a04ff148541cdcdd Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 18 Oct 2024 14:33:17 -0700 Subject: [PATCH 383/875] Add bluetooth_tidy default Enforces clang-tidy checks for all cc targets Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, build change Change-Id: I91f0a12aa06d12ad1dcbdf23ae67d3948ac66c25 --- .clang-tidy | 4 +++ Android.bp | 21 ++++++++++++++ system/build/Android.bp | 1 + system/gd/Android.bp | 54 +----------------------------------- system/gd/dumpsys/Android.bp | 3 -- 5 files changed, 27 insertions(+), 56 deletions(-) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000000..df0d649f1fe --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,4 @@ +--- +CheckOptions: + - key: misc-include-cleaner.IgnoreHeaders + value: (fmt/.*|bits/pthread_types\.h) diff --git a/Android.bp b/Android.bp index 9fbf29d0dfb..7fbd19909a2 100644 --- a/Android.bp +++ b/Android.bp @@ -75,6 +75,27 @@ cc_defaults { cpp_std: "c++20", } +// List of tidy checks that are enabled for cc targets. +// Note that the goal is not to enable all checks, many of them will +// appear as noise especially in the modernize-* range. +bluetooth_tidy_checks = [ + "-*", + "misc-*", + + // This check implements detection of local variables which could be declared + // as const but are not. + "-misc-const-correctness", +] + +// This default tidy checks that will be run against all the cc targets +// developed by the Bluetooth team. +cc_defaults { + name: "bluetooth_tidy", + tidy: true, + tidy_checks: bluetooth_tidy_checks, + tidy_checks_as_errors: bluetooth_tidy_checks, +} + java_defaults { name: "bluetooth_errorprone_rules", errorprone: { diff --git a/system/build/Android.bp b/system/build/Android.bp index fd6636b0c58..13f1ccccf50 100644 --- a/system/build/Android.bp +++ b/system/build/Android.bp @@ -11,6 +11,7 @@ cc_defaults { name: "fluoride_defaults", defaults: [ "bluetooth_cflags", + "bluetooth_tidy", ], cflags: [ "-DEXPORT_SYMBOL=__attribute__((visibility(\"default\")))", diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 5f67289b2fc..579aae7d441 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -12,9 +12,7 @@ cc_defaults { name: "gd_defaults", defaults: [ "bluetooth_cflags", - ], - tidy_checks: [ - "-performance-unnecessary-value-param", + "bluetooth_tidy", ], target: { android: { @@ -39,56 +37,6 @@ cc_defaults { header_libs: ["jni_headers"], } -cc_defaults { - name: "gd_clang_tidy", - tidy: true, - tidy_checks: [ - "-bugprone*", - "-cert-dcl21-cpp", // warning: overloaded returns a non-constant object instead of a constant object type - "-cert-dcl59-cpp", // warning: do not use unnamed namespaces in header files - "-cert-msc30-c", // warning: rand() has limited randomness; use C++11 random library instead - "-cert-msc50-cpp", // warning: rand() has limited randomness; use C++11 random library instead - "-cert-oop54-cpp", // warning: operator=() does not handle self-assignment properly - "-google*", - "-performance*", - "clang-analyzer-core.CallAndMessage", - "clang-analyzer-optin.cplusplus.UninitializedObject", - ], - tidy_checks_as_errors: [ - "clang-analyzer-core.CallAndMessage", - "clang-analyzer-optin.cplusplus.UninitializedObject", - "cppcoreguidelines-pro-type-member-init", - ], - tidy_flags: [ - "--header-filter=^.*packages/modules/Bluetooth/system/.*.h$", - - "--extra-arg-before=-Xclang", - "--extra-arg-before=-analyzer-config", - - "--extra-arg-before=-Xclang", - "--extra-arg-before=optin.cplusplus.UninitializedObject:Pedantic=true", - - "--extra-arg-before=-Xclang", - "--extra-arg-before=-analyzer-config", - - "--extra-arg-before=-Xclang", - "--extra-arg-before=optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true", - - ], -} - -// Clang is targeted for android core libraries but other base libraries -// may not support clang tidy recommendations (e.g. MacOS) -cc_defaults { - name: "gd_clang_tidy_ignore_android", - tidy: true, - tidy_checks: [ - "-android-cloexec-accept", // warning: prefer accept4() to accept() because accept4() allows SOCK_CLOEXEC - "-android-cloexec-pipe2", // warning: 'pipe2' should use O_CLOEXEC where possible - "-android-cloexec-socket", // warning: 'pipe2' should use O_CLOEXEC where possible - ], -} - soong_config_module_type { name: "mgmt_cc_defaults", module_type: "cc_defaults", diff --git a/system/gd/dumpsys/Android.bp b/system/gd/dumpsys/Android.bp index 085c44b7f95..f26ef97f9b4 100644 --- a/system/gd/dumpsys/Android.bp +++ b/system/gd/dumpsys/Android.bp @@ -155,7 +155,6 @@ cc_library { name: "libbluetooth-dumpsys", host_supported: true, defaults: [ - "gd_clang_tidy", "gd_defaults", ], generated_sources: [ @@ -171,7 +170,6 @@ cc_library { name: "libbluetooth-dumpsys-test", host_supported: true, defaults: [ - "gd_clang_tidy", "gd_defaults", ], generated_sources: [ @@ -183,7 +181,6 @@ cc_library { name: "libbluetooth-dumpsys-unittest", host_supported: true, defaults: [ - "gd_clang_tidy", "gd_defaults", ], generated_headers: [ -- GitLab From 50c0da0cd24a5f485716e35bc9e151ea9453c4a5 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Sat, 19 Oct 2024 01:14:05 +0000 Subject: [PATCH 384/875] android/app/jni: clang-tidy fixes Bug: 331817295 Test: m com.android.btservices Test: WITH_TIDY_FLAGS=--fix m libbluetooth_jni-tidy Flag: EXEMPT, no logical change Change-Id: I0a2a6bf7918b1d2598537943ca46f4589c2b4608 --- ...droid_bluetooth_BluetoothQualityReport.cpp | 11 +++++++-- .../app/jni/com_android_bluetooth_a2dp.cpp | 11 +++++++++ .../jni/com_android_bluetooth_a2dp_sink.cpp | 7 ++++++ ...com_android_bluetooth_avrcp_controller.cpp | 13 ++++++++-- .../com_android_bluetooth_avrcp_target.cpp | 14 +++++++++-- ...oid_bluetooth_btservice_AdapterService.cpp | 24 +++++++++++++------ ..._bluetooth_btservice_BluetoothKeystore.cpp | 8 +++++-- ...android_bluetooth_csip_set_coordinator.cpp | 17 ++++++++++--- .../app/jni/com_android_bluetooth_gatt.cpp | 24 +++++++++++++++++-- .../jni/com_android_bluetooth_hap_client.cpp | 16 +++++++++++-- .../jni/com_android_bluetooth_hearing_aid.cpp | 13 ++++++++-- android/app/jni/com_android_bluetooth_hfp.cpp | 9 ++++++- .../jni/com_android_bluetooth_hfpclient.cpp | 11 ++++++++- .../jni/com_android_bluetooth_hid_device.cpp | 10 +++++++- .../jni/com_android_bluetooth_hid_host.cpp | 12 +++++++++- .../jni/com_android_bluetooth_le_audio.cpp | 17 ++++++++++++- android/app/jni/com_android_bluetooth_pan.cpp | 8 ++++++- android/app/jni/com_android_bluetooth_sdp.cpp | 12 +++++++++- android/app/jni/com_android_bluetooth_vc.cpp | 16 ++++++++++--- 19 files changed, 219 insertions(+), 34 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp b/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp index d1d48e93b72..b59bc9116f1 100644 --- a/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp +++ b/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp @@ -16,14 +16,21 @@ #define LOG_TAG "BluetoothQualityReportJni" -#include +#include +#include +#include +#include +#include +#include #include +#include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_bqr.h" +#include "types/raw_address.h" -using bluetooth::bqr::BluetoothQualityReportCallbacks; using bluetooth::bqr::BluetoothQualityReportInterface; namespace android { diff --git a/android/app/jni/com_android_bluetooth_a2dp.cpp b/android/app/jni/com_android_bluetooth_a2dp.cpp index f8a6f5480ac..2d6e255d15a 100644 --- a/android/app/jni/com_android_bluetooth_a2dp.cpp +++ b/android/app/jni/com_android_bluetooth_a2dp.cpp @@ -16,13 +16,24 @@ #define LOG_TAG "bluetooth-a2dp" +#include +#include +#include +#include + +#include +#include #include +#include #include +#include #include "btif/include/btif_av.h" #include "btif/include/btif_util.h" #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_av.h" +#include "types/raw_address.h" namespace android { static jmethodID method_onConnectionStateChanged; diff --git a/android/app/jni/com_android_bluetooth_a2dp_sink.cpp b/android/app/jni/com_android_bluetooth_a2dp_sink.cpp index 44f1fee6cc9..f2347e97497 100644 --- a/android/app/jni/com_android_bluetooth_a2dp_sink.cpp +++ b/android/app/jni/com_android_bluetooth_a2dp_sink.cpp @@ -17,14 +17,21 @@ #define LOG_TAG "BluetoothA2dpSinkServiceJni" #include +#include +#include +#include +#include +#include #include #include #include #include "btif/include/btif_av.h" #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_av.h" +#include "types/raw_address.h" namespace android { static jmethodID method_onConnectionStateChanged; diff --git a/android/app/jni/com_android_bluetooth_avrcp_controller.cpp b/android/app/jni/com_android_bluetooth_avrcp_controller.cpp index 0d29848e819..a0b80f79026 100644 --- a/android/app/jni/com_android_bluetooth_avrcp_controller.cpp +++ b/android/app/jni/com_android_bluetooth_avrcp_controller.cpp @@ -16,12 +16,21 @@ #define LOG_TAG "BluetoothAvrcpControllerJni" -#include - +#include +#include +#include +#include + +#include +#include +#include +#include #include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_rc.h" +#include "types/raw_address.h" namespace android { static jmethodID method_onConnectionStateChanged; diff --git a/android/app/jni/com_android_bluetooth_avrcp_target.cpp b/android/app/jni/com_android_bluetooth_avrcp_target.cpp index 22f11e43458..9ed217aa2a6 100644 --- a/android/app/jni/com_android_bluetooth_avrcp_target.cpp +++ b/android/app/jni/com_android_bluetooth_avrcp_target.cpp @@ -18,14 +18,24 @@ #include #include -#include +#include +#include +#include +#include +#include #include #include #include +#include +#include #include -#include "./com_android_bluetooth.h" +#include "com_android_bluetooth.h" +#include "hardware/avrcp/avrcp.h" +#include "hardware/avrcp/avrcp_common.h" +#include "hardware/bluetooth.h" +#include "types/raw_address.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index 050fc7b1a53..8e2f4e201df 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -17,21 +17,31 @@ #define LOG_TAG "BluetoothServiceJni" -#include -#include -#include -#include +#include +#include +#include +#include #include +#include #include -#include #include -#include +#include +#include +#include +#include +#include #include +#include +#include +#include -#include "./com_android_bluetooth.h" +#include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_sock.h" +#include "types/bluetooth/uuid.h" #include "types/bt_transport.h" +#include "types/raw_address.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp b/android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp index 330b55703ef..5151bbff2fa 100644 --- a/android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp @@ -16,14 +16,18 @@ #define LOG_TAG "BluetoothKeystoreServiceJni" -#include +#include +#include +#include +#include #include +#include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_keystore.h" -using bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks; using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface; namespace android { diff --git a/android/app/jni/com_android_bluetooth_csip_set_coordinator.cpp b/android/app/jni/com_android_bluetooth_csip_set_coordinator.cpp index f083457386f..0f30fb11baf 100644 --- a/android/app/jni/com_android_bluetooth_csip_set_coordinator.cpp +++ b/android/app/jni/com_android_bluetooth_csip_set_coordinator.cpp @@ -15,14 +15,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #define LOG_TAG "BluetoothCsipSetCoordinatorJni" -#include +#include +#include +#include +#include + +#include +#include +#include +#include #include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_csis.h" +#include "types/bluetooth/uuid.h" +#include "types/raw_address.h" +using bluetooth::Uuid; using bluetooth::csis::ConnectionState; using bluetooth::csis::CsisClientCallbacks; using bluetooth::csis::CsisClientInterface; @@ -40,8 +53,6 @@ static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; -using bluetooth::Uuid; - #define UUID_PARAMS(uuid) uuid_lsb(uuid), uuid_msb(uuid) static uint64_t uuid_lsb(const Uuid& uuid) { diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index 71325ee0c74..5ef7e4593d3 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -18,20 +18,40 @@ #include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include +#include #include +#include +#include +#include #include "com_android_bluetooth.h" #include "com_android_bluetooth_flags.h" +#include "hardware/ble_advertiser.h" +#include "hardware/ble_scanner.h" +#include "hardware/bluetooth.h" +#include "hardware/bt_common_types.h" #include "hardware/bt_gatt.h" +#include "hardware/bt_gatt_client.h" +#include "hardware/bt_gatt_server.h" #include "hardware/bt_gatt_types.h" +#include "hardware/distance_measurement_interface.h" #include "main/shim/le_scanning_manager.h" #include "rust/cxx.h" -#include "rust/src/gatt/ffi/gatt_shim.h" #include "src/gatt/ffi.rs.h" +#include "types/bluetooth/uuid.h" +#include "types/raw_address.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/android/app/jni/com_android_bluetooth_hap_client.cpp b/android/app/jni/com_android_bluetooth_hap_client.cpp index 295a207a4c3..d2bdcbac8d8 100644 --- a/android/app/jni/com_android_bluetooth_hap_client.cpp +++ b/android/app/jni/com_android_bluetooth_hap_client.cpp @@ -17,12 +17,24 @@ #define LOG_TAG "BluetoothHapClientJni" -#include - +#include +#include +#include +#include + +#include +#include +#include +#include #include +#include +#include +#include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_has.h" +#include "types/raw_address.h" using bluetooth::has::ConnectionState; using bluetooth::has::ErrorCode; diff --git a/android/app/jni/com_android_bluetooth_hearing_aid.cpp b/android/app/jni/com_android_bluetooth_hearing_aid.cpp index edf8dc58654..dbe2439ed43 100644 --- a/android/app/jni/com_android_bluetooth_hearing_aid.cpp +++ b/android/app/jni/com_android_bluetooth_hearing_aid.cpp @@ -16,12 +16,21 @@ #define LOG_TAG "BluetoothHearingAidServiceJni" -#include - +#include +#include +#include +#include + +#include +#include +#include +#include #include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_hearing_aid.h" +#include "types/raw_address.h" using bluetooth::hearing_aid::ConnectionState; using bluetooth::hearing_aid::HearingAidCallbacks; diff --git a/android/app/jni/com_android_bluetooth_hfp.cpp b/android/app/jni/com_android_bluetooth_hfp.cpp index c1d982de173..0a53d42c6f6 100644 --- a/android/app/jni/com_android_bluetooth_hfp.cpp +++ b/android/app/jni/com_android_bluetooth_hfp.cpp @@ -17,15 +17,22 @@ #define LOG_TAG "BluetoothHeadsetServiceJni" #include +#include +#include +#include +#include +#include +#include #include #include -#include "btif/include/btif_hf.h" #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bluetooth_headset_callbacks.h" #include "hardware/bluetooth_headset_interface.h" #include "hardware/bt_hf.h" +#include "types/raw_address.h" namespace android { diff --git a/android/app/jni/com_android_bluetooth_hfpclient.cpp b/android/app/jni/com_android_bluetooth_hfpclient.cpp index f42d8dd2104..daf575204e3 100644 --- a/android/app/jni/com_android_bluetooth_hfpclient.cpp +++ b/android/app/jni/com_android_bluetooth_hfpclient.cpp @@ -17,11 +17,20 @@ #define LOG_TAG "BluetoothHeadsetClientServiceJni" +#include +#include +#include +#include + +#include +#include +#include #include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_hf_client.h" -#include "os/logging/log_adapter.h" +#include "types/raw_address.h" namespace android { diff --git a/android/app/jni/com_android_bluetooth_hid_device.cpp b/android/app/jni/com_android_bluetooth_hid_device.cpp index 6ff86e05307..5f2b98a2cec 100644 --- a/android/app/jni/com_android_bluetooth_hid_device.cpp +++ b/android/app/jni/com_android_bluetooth_hid_device.cpp @@ -16,10 +16,18 @@ #define LOG_TAG "BluetoothHidDeviceServiceJni" -#include +#include +#include +#include + +#include +#include +#include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_hd.h" +#include "types/raw_address.h" namespace android { diff --git a/android/app/jni/com_android_bluetooth_hid_host.cpp b/android/app/jni/com_android_bluetooth_hid_host.cpp index fcd28e5bbc7..267eea8f84e 100644 --- a/android/app/jni/com_android_bluetooth_hid_host.cpp +++ b/android/app/jni/com_android_bluetooth_hid_host.cpp @@ -16,13 +16,23 @@ #define LOG_TAG "BluetoothHidHostServiceJni" -#include +#include +#include +#include +#include +#include +#include #include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_hh.h" +#include "types/ble_address_with_type.h" +#include "types/bt_transport.h" +#include "types/raw_address.h" #include "utils/Log.h" + namespace android { static jmethodID method_onConnectStateChanged; diff --git a/android/app/jni/com_android_bluetooth_le_audio.cpp b/android/app/jni/com_android_bluetooth_le_audio.cpp index 69c25d99b39..4ce436e5c4f 100644 --- a/android/app/jni/com_android_bluetooth_le_audio.cpp +++ b/android/app/jni/com_android_bluetooth_le_audio.cpp @@ -16,14 +16,29 @@ #define LOG_TAG "BluetoothLeAudioServiceJni" -#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_le_audio.h" +#include "types/raw_address.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/android/app/jni/com_android_bluetooth_pan.cpp b/android/app/jni/com_android_bluetooth_pan.cpp index 195b8fefc26..f0c78eac72e 100644 --- a/android/app/jni/com_android_bluetooth_pan.cpp +++ b/android/app/jni/com_android_bluetooth_pan.cpp @@ -16,10 +16,16 @@ #define LOG_TAG "BluetoothPanServiceJni" -#include +#include +#include +#include + +#include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_pan.h" +#include "types/raw_address.h" namespace android { diff --git a/android/app/jni/com_android_bluetooth_sdp.cpp b/android/app/jni/com_android_bluetooth_sdp.cpp index 1d49fca11a1..e667dbcd8c6 100644 --- a/android/app/jni/com_android_bluetooth_sdp.cpp +++ b/android/app/jni/com_android_bluetooth_sdp.cpp @@ -16,10 +16,20 @@ #define LOG_TAG "BluetoothSdpJni" -#include +#include +#include +#include +#include + +#include +#include +#include #include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_sdp.h" +#include "types/bluetooth/uuid.h" +#include "types/raw_address.h" using bluetooth::Uuid; diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp index c998c0f7a12..39bd355dadc 100644 --- a/android/app/jni/com_android_bluetooth_vc.cpp +++ b/android/app/jni/com_android_bluetooth_vc.cpp @@ -17,12 +17,22 @@ #define LOG_TAG "BluetoothVolumeControlServiceJni" -#include - +#include +#include +#include +#include + +#include +#include +#include +#include #include +#include -#include "./com_android_bluetooth.h" +#include "com_android_bluetooth.h" +#include "hardware/bluetooth.h" #include "hardware/bt_vc.h" +#include "types/raw_address.h" using bluetooth::vc::ConnectionState; using bluetooth::vc::VolumeControlCallbacks; -- GitLab From bed62da40cbc3dc28b344a2babe99eed9eeb060a Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 21 Oct 2024 14:16:20 -0700 Subject: [PATCH 385/875] errorprone: Discard InlineMeSuggester Bug: 344658662 Test: m com.android.btservices Flag: Exempt lint enforcement Change-Id: I3674436976123e6c4b7e774f06500372baa3eecb --- Android.bp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Android.bp b/Android.bp index 9fbf29d0dfb..ebb06c54b0d 100644 --- a/Android.bp +++ b/Android.bp @@ -147,8 +147,10 @@ java_defaults { // Exclude generated files "-XepExcludedPaths:.*/srcjars/.*", - // The @InlineMe annotation is not available - // "-Xep:InlineMeSuggester:OFF", + // The @InlineMe annotation could be made available, but it would + // apply on external facing API. This is not desired. For more + // context, see https://r.android.com/3303475 + "-Xep:InlineMeSuggester:OFF", ], }, } -- GitLab From 81fade894b5ac9560ef55003dfbe9f07195dc482 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 17 Oct 2024 18:08:48 -0700 Subject: [PATCH 386/875] Flags: Sort hap flags Bug: 373814270 Bug: 372328699 Flag: com.android.bluetooth.flags.aics_api Test: m . Change-Id: Id09bbaca578c9173fcb3e55d967bbe3f53496c7e --- flags/hap.aconfig | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/flags/hap.aconfig b/flags/hap.aconfig index 0780daf2387..15cfd9c5bb3 100644 --- a/flags/hap.aconfig +++ b/flags/hap.aconfig @@ -2,18 +2,18 @@ package: "com.android.bluetooth.flags" container: "com.android.btservices" flag { - name: "enable_hap_by_default" + name: "aics_api" + is_exported: true namespace: "bluetooth" - description: "On device that support HAP, enable it by default and disable ASHA" - bug: "345826775" + description: "Expose new API to control AICS data" + bug: "372328699" } flag { - name: "settings_can_control_hap_preset" - is_exported: true + name: "enable_hap_by_default" namespace: "bluetooth" - description: "Allow user to control the preset of hearing aid devices" - bug: "306236481" + description: "On device that support HAP, enable it by default and disable ASHA" + bug: "345826775" } flag { @@ -26,11 +26,10 @@ flag { } } - flag { - name: "aics_api" + name: "settings_can_control_hap_preset" is_exported: true namespace: "bluetooth" - description: "Expose new API to control AICS data" - bug: "372328699" + description: "Allow user to control the preset of hearing aid devices" + bug: "306236481" } -- GitLab From 100d46735746e6fa805832a7e48b6b151a39963a Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Tue, 22 Oct 2024 12:35:55 +0900 Subject: [PATCH 387/875] Fix Bluetooth popup when sharing files Bug: 370529308 Test: m -j; Test: Manual, checked the popup is gone Flag: EXEMPT, XML style change Change-Id: Iadb88c2bbbb7afe68bfb5bb5321ad8de803be03e --- android/app/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/AndroidManifest.xml b/android/app/AndroidManifest.xml index c77602c8a7f..3416c8ff7f3 100644 --- a/android/app/AndroidManifest.xml +++ b/android/app/AndroidManifest.xml @@ -203,7 +203,7 @@ -- GitLab From 588c7b6a81e2f6e5983edb52d23b4b602a7b9265 Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Wed, 9 Oct 2024 17:23:10 +0000 Subject: [PATCH 388/875] Bass: Do not notify about source lost immediately Start 5s broadcast sync lost timer, instead of immediate notify about sync lost. Start 5s broadcast sync lost timer when sync removed because of max active synced sources limit reached. Restart timer on each new advertising from that broadcaster when timer is started. Notify about lost and clear cache if needed, when timer fire out. Additionally, handle all timeouts per broadcast id. Bug: 372390557 Bug: 363168099 Test: atest BassClientServiceTest Change-Id: I48c929496ee7b1a1bc477938d10188f00e51631e --- .../bass_client/BassClientService.java | 237 +++++++++---- .../bass_client/BassClientServiceTest.java | 320 +++++++++++++++--- .../BluetoothLeBroadcastAssistant.java | 5 +- 3 files changed, 451 insertions(+), 111 deletions(-) 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 737cdb541ce..8135014cbfe 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -124,6 +124,7 @@ public class BassClientService extends ProfileService { @VisibleForTesting static final int MESSAGE_SYNC_TIMEOUT = 1; @VisibleForTesting static final int MESSAGE_BIG_MONITOR_TIMEOUT = 2; @VisibleForTesting static final int MESSAGE_BROADCAST_MONITOR_TIMEOUT = 3; + @VisibleForTesting static final int MESSAGE_SYNC_LOST_TIMEOUT = 4; /* 1 minute timeout for primary device reconnection in Private Broadcast case */ private static final int DIALING_OUT_TIMEOUT_MS = 60000; @@ -137,6 +138,9 @@ public class BassClientService extends ProfileService { // 5 minutes timeout for monitoring broadcaster private static final Duration sBroadcasterMonitorTimeout = Duration.ofMinutes(5); + // 5 seconds timeout for sync Lost notification + private static final Duration sSyncLostTimeout = Duration.ofSeconds(5); + private enum PauseType { HOST_INTENTIONAL, SINK_UNINTENTIONAL @@ -216,39 +220,131 @@ public class BassClientService extends ProfileService { clearAllSyncData(); break; } - case MESSAGE_BROADCAST_MONITOR_TIMEOUT: - { - log("MESSAGE_BROADCAST_MONITOR_TIMEOUT"); - int broadcastId = msg.arg1; - List activeSyncedSrc = - new ArrayList<>(getActiveSyncedSources()); - if (activeSyncedSrc.contains( - getSyncHandleForBroadcastId(broadcastId))) { - break; - } - log("Notify broadcast source lost, broadcast id: " + broadcastId); - mCallbacks.notifySourceLost(broadcastId); - // fall through - } - case MESSAGE_BIG_MONITOR_TIMEOUT: - { - log("MESSAGE_BIG_MONITOR_TIMEOUT"); - int broadcastId = msg.arg1; - stopSourceReceivers(broadcastId); - synchronized (mSearchScanCallbackLock) { - // when searching is stopped then clear all sync data - if (mSearchScanCallback == null) { - clearAllSyncData(); - } - } - break; - } default: break; } } }; + @VisibleForTesting public final TimeoutHandler mTimeoutHandler = new TimeoutHandler(); + + @VisibleForTesting + public final class TimeoutHandler { + private final Map mHandlers = new HashMap<>(); + + @VisibleForTesting + public Handler getOrCreateHandler(int broadcastId) { + return mHandlers.computeIfAbsent( + broadcastId, + key -> + new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_SYNC_LOST_TIMEOUT: + { + log("MESSAGE_SYNC_LOST_TIMEOUT"); + // fall through + } + case MESSAGE_BROADCAST_MONITOR_TIMEOUT: + { + log("MESSAGE_BROADCAST_MONITOR_TIMEOUT"); + List activeSyncedSrc = + new ArrayList<>(getActiveSyncedSources()); + if (activeSyncedSrc.contains( + getSyncHandleForBroadcastId(broadcastId))) { + break; + } + // Clear from cache to make possible sync again + // (only during active searching) + synchronized (mSearchScanCallbackLock) { + if (mSearchScanCallback != null) { + mCachedBroadcasts.remove(broadcastId); + } + } + log( + "Notify broadcast source lost, broadcast" + + " id: " + + broadcastId); + mCallbacks.notifySourceLost(broadcastId); + if (!isSinkUnintentionalPauseType(broadcastId)) { + break; + } + // fall through + } + case MESSAGE_BIG_MONITOR_TIMEOUT: + { + log("MESSAGE_BIG_MONITOR_TIMEOUT"); + stopSourceReceivers(broadcastId); + synchronized (mSearchScanCallbackLock) { + // when searching is stopped then clear all sync + // data + if (mSearchScanCallback == null) { + clearAllSyncData(); + } + } + break; + } + default: + break; + } + Handler handler = getOrCreateHandler(broadcastId); + if (!handler.hasMessagesOrCallbacks()) { + mHandlers.remove(broadcastId); + } + } + }); + } + + void start(int broadcastId, int msg, Duration duration) { + Handler handler = getOrCreateHandler(broadcastId); + log( + "Started timeout: " + + ("broadcastId: " + broadcastId) + + (", msg: " + msg) + + (", duration: " + duration)); + handler.sendEmptyMessageDelayed(msg, duration.toMillis()); + } + + void stop(int broadcastId, int msg) { + if (!mHandlers.containsKey(broadcastId)) { + return; + } + Handler handler = getOrCreateHandler(broadcastId); + handler.removeMessages(msg); + if (!handler.hasMessagesOrCallbacks()) { + mHandlers.remove(broadcastId); + } + } + + void stopAll() { + for (Handler handler : mHandlers.values()) { + handler.removeCallbacksAndMessages(null); + } + mHandlers.clear(); + } + + void stopAll(int msg) { + Iterator> iterator = mHandlers.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + Handler handler = entry.getValue(); + handler.removeMessages(msg); + if (!handler.hasMessagesOrCallbacks()) { + iterator.remove(); + } + } + } + + boolean isStarted(int broadcastId, int msg) { + if (!mHandlers.containsKey(broadcastId)) { + return false; + } + Handler handler = getOrCreateHandler(broadcastId); + return handler.hasMessages(msg); + } + } + public BassClientService(Context ctx) { super(ctx); } @@ -710,6 +806,7 @@ public class BassClientService extends ProfileService { } mHandler.removeCallbacksAndMessages(null); + mTimeoutHandler.stopAll(); setBassClientService(null); if (!leaudioBroadcastExtractPeriodicScannerFromStateMachine()) { @@ -1041,11 +1138,9 @@ public class BassClientService extends ProfileService { mPausedBroadcastIds.put(broadcastId, PauseType.SINK_UNINTENTIONAL); cacheSuspendingSources(broadcastId); - mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_MONITOR_TIMEOUT); - newMsg.arg1 = broadcastId; - log("Started MESSAGE_BIG_MONITOR_TIMEOUT"); - mHandler.sendMessageDelayed(newMsg, sBigMonitorTimeout.toMillis()); + mTimeoutHandler.stop(broadcastId, MESSAGE_BIG_MONITOR_TIMEOUT); + mTimeoutHandler.start( + broadcastId, MESSAGE_BIG_MONITOR_TIMEOUT, sBigMonitorTimeout); } } } else if (isEmptyBluetoothDevice(receiveState.getSourceDevice())) { @@ -1832,8 +1927,10 @@ public class BassClientService extends ProfileService { TAG, "Broadcast Source Found: Broadcast ID: " + broadcastId); - if (broadcastId != BassConstants.INVALID_BROADCAST_ID - && !mCachedBroadcasts.containsKey(broadcastId)) { + if (broadcastId == BassConstants.INVALID_BROADCAST_ID) { + return; + } + if (!mCachedBroadcasts.containsKey(broadcastId)) { log("selectBroadcastSource: broadcastId " + broadcastId); mCachedBroadcasts.put(broadcastId, result); if (leaudioBroadcastExtractPeriodicScannerFromStateMachine()) { @@ -1848,6 +1945,14 @@ public class BassClientService extends ProfileService { } } } + } else if (leaudioBroadcastResyncHelper() + && mTimeoutHandler.isStarted( + broadcastId, MESSAGE_SYNC_LOST_TIMEOUT)) { + mTimeoutHandler.stop(broadcastId, MESSAGE_SYNC_LOST_TIMEOUT); + mTimeoutHandler.start( + broadcastId, + MESSAGE_SYNC_LOST_TIMEOUT, + sSyncLostTimeout); } } } @@ -1970,6 +2075,7 @@ public class BassClientService extends ProfileService { private void clearAllSyncData() { log("clearAllSyncData"); + mTimeoutHandler.stopAll(MESSAGE_SYNC_LOST_TIMEOUT); mSourceSyncRequestsQueue.clear(); mSyncFailureCounter.clear(); mPendingSourcesToAdd.clear(); @@ -2047,7 +2153,7 @@ public class BassClientService extends ProfileService { } } } else { - mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mTimeoutHandler.stop(broadcastId, MESSAGE_BROADCAST_MONITOR_TIMEOUT); } // update valid sync handle in mPeriodicAdvCallbacksMap @@ -2100,11 +2206,12 @@ public class BassClientService extends ProfileService { mSyncFailureCounter.put(broadcastId, failsCounter); } if (isSinkUnintentionalPauseType(broadcastId)) { - if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { - Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT); - newMsg.arg1 = broadcastId; - log("Started MESSAGE_BROADCAST_MONITOR_TIMEOUT"); - mHandler.sendMessageDelayed(newMsg, sBroadcasterMonitorTimeout.toMillis()); + if (!mTimeoutHandler.isStarted( + broadcastId, MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { + mTimeoutHandler.start( + broadcastId, + MESSAGE_BROADCAST_MONITOR_TIMEOUT, + sBroadcasterMonitorTimeout); } addSelectSourceRequest(broadcastId, true); } else { @@ -2183,23 +2290,31 @@ public class BassClientService extends ProfileService { int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1; mSyncFailureCounter.put(broadcastId, failsCounter); } + mTimeoutHandler.stop(broadcastId, MESSAGE_SYNC_LOST_TIMEOUT); if (isSinkUnintentionalPauseType(broadcastId)) { - if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { - Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT); - newMsg.arg1 = broadcastId; - log("Started MESSAGE_BROADCAST_MONITOR_TIMEOUT"); - mHandler.sendMessageDelayed(newMsg, sBroadcasterMonitorTimeout.toMillis()); + if (!mTimeoutHandler.isStarted( + broadcastId, MESSAGE_BROADCAST_MONITOR_TIMEOUT)) { + mTimeoutHandler.start( + broadcastId, + MESSAGE_BROADCAST_MONITOR_TIMEOUT, + sBroadcasterMonitorTimeout); } addSelectSourceRequest(broadcastId, true); } else { - // Clear from cache to make possible sync again (only during active searching) - synchronized (mSearchScanCallbackLock) { - if (mSearchScanCallback != null) { - mCachedBroadcasts.remove(broadcastId); + if (leaudioBroadcastResyncHelper()) { + mTimeoutHandler.start( + broadcastId, MESSAGE_SYNC_LOST_TIMEOUT, sSyncLostTimeout); + } else { + // Clear from cache to make possible sync again (only during active + // searching) + synchronized (mSearchScanCallbackLock) { + if (mSearchScanCallback != null) { + mCachedBroadcasts.remove(broadcastId); + } } + log("Notify broadcast source lost, broadcast id: " + broadcastId); + mCallbacks.notifySourceLost(broadcastId); } - log("Notify broadcast source lost, broadcast id: " + broadcastId); - mCallbacks.notifySourceLost(broadcastId); } } } @@ -2480,7 +2595,7 @@ public class BassClientService extends ProfileService { + broadcastId + ", hasPriority: " + hasPriority); - + mTimeoutHandler.stop(broadcastId, MESSAGE_SYNC_LOST_TIMEOUT); ScanResult scanRes = getCachedBroadcast(broadcastId); if (scanRes != null) { ScanRecord scanRecord = scanRes.getScanRecord(); @@ -2572,9 +2687,11 @@ public class BassClientService extends ProfileService { cancelActiveSync(syncHandle); } else { Boolean canceledActiveSync = false; + int broadcstIdToLostMonitoring = BassConstants.INVALID_BROADCAST_ID; for (int syncHandle : activeSyncedSrc) { if (!isAnyReceiverSyncedToBroadcast(getBroadcastIdForSyncHandle(syncHandle))) { canceledActiveSync = true; + broadcstIdToLostMonitoring = getBroadcastIdForSyncHandle(syncHandle); cancelActiveSync(syncHandle); break; } @@ -2582,8 +2699,11 @@ public class BassClientService extends ProfileService { if (!canceledActiveSync) { int syncHandle = activeSyncedSrc.get(0); // removing the 1st synced source before proceeding to add new + broadcstIdToLostMonitoring = getBroadcastIdForSyncHandle(syncHandle); cancelActiveSync(syncHandle); } + mTimeoutHandler.start( + broadcstIdToLostMonitoring, MESSAGE_SYNC_LOST_TIMEOUT, sSyncLostTimeout); } } @@ -3447,14 +3567,13 @@ public class BassClientService extends ProfileService { return; } log("stopBigMonitoring"); - mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); - mPausedBroadcastSinks.clear(); Iterator iterator = mPausedBroadcastIds.keySet().iterator(); while (iterator.hasNext()) { int pausedBroadcastId = iterator.next(); + mTimeoutHandler.stop(pausedBroadcastId, MESSAGE_BIG_MONITOR_TIMEOUT); + mTimeoutHandler.stop(pausedBroadcastId, MESSAGE_BROADCAST_MONITOR_TIMEOUT); iterator.remove(); synchronized (mSearchScanCallbackLock) { // when searching is stopped then stop active sync @@ -3475,8 +3594,8 @@ public class BassClientService extends ProfileService { while (iterator.hasNext()) { int pausedBroadcastId = iterator.next(); if (!isAnyReceiverSyncedToBroadcast(pausedBroadcastId)) { - mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mTimeoutHandler.stop(pausedBroadcastId, MESSAGE_BIG_MONITOR_TIMEOUT); + mTimeoutHandler.stop(pausedBroadcastId, MESSAGE_BROADCAST_MONITOR_TIMEOUT); iterator.remove(); synchronized (mSearchScanCallbackLock) { // when searching is stopped then stop active sync @@ -3494,8 +3613,8 @@ public class BassClientService extends ProfileService { return; } log("stopBigMonitoring broadcastId: " + broadcastId + ", hostInitiated: " + hostInitiated); - mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT); - mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT); + mTimeoutHandler.stop(broadcastId, MESSAGE_BIG_MONITOR_TIMEOUT); + mTimeoutHandler.stop(broadcastId, MESSAGE_BROADCAST_MONITOR_TIMEOUT); if (hostInitiated) { mPausedBroadcastIds.put(broadcastId, PauseType.HOST_INTENTIONAL); } else { diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index ac848668afd..89fe1daa5bf 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -62,6 +62,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; +import android.os.Handler; import android.os.Message; import android.os.ParcelUuid; import android.os.RemoteException; @@ -784,7 +785,8 @@ public class BassClientServiceTest { @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) - public void testNotRemovingCachedBroadcastOnLostWithoutScanning() { + @DisableFlags(Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER) + public void testNotRemovingCachedBroadcastOnLostWithoutScanning_noResyncFlag() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -814,19 +816,95 @@ public class BassClientServiceTest { throw e.rethrowFromSystemServer(); } - // Scan and sync again + // Add broadcast to cache onScanResult(mSourceDevice, TEST_BROADCAST_ID); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + // Stop searching + mBassClientService.stopSearchingForSources(); + + // Add sync handle by add source + mBassClientService.addSource(mCurrentDevice, meta, true); + handleHandoverSupport(); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + // Sync lost without active scanning should not remove broadcast cache + onSyncLost(); + + // Add source to unsynced broadcast, causes synchronization first + mBassClientService.addSource(mCurrentDevice, meta, true); + handleHandoverSupport(); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER + }) + public void testNotRemovingCachedBroadcastOnLostWithoutScanning() { + prepareConnectedDeviceGroup(); + startSearchingForSources(); + + // Scan and sync 1 + onScanResult(mSourceDevice, TEST_BROADCAST_ID); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + + // Sync lost during scanning removes cached broadcast + onSyncLost(); + checkAndDispatchTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_SYNC_LOST_TIMEOUT); + + // Add source to not cached broadcast cause addFailed notification + BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); + mBassClientService.addSource(mCurrentDevice, meta, true); + handleHandoverSupport(); + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + try { + verify(mCallback) + .onSourceAddFailed( + eq(mCurrentDevice), + eq(meta), + eq(BluetoothStatusCodes.ERROR_BAD_PARAMETERS)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + // Add broadcast to cache + onScanResult(mSourceDevice, TEST_BROADCAST_ID); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + // Stop searching mBassClientService.stopSearchingForSources(); + // Add sync handle by add source + mBassClientService.addSource(mCurrentDevice, meta, true); + handleHandoverSupport(); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + // Sync lost without active scanning should not remove broadcast cache onSyncLost(); + checkAndDispatchTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_SYNC_LOST_TIMEOUT); // Add source to unsynced broadcast, causes synchronization first mBassClientService.addSource(mCurrentDevice, meta, true); @@ -1115,20 +1193,20 @@ public class BassClientServiceTest { any(), any(), anyInt(), anyInt(), any(), any()); } - private void checkNoMessage(int message) { - assertThat(mBassClientService.mHandler.hasMessages(message)).isFalse(); + private void checkNoTimeout(int broadcastId, int message) { + assertThat(mBassClientService.mTimeoutHandler.isStarted(broadcastId, message)).isFalse(); } - private void checkMessage(int message) { - assertThat(mBassClientService.mHandler.hasMessages(message)).isTrue(); + private void checkTimeout(int broadcastId, int message) { + assertThat(mBassClientService.mTimeoutHandler.isStarted(broadcastId, message)).isTrue(); } - private void checkAndDispatchMessage(int message, int broadcastId) { - checkMessage(message); - mBassClientService.mHandler.removeMessages(message); - Message newMsg = mBassClientService.mHandler.obtainMessage(message); - newMsg.arg1 = broadcastId; - mBassClientService.mHandler.dispatchMessage(newMsg); + private void checkAndDispatchTimeout(int broadcastId, int message) { + checkTimeout(broadcastId, message); + mBassClientService.mTimeoutHandler.stop(broadcastId, message); + Handler handler = mBassClientService.mTimeoutHandler.getOrCreateHandler(broadcastId); + Message newMsg = handler.obtainMessage(message); + handler.dispatchMessage(newMsg); } @Test @@ -1154,7 +1232,8 @@ public class BassClientServiceTest { handleHandoverSupport(); // Source synced which cause start timeout event - checkNoMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + assertThat(mBassClientService.mHandler.hasMessages(BassClientService.MESSAGE_SYNC_TIMEOUT)) + .isFalse(); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); assertThat(mBassClientService.getActiveSyncedSources().size()).isEqualTo(1); @@ -1163,7 +1242,13 @@ public class BassClientServiceTest { assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - checkAndDispatchMessage(BassClientService.MESSAGE_SYNC_TIMEOUT, TEST_BROADCAST_ID); + assertThat(mBassClientService.mHandler.hasMessages(BassClientService.MESSAGE_SYNC_TIMEOUT)) + .isTrue(); + mBassClientService.mHandler.removeMessages(BassClientService.MESSAGE_SYNC_TIMEOUT); + Message newMsg = + mBassClientService.mHandler.obtainMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + newMsg.arg1 = TEST_BROADCAST_ID; + mBassClientService.mHandler.dispatchMessage(newMsg); // Check if unsyced mInOrderMethodProxy @@ -1194,9 +1279,11 @@ public class BassClientServiceTest { handleHandoverSupport(); // Source synced which cause start timeout event - checkNoMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + assertThat(mBassClientService.mHandler.hasMessages(BassClientService.MESSAGE_SYNC_TIMEOUT)) + .isFalse(); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - checkMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + assertThat(mBassClientService.mHandler.hasMessages(BassClientService.MESSAGE_SYNC_TIMEOUT)) + .isTrue(); assertThat(mBassClientService.getActiveSyncedSources().size()).isEqualTo(1); assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)) @@ -1206,7 +1293,8 @@ public class BassClientServiceTest { // Start searching again should clear timeout startSearchingForSources(); - checkNoMessage(BassClientService.MESSAGE_SYNC_TIMEOUT); + assertThat(mBassClientService.mHandler.hasMessages(BassClientService.MESSAGE_SYNC_TIMEOUT)) + .isFalse(); mInOrderMethodProxy .verify(mMethodProxy, never()) @@ -3155,11 +3243,11 @@ public class BassClientServiceTest { mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerUnregisterSync(any(), any()); - onSyncEstablished(device5, handle5); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); + onSyncEstablished(device5, handle5); assertThat(mBassClientService.getActiveSyncedSources().size()).isEqualTo(4); assertThat(mBassClientService.getActiveSyncedSources()) .containsExactly(handle2, handle3, handle4, handle5) @@ -5351,6 +5439,51 @@ public class BassClientServiceTest { @Test @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE) + @DisableFlags(Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER) + public void onSyncLost_notifySourceLostAndCancelSync_noResyncFlag() { + prepareConnectedDeviceGroup(); + startSearchingForSources(); + onScanResult(mSourceDevice, TEST_BROADCAST_ID); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + assertThat(mBassClientService.getActiveSyncedSources().size()).isEqualTo(1); + assertThat(mBassClientService.getActiveSyncedSources()).containsExactly(TEST_SYNC_HANDLE); + assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)) + .isEqualTo(mSourceDevice); + assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) + .isEqualTo(TEST_BROADCAST_ID); + + onSyncLost(); + + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + try { + verify(mCallback).onSourceLost(eq(TEST_BROADCAST_ID)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + // Cleaned all + assertThat(mBassClientService.getActiveSyncedSources()).isEmpty(); + assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) + .isEqualTo(BassConstants.INVALID_BROADCAST_ID); + + // Could try to sync again + onScanResult(mSourceDevice, TEST_BROADCAST_ID); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER + }) public void onSyncLost_notifySourceLostAndCancelSync() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -5368,6 +5501,7 @@ public class BassClientServiceTest { .isEqualTo(TEST_BROADCAST_ID); onSyncLost(); + checkAndDispatchTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_SYNC_LOST_TIMEOUT); TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); try { @@ -5390,6 +5524,92 @@ public class BassClientServiceTest { any(), any(), anyInt(), anyInt(), any(), any()); } + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE, + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER + }) + public void monitorBroadcastAfterSyncMaxLimit() { + final BluetoothDevice device1 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:11", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final BluetoothDevice device2 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:22", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final BluetoothDevice device3 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:33", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final BluetoothDevice device4 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:44", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final BluetoothDevice device5 = + mBluetoothAdapter.getRemoteLeDevice( + "00:11:22:33:44:55", BluetoothDevice.ADDRESS_TYPE_RANDOM); + final int handle1 = 0; + final int handle2 = 1; + final int handle3 = 2; + final int handle4 = 3; + final int handle5 = 4; + final int broadcastId1 = 1111; + final int broadcastId2 = 2222; + final int broadcastId3 = 3333; + final int broadcastId4 = 4444; + final int broadcastId5 = 5555; + + prepareConnectedDeviceGroup(); + startSearchingForSources(); + + // Scan and sync 5 sources cause removing 1 synced element + onScanResult(device1, broadcastId1); + onSyncEstablished(device1, handle1); + onScanResult(device2, broadcastId2); + onSyncEstablished(device2, handle2); + onScanResult(device3, broadcastId3); + onSyncEstablished(device3, handle3); + onScanResult(device4, broadcastId4); + onSyncEstablished(device4, handle4); + onScanResult(device5, broadcastId5); + mInOrderMethodProxy + .verify(mMethodProxy, times(4)) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerUnregisterSync(any(), any()); + + checkTimeout(broadcastId1, BassClientService.MESSAGE_SYNC_LOST_TIMEOUT); + + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + onSyncEstablished(device5, handle5); + + // Couldn't sync again as broadcast is in the cache + onScanResult(device1, broadcastId1); + mInOrderMethodProxy + .verify(mMethodProxy, never()) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + // Lost should notify about lost and clear cache + checkAndDispatchTimeout(broadcastId1, BassClientService.MESSAGE_SYNC_LOST_TIMEOUT); + + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + try { + verify(mCallback).onSourceLost(eq(broadcastId1)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + // Could try to sync again + onScanResult(device1, broadcastId1); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + } + private void prepareSynchronizedPair() { prepareConnectedDeviceGroup(); startSearchingForSources(); @@ -5432,7 +5652,7 @@ public class BassClientServiceTest { .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); } private void sinkUnintentionalDuringScanning() { @@ -5441,7 +5661,7 @@ public class BassClientServiceTest { // Bis and PA unsynced, SINK_UNINTENTIONAL BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); injectRemoteSourceStateChanged(meta, false, false); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); } private void checkResumeSynchronizationByBig() { @@ -5491,16 +5711,16 @@ public class BassClientServiceTest { } private void verifyStopBigMonitoringWithUnsync() { - checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerUnregisterSync(any(), any()); } private void verifyStopBigMonitoringWithoutUnsync() { - checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -5527,14 +5747,14 @@ public class BassClientServiceTest { .verify(mMethodProxy, never()) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkNoMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); } private void checkSinkPause() { BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); injectRemoteSourceStateChanged(meta, false, false); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); } @Test @@ -5807,7 +6027,7 @@ public class BassClientServiceTest { (long) 0x00000000); } } - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Unsync all sinks cause stop monitoring for (BassClientStateMachine sm : mStateMachines.values()) { @@ -5849,7 +6069,7 @@ public class BassClientServiceTest { (long) 0x00000000); } } - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Unsync all sinks cause stop monitoring for (BassClientStateMachine sm : mStateMachines.values()) { @@ -5886,7 +6106,7 @@ public class BassClientServiceTest { mCurrentDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Disconnect all sinks cause stop monitoring doReturn(BluetoothProfile.STATE_DISCONNECTED) @@ -5918,7 +6138,7 @@ public class BassClientServiceTest { mCurrentDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); // Disconnect all sinks cause stop monitoring doReturn(BluetoothProfile.STATE_DISCONNECTED) @@ -5941,10 +6161,10 @@ public class BassClientServiceTest { public void sinkUnintentional_syncLost_withoutScanning_outOfRange() { sinkUnintentionalWithoutScanning(); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); onSyncLost(); - checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( @@ -5956,8 +6176,8 @@ public class BassClientServiceTest { .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkAndDispatchMessage( - BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + checkAndDispatchTimeout( + TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); verifyStopBigMonitoringWithUnsync(); verifyRemoveMessageAndInjectSourceRemoval(); checkNoResumeSynchronizationByBig(); @@ -5971,10 +6191,10 @@ public class BassClientServiceTest { public void sinkUnintentional_syncLost_duringScanning_outOfRange() { sinkUnintentionalDuringScanning(); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); onSyncLost(); - checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( @@ -5986,8 +6206,8 @@ public class BassClientServiceTest { .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkAndDispatchMessage( - BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + checkAndDispatchTimeout( + TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); verifyStopBigMonitoringWithoutUnsync(); verifyRemoveMessageAndInjectSourceRemoval(); checkNoResumeSynchronizationByBig(); @@ -6001,7 +6221,7 @@ public class BassClientServiceTest { public void sinkUnintentional_bigMonitorTimeout_withoutScanning() { sinkUnintentionalWithoutScanning(); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + checkAndDispatchTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); verifyStopBigMonitoringWithUnsync(); verifyRemoveMessageAndInjectSourceRemoval(); checkNoResumeSynchronizationByBig(); @@ -6015,7 +6235,7 @@ public class BassClientServiceTest { public void sinkUnintentional_bigMonitorTimeout_duringScanning() { sinkUnintentionalDuringScanning(); - checkAndDispatchMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + checkAndDispatchTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); verifyStopBigMonitoringWithoutUnsync(); verifyRemoveMessageAndInjectSourceRemoval(); checkNoResumeSynchronizationByBig(); @@ -6371,11 +6591,11 @@ public class BassClientServiceTest { .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); - checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( @@ -6387,8 +6607,8 @@ public class BassClientServiceTest { .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkAndDispatchMessage( - BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT, TEST_BROADCAST_ID); + checkAndDispatchTimeout( + TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); verifyStopBigMonitoringWithUnsync(); } @@ -6407,11 +6627,11 @@ public class BassClientServiceTest { .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - checkMessage(BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BIG_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); - checkMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerRegisterSync( @@ -6424,7 +6644,7 @@ public class BassClientServiceTest { any(), any(), anyInt(), anyInt(), any(), any()); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); - checkNoMessage(BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); + checkNoTimeout(TEST_BROADCAST_ID, BassClientService.MESSAGE_BROADCAST_MONITOR_TIMEOUT); } @Test diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java index b802943b497..28b4e779eef 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java @@ -316,6 +316,8 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au * Callback invoked when a new Broadcast Source is found together with the {@link * BluetoothLeBroadcastMetadata}. * + *

    Broadcast is found when it is available for user to synchronize with it. + * * @param source {@link BluetoothLeBroadcastMetadata} representing a Broadcast Source * @hide */ @@ -443,8 +445,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au /** * Callback invoked when the Broadcast Source is lost together with source broadcast id. * - *

    This callback is to notify source lost due to periodic advertising sync lost. Callback - * client can know that the source notified by {@link + *

    Callback client can know that the source notified by {@link * Callback#onSourceFound(BluetoothLeBroadcastMetadata)} before is not available any more * after this callback. * -- GitLab From 9e813d44819e87d9e3e90229a1f42d3dc22b077f Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 10 Oct 2024 08:44:50 +0000 Subject: [PATCH 389/875] IsoManager: Fix sequence numbers for bidirectional CISes Sequence numbers shall be independent for each direction. Bug: 374949495 Test: atest net_test_btm_iso Flag: EXEMPT; Covered with newly added unit test Change-Id: I8cba32be45d0b6ebc6db70f242dad045fc35e86d --- system/stack/btm/btm_iso_impl.h | 15 +++--- system/stack/test/btm_iso_test.cc | 78 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/system/stack/btm/btm_iso_impl.h b/system/stack/btm/btm_iso_impl.h index fcd97d03326..5e563e9860e 100644 --- a/system/stack/btm/btm_iso_impl.h +++ b/system/stack/btm/btm_iso_impl.h @@ -57,7 +57,8 @@ static constexpr uint8_t kStateFlagIsCancelled = 0x20; constexpr char kBtmLogTag[] = "ISO"; struct iso_sync_info { - uint16_t seq_nb; + uint16_t tx_seq_nb; + uint16_t rx_seq_nb; }; struct iso_base { @@ -159,7 +160,7 @@ struct iso_impl { auto cis = std::unique_ptr(new iso_cis()); cis->cig_id = cig_id; cis->sdu_itv = sdu_itv_mtos; - cis->sync_info = {.seq_nb = 0}; + cis->sync_info = {.tx_seq_nb = 0, .rx_seq_nb = 0}; cis->used_credits = 0; cis->state_flags = kStateFlagsNone; conn_hdl_to_cis_map_[conn_handle] = std::move(cis); @@ -528,8 +529,8 @@ struct iso_impl { /* Calculate sequence number for the ISO data packet. * It should be incremented by 1 every SDU Interval. */ - uint16_t seq_nb = iso->sync_info.seq_nb; - iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; + uint16_t seq_nb = iso->sync_info.tx_seq_nb; + iso->sync_info.tx_seq_nb = (seq_nb + 1) & 0xffff; if (iso_credits_ == 0 || data_len > iso_buffer_size_) { iso->cr_stats.credits_underflow_bytes += data_len; @@ -681,7 +682,7 @@ struct iso_impl { auto bis = std::unique_ptr(new iso_bis()); bis->big_handle = evt.big_id; bis->sdu_itv = last_big_create_req_sdu_itv_; - bis->sync_info = {.seq_nb = 0}; + bis->sync_info = {.tx_seq_nb = 0, .rx_seq_nb = 0}; bis->used_credits = 0; bis->state_flags = kStateFlagIsBroadcast; conn_hdl_to_bis_map_[conn_handle] = std::move(bis); @@ -806,8 +807,8 @@ struct iso_impl { STREAM_TO_UINT16(seq_nb, stream); - uint16_t expected_seq_nb = iso->sync_info.seq_nb; - iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; + uint16_t expected_seq_nb = iso->sync_info.rx_seq_nb; + iso->sync_info.rx_seq_nb = (seq_nb + 1) & 0xffff; evt.evt_lost = ((1 << 16) + seq_nb - expected_seq_nb) & 0xffff; if (evt.evt_lost > 0) { diff --git a/system/stack/test/btm_iso_test.cc b/system/stack/test/btm_iso_test.cc index 50a4948b34b..3cb550b04dc 100644 --- a/system/stack/test/btm_iso_test.cc +++ b/system/stack/test/btm_iso_test.cc @@ -2085,6 +2085,84 @@ TEST_F(IsoManagerTest, SendIsoDataCigValid) { } } +TEST_F(IsoManagerTest, SendReceiveIsoDataSequenceNumberCheck) { + IsoManager::GetInstance()->CreateCig(volatile_test_cig_create_cmpl_evt_.cig_id, + kDefaultCigParams); + + bluetooth::hci::iso_manager::cis_establish_params params; + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + params.conn_pairs.push_back({handle, 1}); + } + IsoManager::GetInstance()->EstablishCis(params); + + for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { + bluetooth::hci::iso_manager::iso_data_path_params path_params = kDefaultIsoDataPathParams; + path_params.data_path_dir = bluetooth::hci::iso_manager::kIsoDataPathDirectionOut; + IsoManager::GetInstance()->SetupIsoDataPath(handle, path_params); + + constexpr uint8_t data_len = 108; + uint16_t seq_num = 0xFFFF; + + EXPECT_CALL(iso_interface_, HciSend) + .WillRepeatedly([handle, data_len, &seq_num](BT_HDR* p_msg) { + uint8_t* p = p_msg->data; + uint16_t msg_handle; + uint16_t iso_load_len; + + ASSERT_NE(p_msg, nullptr); + ASSERT_EQ(p_msg->len, + data_len + ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) ? 12 : 8)); + + // Verify packet internals + STREAM_TO_UINT16(msg_handle, p); + ASSERT_EQ(msg_handle, handle); + + STREAM_TO_UINT16(iso_load_len, p); + ASSERT_EQ(iso_load_len, + data_len + ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) ? 8 : 4)); + + if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) { + STREAM_SKIP_UINT16(p); // skip ts LSB halfword + STREAM_SKIP_UINT16(p); // skip ts MSB halfword + } + // store the seq_nb + STREAM_TO_UINT16(seq_num, p); + + uint16_t msg_data_len; + STREAM_TO_UINT16(msg_data_len, p); + ASSERT_EQ(msg_data_len, data_len); + }) + .RetiresOnSaturation(); + + // Send Iso data and verify the sequence number + std::vector data_vec(data_len, 0); + IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), data_vec.size()); + IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), data_vec.size()); + ASSERT_NE(0xFFFF, seq_num); + + // Check the receiving iso packet + // EXPECT_CALL(*cig_callbacks_, OnCisEvent).Times(1); + EXPECT_CALL(*cig_callbacks_, + OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDataAvailable, _)) + .WillOnce([](uint8_t /*evt_code*/, void* event) { + bluetooth::hci::iso_manager::cis_data_evt* cis_data_evt = + static_cast(event); + // Make sure no event lost is reported due to seq_nb being shared between two + // directions + ASSERT_EQ(cis_data_evt->evt_lost, 0); + }); + + std::vector dummy_msg(18); + uint8_t* p = dummy_msg.data(); + UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_ISO); + UINT16_TO_STREAM(p, 10); // .len + UINT16_TO_STREAM(p, 0); // .offset + UINT16_TO_STREAM(p, 0); // .layer_specific + UINT16_TO_STREAM(p, handle); + IsoManager::GetInstance()->HandleIsoData(dummy_msg.data()); + } +} + TEST_F(IsoManagerTest, SendIsoDataBigValid) { IsoManager::GetInstance()->CreateBig(volatile_test_big_params_evt_.big_id, kDefaultBigParams); -- GitLab From c1f6ac4f7150e866596c7fb1993879d0fc96637c Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 22 Oct 2024 12:18:33 +0200 Subject: [PATCH 390/875] Remove cleanup_le_only_device_type Bug: 333949759 Test: mma -j32; Flag: com.android.bluetooth.flags.cleanup_le_only_device_type Change-Id: I0c06de4cfe85833d62fbc97d971295beea04233b --- .../android/bluetooth/btservice/AdapterProperties.java | 10 +++------- flags/pairing.aconfig | 7 ------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index 42191c742ce..43752e6faf3 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -531,7 +531,7 @@ class AdapterProperties { return; } - if (Flags.cleanupLeOnlyDeviceType() && deviceType != BluetoothDevice.DEVICE_TYPE_LE) { + if (deviceType != BluetoothDevice.DEVICE_TYPE_LE) { return; } @@ -547,12 +547,8 @@ class AdapterProperties { boolean removeExisting = false; if (identityAddress.equals(existingIdentityAddress) && !address.equals(existingAddress)) { - if (Flags.cleanupLeOnlyDeviceType()) { - // Existing device record should be removed only if the device type is LE-only - removeExisting = (existingDeviceType == BluetoothDevice.DEVICE_TYPE_LE); - } else { - removeExisting = true; - } + // Existing device record should be removed only if the device type is LE-only + removeExisting = (existingDeviceType == BluetoothDevice.DEVICE_TYPE_LE); } if (removeExisting) { diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig index 8acd9afbc72..66ab03984c2 100644 --- a/flags/pairing.aconfig +++ b/flags/pairing.aconfig @@ -11,13 +11,6 @@ flag { } } -flag { - name: "cleanup_le_only_device_type" - namespace: "bluetooth" - description: "Cleanup the duplicate bond records only if the device type is LE-only" - bug: "333949759" -} - flag { name: "pairing_on_unknown_transport" namespace: "bluetooth" -- GitLab From 4210130a2fe417cf53d7d3629e8d6e1646576801 Mon Sep 17 00:00:00 2001 From: Rishab Date: Tue, 22 Oct 2024 18:02:20 +0000 Subject: [PATCH 391/875] Define flag support_remote_device_metadata for remote device metadata API changes Test: m com.android.btservices Bug: 374171574 Bug: 358631232 Change-Id: Ic78ed459dd9778cfe449c5eed5ca9be08bd477d9 --- flags/framework.aconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flags/framework.aconfig b/flags/framework.aconfig index 7834bfd524b..1ce042e583c 100644 --- a/flags/framework.aconfig +++ b/flags/framework.aconfig @@ -63,3 +63,11 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "support_remote_device_metadata" + is_exported: true + namespace: "bluetooth" + description: "Support setting/retrieving the remote device metadata for a BluetoothDevice" + bug: "374171574" +} \ No newline at end of file -- GitLab From 14cff6158b66052d12c5b0e5a2f12ed9e9f7900a Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Sat, 12 Oct 2024 09:05:19 -0700 Subject: [PATCH 392/875] stack::avct: Associate browse l2cap channel with active link Bug: 373471940 Bug: 373482555 Test: Manual Test: m . Flag: associate_browse_l2cap_request_with_active_control_channel Change-Id: I60f5e70c4c13c17b4f2680a57e4fa362625490d6 --- system/stack/avct/avct_bcb_act.cc | 75 ++++++++++++++++++------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/system/stack/avct/avct_bcb_act.cc b/system/stack/avct/avct_bcb_act.cc index 75d54bbcee7..96938883707 100644 --- a/system/stack/avct/avct_bcb_act.cc +++ b/system/stack/avct/avct_bcb_act.cc @@ -31,14 +31,13 @@ #include #include -#include "avct_api.h" -#include "avct_int.h" #include "bta/include/bta_sec_api.h" #include "btif/include/btif_av.h" #include "internal_include/bt_target.h" #include "osi/include/allocator.h" -#include "osi/include/osi.h" #include "stack/avct/avct_defs.h" +#include "stack/avct/avct_int.h" +#include "stack/include/avct_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" #include "stack/include/l2cap_interface.h" @@ -162,56 +161,68 @@ void avct_bcb_unbind_disc(tAVCT_BCB* /* p_bcb */, tAVCT_LCB_EVT* p_data) { * Returns Nothing. * ******************************************************************************/ +namespace { +bool is_valid_role_check(const tAVCT_CCB* p_ccb) { + return com::android::bluetooth::flags:: + associate_browse_l2cap_request_with_active_control_channel() + ? true + : p_ccb->cc.role == AVCT_ACP; +} +} // namespace + void avct_bcb_open_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; - tAVCT_CCB* p_ccb_bind = NULL; - bool bind = false; - tAVCT_UL_MSG ul_msg; + tAVCT_CCB* p_ccb_bind = nullptr; for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { - /* if ccb allocated and */ - if (p_ccb->allocated) { - /* if bound to this bcb send connect confirm event */ - if (p_ccb->p_bcb == p_bcb) { - bind = true; - p_ccb_bind = p_ccb; - p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_CFM_EVT, 0, - &p_ccb->p_lcb->peer_addr); - } + if (!p_ccb->allocated) { + continue; + } + + /* if ccb allocated and bound to this bcb send connect confirm event */ + if (p_ccb->p_bcb == p_bcb) { + p_ccb_bind = p_ccb; + p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_CFM_EVT, 0, + &p_ccb->p_lcb->peer_addr); + } else if ((p_ccb->p_bcb == NULL) && is_valid_role_check(p_ccb) && (p_ccb->p_lcb != NULL) && + p_bcb->peer_addr == p_ccb->p_lcb->peer_addr) { /* if unbound acceptor and lcb allocated and bd_addr are the same for bcb and lcb */ - else if ((p_ccb->p_bcb == NULL) && (p_ccb->cc.role == AVCT_ACP) && (p_ccb->p_lcb != NULL) && - p_bcb->peer_addr == p_ccb->p_lcb->peer_addr) { - /* bind bcb to ccb and send connect ind event */ - bind = true; - p_ccb_bind = p_ccb; - p_ccb->p_bcb = p_bcb; - p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_IND_EVT, 0, - &p_ccb->p_lcb->peer_addr); - } + /* bind bcb to ccb and send connect ind event */ + p_ccb_bind = p_ccb; + p_ccb->p_bcb = p_bcb; + p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_IND_EVT, 0, + &p_ccb->p_lcb->peer_addr); } } /* if no ccbs bound to this lcb, disconnect */ - if (!bind) { + if (p_ccb_bind == nullptr) { + log::warn("Ignoring incoming browse request and closing channel from peer:{} lcid:0x{:04x}", + p_bcb->peer_addr, p_bcb->ch_lcid); avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data); return; } - if (!p_bcb->p_tx_msg || !p_ccb_bind) { + if (!p_bcb->p_tx_msg) { + log::warn("Received browse packet with no browse data peer:{} lcid:0x{:04x}", p_bcb->peer_addr, + p_bcb->ch_lcid); return; } - ul_msg.p_buf = p_bcb->p_tx_msg; - ul_msg.p_ccb = p_ccb_bind; - ul_msg.label = (uint8_t)(p_bcb->p_tx_msg->layer_specific & 0xFF); - ul_msg.cr = (uint8_t)((p_bcb->p_tx_msg->layer_specific & 0xFF00) >> 8); + tAVCT_UL_MSG ul_msg = { + .p_buf = p_bcb->p_tx_msg, + .p_ccb = p_ccb_bind, + .label = (uint8_t)(p_bcb->p_tx_msg->layer_specific & 0xFF), + .cr = (uint8_t)((p_bcb->p_tx_msg->layer_specific & 0xFF00) >> 8), + }; p_bcb->p_tx_msg->layer_specific = AVCT_DATA_BROWSE; p_bcb->p_tx_msg = NULL; /* send msg event to bcb */ - tAVCT_LCB_EVT avct_lcb_evt; - avct_lcb_evt.ul_msg = ul_msg; + tAVCT_LCB_EVT avct_lcb_evt = { + .ul_msg = ul_msg, + }; avct_bcb_event(p_bcb, AVCT_LCB_UL_MSG_EVT, &avct_lcb_evt); } -- GitLab From 2def12c612304ec826daa5b7f6545728a31ba534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 11 Oct 2024 09:10:18 +0000 Subject: [PATCH 393/875] BluetoothLeAudio: Use new API flag for API changes on Mono errata Since API change is later then we want deliver stack changes, we use new flag for API changes Bug: 330847930 Bug: 372840605 Test: mmm packages/modules/Bluetooth Flag: com::android::bluetooth:flags::leaudio_mono_location_errata_api Change-Id: Icb811d399078f8b8bde2c84672f3519b983c34bf --- framework/api/system-current.txt | 6 +++--- framework/java/android/bluetooth/BluetoothLeAudio.java | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 8fb6d6940a4..d4aadc4e9f9 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -479,11 +479,11 @@ package android.bluetooth { field public static final int AUDIO_LOCATION_FRONT_RIGHT = 2; // 0x2 field public static final int AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER = 128; // 0x80 field public static final int AUDIO_LOCATION_FRONT_RIGHT_WIDE = 33554432; // 0x2000000 - field @Deprecated @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata") public static final int AUDIO_LOCATION_INVALID = 0; // 0x0 + field @Deprecated @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata_api") public static final int AUDIO_LOCATION_INVALID = 0; // 0x0 field public static final int AUDIO_LOCATION_LEFT_SURROUND = 67108864; // 0x4000000 field public static final int AUDIO_LOCATION_LOW_FREQ_EFFECTS_ONE = 8; // 0x8 field public static final int AUDIO_LOCATION_LOW_FREQ_EFFECTS_TWO = 512; // 0x200 - field @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata") public static final int AUDIO_LOCATION_MONO = 0; // 0x0 + field @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata_api") public static final int AUDIO_LOCATION_MONO = 0; // 0x0 field public static final int AUDIO_LOCATION_RIGHT_SURROUND = 134217728; // 0x8000000 field public static final int AUDIO_LOCATION_SIDE_LEFT = 1024; // 0x400 field public static final int AUDIO_LOCATION_SIDE_RIGHT = 2048; // 0x800 @@ -496,7 +496,7 @@ package android.bluetooth { field public static final int AUDIO_LOCATION_TOP_FRONT_RIGHT = 8192; // 0x2000 field public static final int AUDIO_LOCATION_TOP_SIDE_LEFT = 262144; // 0x40000 field public static final int AUDIO_LOCATION_TOP_SIDE_RIGHT = 524288; // 0x80000 - field @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata") public static final int AUDIO_LOCATION_UNKNOWN = -2147483648; // 0x80000000 + field @FlaggedApi("com.android.bluetooth.flags.leaudio_mono_location_errata_api") public static final int AUDIO_LOCATION_UNKNOWN = -2147483648; // 0x80000000 field public static final String EXTRA_LE_AUDIO_GROUP_ID = "android.bluetooth.extra.LE_AUDIO_GROUP_ID"; field public static final int GROUP_STREAM_STATUS_IDLE = 0; // 0x0 field public static final int GROUP_STREAM_STATUS_STREAMING = 1; // 0x1 diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index c11efe16835..6bc4a73de97 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -367,7 +367,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { * with a meaning MONO. * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA) + @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA_API) @Deprecated @SystemApi public static final int AUDIO_LOCATION_INVALID = 0; @@ -377,7 +377,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { * * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA) + @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA_API) @SystemApi public static final int AUDIO_LOCATION_MONO = 0; @@ -386,7 +386,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { * * @hide */ - @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA) + @FlaggedApi(Flags.FLAG_LEAUDIO_MONO_LOCATION_ERRATA_API) @SystemApi public static final int AUDIO_LOCATION_UNKNOWN = 0x01 << 31; @@ -1186,6 +1186,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) + @SuppressWarnings("FlaggedApi") // Due to deprecated AUDIO_LOCATION_INVALID public @AudioLocation int getAudioLocation(@NonNull BluetoothDevice device) { if (VDBG) log("getAudioLocation()"); final IBluetoothLeAudio service = getService(); @@ -1200,7 +1201,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { } } - if (Flags.leaudioMonoLocationErrata() + if (Flags.leaudioMonoLocationErrataApi() && CompatChanges.isChangeEnabled(LEAUDIO_MONO_LOCATION_ERRATA)) { return AUDIO_LOCATION_UNKNOWN; } -- GitLab From 28b3e4841200269f90bc98002fc3b3d6ba5e2edd Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Mon, 14 Oct 2024 18:09:53 +0200 Subject: [PATCH 394/875] Make it obvious that connection_manager is separate from GATT Even though it now shares client identifiers with GATT, the plan is to have it as independent piece of stack. connection_manager is also used from L2CAP, and it looks improper when l2cap relies on some GATT related things. Test: mma -j32 Bug: 372202918 Flag: EXEMPT, just renaming/moving code Change-Id: I7ae54072f140c360edac64ab4e1c9bcef72b1695 --- system/bta/Android.bp | 1 + system/bta/dm/bta_dm_act.cc | 2 +- system/btif/src/bluetooth.cc | 2 +- system/stack/Android.bp | 15 +++++++++------ system/stack/BUILD.gn | 2 +- system/stack/acl/ble_acl.cc | 2 +- system/stack/btm/btm_devctl.cc | 2 +- .../connection_manager.cc | 0 .../connection_manager.h | 0 system/stack/gatt/gatt_api.cc | 2 +- system/stack/gatt/gatt_main.cc | 2 +- system/stack/gatt/gatt_utils.cc | 2 +- system/stack/l2cap/l2c_ble.cc | 2 +- ...manager_test.cc => connection_manager_test.cc} | 3 ++- system/stack/test/gatt/mock_gatt_utils_ref.cc | 2 +- system/test/Android.bp | 7 +++++++ system/test/headless/bt_stack_info.cc | 2 +- ...anager.cc => mock_stack_connection_manager.cc} | 8 +++++++- 18 files changed, 37 insertions(+), 19 deletions(-) rename system/stack/{gatt => connection_manager}/connection_manager.cc (100%) rename system/stack/{gatt => connection_manager}/connection_manager.h (100%) rename system/stack/test/{gatt_connection_manager_test.cc => connection_manager_test.cc} (99%) rename system/test/mock/{mock_stack_gatt_connection_manager.cc => mock_stack_connection_manager.cc} (92%) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 235246605f2..64c44d250cf 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -260,6 +260,7 @@ cc_test { ":TestMockStackAvdt", ":TestMockStackAvrc", ":TestMockStackBtm", + ":TestMockStackConnMgr", ":TestMockStackGap", ":TestMockStackGatt", ":TestMockStackHid", diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 1d1d5c589de..792aa44b6e3 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -52,7 +52,7 @@ #include "main/shim/entry.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index f246ca1be87..a5a2e54f203 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -100,7 +100,7 @@ #include "osi/include/wakelock.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sco_hfp_hal.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/a2dp_api.h" #include "stack/include/avdt_api.h" #include "stack/include/btm_client_interface.h" diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 5fec9d2cee2..1161cae7ca5 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -275,11 +275,11 @@ cc_library_static { "btm/security_event_parser.cc", "btu/btu_event.cc", "btu/btu_hcif.cc", + "connection_manager/connection_manager.cc", "eatt/eatt.cc", "gap/gap_ble.cc", "gap/gap_conn.cc", "gatt/att_protocol.cc", - "gatt/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", @@ -540,6 +540,7 @@ cc_fuzz { ":TestMockStackAcl", ":TestMockStackArbiter", ":TestMockStackBtm", + ":TestMockStackConnMgr", ":TestMockStackHcic", ":TestMockStackL2cap", ":TestMockStackMetrics", @@ -1067,7 +1068,7 @@ cc_test { // Bluetooth stack connection multiplexing cc_test { - name: "net_test_gatt_conn_multiplexing", + name: "net_test_conn_multiplexing", defaults: [ "fluoride_defaults", "mts_defaults", @@ -1086,9 +1087,9 @@ cc_test { srcs: [ ":TestCommonMainHandler", ":TestMockStackBtmInterface", - "gatt/connection_manager.cc", + "connection_manager/connection_manager.cc", "test/common/mock_btm_api_layer.cc", - "test/gatt_connection_manager_test.cc", + "test/connection_manager_test.cc", ], shared_libs: [ "libcutils", @@ -1652,6 +1653,7 @@ cc_test { ":TestMockMainShimEntry", ":TestMockRustFfi", ":TestMockStackBtu", + ":TestMockStackConnMgr", ":TestMockStackGap", ":TestMockStackGatt", ":TestMockStackHcic", @@ -1972,9 +1974,9 @@ cc_test { ":TestMockStackSmp", "ais/ais_ble.cc", "arbiter/acl_arbiter.cc", + "connection_manager/connection_manager.cc", "eatt/eatt.cc", "gatt/att_protocol.cc", - "gatt/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", @@ -2067,7 +2069,7 @@ cc_test { ":TestMockMainShimEntry", ":TestMockStackAcl", ":TestMockStackBtm", - ":TestMockStackGatt", + ":TestMockStackConnMgr", ":TestMockStackHcic", ":TestMockStackSdp", ":TestMockStackSmp", @@ -2164,6 +2166,7 @@ cc_test { ":TestMockRustFfi", ":TestMockStackBtm", ":TestMockStackBtu", + ":TestMockStackConnMgr", ":TestMockStackGatt", ":TestMockStackHcic", ":TestMockStackL2cap", diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn index c2b87b44a55..559aa1f366c 100644 --- a/system/stack/BUILD.gn +++ b/system/stack/BUILD.gn @@ -125,7 +125,7 @@ source_set("stack") { "gap/gap_ble.cc", "gap/gap_conn.cc", "gatt/att_protocol.cc", - "gatt/connection_manager.cc", + "connection_manager/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index 1f5d5b580c3..0606716f757 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -25,7 +25,7 @@ #include "stack/btm/btm_dev.h" #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/btm_ble_addr.h" #include "stack/include/btm_ble_privacy.h" diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc index 86f4af00e4b..d22fba73c77 100644 --- a/system/stack/btm/btm_devctl.cc +++ b/system/stack/btm/btm_devctl.cc @@ -38,7 +38,7 @@ #include "main/shim/entry.h" #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/acl_api_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/gatt/connection_manager.cc b/system/stack/connection_manager/connection_manager.cc similarity index 100% rename from system/stack/gatt/connection_manager.cc rename to system/stack/connection_manager/connection_manager.cc diff --git a/system/stack/gatt/connection_manager.h b/system/stack/connection_manager/connection_manager.h similarity index 100% rename from system/stack/gatt/connection_manager.h rename to system/stack/connection_manager/connection_manager.h diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index d9d7f051d95..7ed0fe05160 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -37,7 +37,7 @@ #include "osi/include/allocator.h" #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/gatt/gatt_int.h" #include "stack/include/ais_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index bc559a5715c..f5591d21948 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -28,7 +28,6 @@ #include "btif/include/btif_dm.h" #include "btif/include/btif_storage.h" #include "btif/include/stack_manager_t.h" -#include "connection_manager.h" #include "device/include/interop.h" #include "internal_include/bt_target.h" #include "internal_include/stack_config.h" @@ -38,6 +37,7 @@ #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/eatt/eatt.h" #include "stack/gatt/gatt_int.h" #include "stack/include/acl_api.h" diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index 72083acb500..d159bbd794a 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -38,8 +38,8 @@ #include "osi/include/properties.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/eatt/eatt.h" -#include "stack/gatt/connection_manager.h" #include "stack/gatt/gatt_int.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_psm_types.h" diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index a00e0d17f46..fe22262b89a 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -44,7 +44,7 @@ #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" #include "stack/btm/btm_sec_int_types.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/test/gatt_connection_manager_test.cc b/system/stack/test/connection_manager_test.cc similarity index 99% rename from system/stack/test/gatt_connection_manager_test.cc rename to system/stack/test/connection_manager_test.cc index afe3fcba4e8..cbb7b3ff35d 100644 --- a/system/stack/test/gatt_connection_manager_test.cc +++ b/system/stack/test/connection_manager_test.cc @@ -1,3 +1,5 @@ +#include "stack/connection_manager/connection_manager.h" + #include #include #include @@ -11,7 +13,6 @@ #include "osi/test/alarm_mock.h" #include "security_device_record.h" #include "stack/btm/neighbor_inquiry.h" -#include "stack/gatt/connection_manager.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc index f79db0ac3d8..2f392b3e90a 100644 --- a/system/stack/test/gatt/mock_gatt_utils_ref.cc +++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc @@ -22,7 +22,7 @@ #pragma GCC diagnostic ignored "-Wmissing-prototypes" #pragma GCC diagnostic ignored "-Wunused-parameter" -/** stack/gatt/connection_manager.cc */ +/** stack/connection_manager/connection_manager.cc */ namespace connection_manager { bool background_connect_remove(uint8_t app_id, const RawAddress& address) { return false; } bool direct_connect_remove(uint8_t app_id, const RawAddress& address, bool connection_timeout) { diff --git a/system/test/Android.bp b/system/test/Android.bp index a78ed4e8ef8..d4a1a767eb8 100644 --- a/system/test/Android.bp +++ b/system/test/Android.bp @@ -483,6 +483,13 @@ filegroup { ], } +filegroup { + name: "TestMockStackConnMgr", + srcs: [ + "mock/mock_stack_connection_manager.cc", + ], +} + filegroup { name: "TestMockStackEatt", srcs: [ diff --git a/system/test/headless/bt_stack_info.cc b/system/test/headless/bt_stack_info.cc index ad00ba5c6b5..300dbf62b78 100644 --- a/system/test/headless/bt_stack_info.cc +++ b/system/test/headless/bt_stack_info.cc @@ -21,7 +21,7 @@ #include "btif/include/btif_common.h" // do_in_jni_thread #include "btif/include/btif_hh.h" // DumpsysHid #include "main/shim/dumpsys.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/main_thread.h" #include "stack/include/pan_api.h" // PAN_Dumpsys #include "test/headless/log.h" diff --git a/system/test/mock/mock_stack_gatt_connection_manager.cc b/system/test/mock/mock_stack_connection_manager.cc similarity index 92% rename from system/test/mock/mock_stack_gatt_connection_manager.cc rename to system/test/mock/mock_stack_connection_manager.cc index f0f33dddb5e..97cd1608548 100644 --- a/system/test/mock/mock_stack_gatt_connection_manager.cc +++ b/system/test/mock/mock_stack_connection_manager.cc @@ -21,12 +21,18 @@ #include -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" using namespace connection_manager; +bool connection_manager::background_connect_targeted_announcement_add( + tAPP_ID /* app_id */, const RawAddress& /* address */) { + inc_func_call_count(__func__); + return false; +} + bool connection_manager::background_connect_add(uint8_t /* app_id */, const RawAddress& /* address */) { inc_func_call_count(__func__); -- GitLab From 5df81d0a78b233952421eba8256f1b78ba24ed92 Mon Sep 17 00:00:00 2001 From: zhidou Date: Tue, 22 Oct 2024 19:16:07 +0000 Subject: [PATCH 395/875] add the flag declaration in the framework Test: atest BluetoothInstrumentationTests Bug: 361398259 FLAG: NONE build file change Change-Id: Ibdff295d2a182c69ee7d66fcde7de6cf8d96bca6 --- flags/Android.bp | 3 +++ framework/Android.bp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/flags/Android.bp b/flags/Android.bp index db47305e1e1..56acb5c0d8e 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -7,6 +7,9 @@ aconfig_declarations { name: "bluetooth_aconfig_flags", package: "com.android.bluetooth.flags", container: "com.android.btservices", + visibility: [ + "//packages/modules/Bluetooth/framework", + ], // LINT.IfChange srcs: [ "a2dp.aconfig", diff --git a/framework/Android.bp b/framework/Android.bp index 9fa8d9a1608..5be5ed9c249 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -91,6 +91,9 @@ java_sdk_library { plugins: [ "error_prone_android_framework", ], + aconfig_declarations: [ + "bluetooth_aconfig_flags", + ], lint: { error_checks: [ "Autofill", -- GitLab From ae49fae55eef43684db1ab0dbaf811ec30bd49ce Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 22 Oct 2024 14:06:26 +0200 Subject: [PATCH 396/875] Make connection_manager dumpsys more concise Test: mma -j32 Bug: 372202918 Flag: EXEMPT, just dumpsys change Change-Id: I6cd8fbb1b0c0c10c8069fd6d767a85e1365ec7db --- .../stack/connection_manager/connection_manager.cc | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/system/stack/connection_manager/connection_manager.cc b/system/stack/connection_manager/connection_manager.cc index 96278a91064..c29ac5d4031 100644 --- a/system/stack/connection_manager/connection_manager.cc +++ b/system/stack/connection_manager/connection_manager.cc @@ -581,7 +581,10 @@ void dump(int fd) { dprintf(fd, "\tdevices attempting connection: %d", (int)bgconn_dev.size()); for (const auto& entry : bgconn_dev) { // TODO: confirm whether we need to replace this - dprintf(fd, "\n\t * %s: ", ADDRESS_TO_LOGGABLE_CSTR(entry.first)); + dprintf(fd, "\n\t * %s:\t\tin_accept_list: %s\t cap_targeted_announcements: %s", + ADDRESS_TO_LOGGABLE_CSTR(entry.first), + entry.second.is_in_accept_list ? "true" : "false", + entry.second.doing_targeted_announcements_conn.empty() ? "false" : "true"); if (!entry.second.doing_direct_conn.empty()) { dprintf(fd, "\n\t\tapps doing direct connect: "); @@ -596,14 +599,6 @@ void dump(int fd) { dprintf(fd, "%d, ", id); } } - if (!entry.second.doing_targeted_announcements_conn.empty()) { - dprintf(fd, "\n\t\tapps doing cap announcement connect: "); - for (const auto& id : entry.second.doing_targeted_announcements_conn) { - dprintf(fd, "%d, ", id); - } - } - dprintf(fd, "\n\t\t is in the allow list: %s", - entry.second.is_in_accept_list ? "true" : "false"); } dprintf(fd, "\n"); } -- GitLab From 023cccba4da6d98e498f09c8f3ed2246fabee392 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 17 Oct 2024 17:56:01 -0700 Subject: [PATCH 397/875] errorprone: activate EnumOrdinal Bug: 344658662 Test: m com.android.btservices Flag: Exempt lint enforcement Change-Id: I2951e2a779749f181ff713f923c098d838ba0965 --- Android.bp | 1 + .../bluetooth/map/BluetoothMapContentObserver.java | 3 +++ android/app/src/com/android/bluetooth/tbs/TbsGatt.java | 3 ++- .../bluetooth/map/BluetoothMapContentObserverTest.java | 8 ++------ 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Android.bp b/Android.bp index 7e5bf156bf2..4a5ba15f664 100644 --- a/Android.bp +++ b/Android.bp @@ -112,6 +112,7 @@ java_defaults { "-Xep:DirectInvocationOnMock:ERROR", "-Xep:EmptyBlockTag:ERROR", "-Xep:EmptyCatch:ERROR", + "-Xep:EnumOrdinal:ERROR", "-Xep:EqualsGetClass:ERROR", "-Xep:EqualsHashCode:ERROR", "-Xep:EqualsIncompatibleType:ERROR", diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java index f70903f1bed..e0fce723380 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java @@ -3352,6 +3352,7 @@ public class BluetoothMapContentObserver { return handle; } + @SuppressWarnings("EnumOrdinal") // remove entire usage of internal intent public long sendMmsMessage( String folder, String[] toAddress, @@ -4090,6 +4091,7 @@ public class BluetoothMapContentObserver { } } + @SuppressWarnings("EnumOrdinal") // remove entire usage of internal intent public static void actionMessageSentDisconnected(Context context, Intent intent, int result) { TYPE type = TYPE.fromOrdinal( @@ -4277,6 +4279,7 @@ public class BluetoothMapContentObserver { } } + @SuppressWarnings("EnumOrdinal") // remove entire usage of internal intent public boolean handleSmsSendIntent(Context context, Intent intent) { TYPE type = TYPE.fromOrdinal( diff --git a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java index af1cc022910..803b249a3d2 100644 --- a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java +++ b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java @@ -1036,6 +1036,7 @@ public class TbsGatt { return mTbsService.getDeviceAuthorization(device); } + @SuppressWarnings("EnumOrdinal") private void onRejectedAuthorizationGattOperation(BluetoothDevice device, GattOpContext op) { UUID charUuid = (op.mCharacteristic != null @@ -1102,7 +1103,7 @@ public class TbsGatt { boolean allowToReadRealValue = false; byte[] buffer = null; - /* Allow only some informations to be disclosed at this stage. */ + /* Allow only some information to be disclosed at this stage. */ if (charUuid.equals(UUID_BEARER_PROVIDER_NAME)) { ByteBuffer bb = ByteBuffer.allocate(0).order(ByteOrder.LITTLE_ENDIAN); bb.put("".getBytes()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java index e8f65e39667..042666d3218 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java @@ -2156,9 +2156,7 @@ public class BluetoothMapContentObserverTest { // This mock sets type to MMS doReturn(4) .when(mIntent) - .getIntExtra( - BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_MSG_TYPE, - TYPE.NONE.ordinal()); + .getIntExtra(eq(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_MSG_TYPE), anyInt()); mObserver.actionMessageSentDisconnected(mContext, mIntent, 1); @@ -2177,9 +2175,7 @@ public class BluetoothMapContentObserverTest { // This mock sets type to Email doReturn(1) .when(mIntent) - .getIntExtra( - BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_MSG_TYPE, - TYPE.NONE.ordinal()); + .getIntExtra(eq(BluetoothMapContentObserver.EXTRA_MESSAGE_SENT_MSG_TYPE), anyInt()); clearInvocations(mContext); mObserver.actionMessageSentDisconnected(mContext, mIntent, Activity.RESULT_FIRST_USER); -- GitLab From 3cfe3789b943ca6dfae8d8d997af2df74e2ddc9d Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 22 Oct 2024 11:35:09 -0700 Subject: [PATCH 398/875] btif_a2dp_source: Suppress underflow warning after stream is stopped Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I8579f3af9589a2744f7f534872c4685776767c28 --- system/btif/src/btif_a2dp_source.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index e4b197845a5..af1e7244b01 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -915,9 +915,13 @@ static void btif_a2dp_source_audio_handle_timer(void) { } static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) { + if (!btif_a2dp_source_cb.sw_audio_is_encoding) { + return 0; + } + uint32_t bytes_read = bluetooth::audio::a2dp::read(p_buf, len); - if (btif_a2dp_source_cb.sw_audio_is_encoding && bytes_read < len) { + if (bytes_read < len) { log::warn("UNDERFLOW: ONLY READ {} BYTES OUT OF {}", bytes_read, len); btif_a2dp_source_cb.stats.media_read_total_underflow_bytes += (len - bytes_read); btif_a2dp_source_cb.stats.media_read_total_underflow_count++; -- GitLab From eda47ee2172978bea8315780e06f11589ffd511e Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Tue, 22 Oct 2024 16:31:00 -0700 Subject: [PATCH 399/875] Remove dependencies on the 1-variant fallback When adding a dependencies, if the variants don't match, but the dependency only has 1 variant anyways, soong will always use that variant. This makes it hard to add new variants to soong, because the 1-variant fallback stops being used and you start getting missing variant errors. Make changes to bp files such that all dependencies correctly specify the variant to use. Bug: 372091092 Flag: EXEMPT refactor Test: m nothing Change-Id: I586e9329c22fa94c2fe83a56dc34dff1fe311900 --- android/pandora/test/Android.bp | 8 ++++++-- framework/tests/bumble/Android.bp | 6 ++++-- framework/tests/metrics/host/Android.bp | 2 +- system/Android.bp | 4 +++- system/bta/Android.bp | 8 ++++---- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/android/pandora/test/Android.bp b/android/pandora/test/Android.bp index 0b75292c3cf..cc961871a7a 100644 --- a/android/pandora/test/Android.bp +++ b/android/pandora/test/Android.bp @@ -39,9 +39,11 @@ python_test_host { unit_test: false, }, data: [ - ":PandoraServer", "config.yml", ], + device_common_data: [ + ":PandoraServer", + ], } python_test_host { @@ -68,9 +70,11 @@ python_test_host { unit_test: false, }, data: [ - ":PandoraServer", "config.yml", ], + device_common_data: [ + ":PandoraServer", + ], } sh_binary_host { diff --git a/framework/tests/bumble/Android.bp b/framework/tests/bumble/Android.bp index a97112171cb..6c516acf11c 100644 --- a/framework/tests/bumble/Android.bp +++ b/framework/tests/bumble/Android.bp @@ -54,7 +54,7 @@ java_test_host { "tradefed", ], - data: [ + device_common_data: [ ":BumbleBluetoothTestsApp", "bumble_config.json", ], @@ -80,9 +80,11 @@ java_test_host { ], data: [ - ":BumbleBluetoothTestsApp", "bumble_config.json", ], + device_common_data: [ + ":BumbleBluetoothTestsApp", + ], data_native_bins: [ "bumble_pandora_server", ], diff --git a/framework/tests/metrics/host/Android.bp b/framework/tests/metrics/host/Android.bp index f90e35a29d7..4bb72818a16 100644 --- a/framework/tests/metrics/host/Android.bp +++ b/framework/tests/metrics/host/Android.bp @@ -16,7 +16,7 @@ java_test_host { "tradefed", ], - data: [ + device_common_data: [ ":BluetoothMetricsTestApp", ], diff --git a/system/Android.bp b/system/Android.bp index b788868c0e4..b79fa124894 100644 --- a/system/Android.bp +++ b/system/Android.bp @@ -307,11 +307,13 @@ cc_genrule { ":BlueberryFacadeAndCertGeneratedStub_py", ":bluetooth_cert_test_host_deps-zip", ":bluetooth_cert_test_sources-zip", - ":bluetooth_cert_test_target_deps-zip", ":gd_hci_packets_python3_gen-zip", ":gd_smp_packets_python3_gen-zip", ":llvm-tools-zip", ], + device_first_srcs: [ + ":bluetooth_cert_test_target_deps-zip", + ], out: ["bluetooth_cert_tests.zip"], cmd: "$(location merge_zips) $(genDir)/temp.zip $(in) && " + "unzip -q -d $(genDir)/files $(genDir)/temp.zip && " + diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 235246605f2..9bfe5f6d7e0 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -325,7 +325,7 @@ cc_test { "libgmock", "server_configurable_flags", ], - data: [ + device_first_data: [ ":audio_set_configurations_bfbs", ":audio_set_configurations_json", ":audio_set_scenarios_bfbs", @@ -791,7 +791,7 @@ cc_test { "le_audio/le_audio_types.cc", "le_audio/le_audio_utils.cc", ], - data: [ + device_first_data: [ ":audio_set_configurations_bfbs", ":audio_set_configurations_json", ":audio_set_scenarios_bfbs", @@ -900,7 +900,7 @@ cc_test { "test/common/btm_api_mock.cc", "test/common/mock_csis_client.cc", ], - data: [ + device_first_data: [ ":audio_set_configurations_bfbs", ":audio_set_configurations_json", ":audio_set_scenarios_bfbs", @@ -1026,7 +1026,7 @@ cc_test { "libosi", "server_configurable_flags", ], - data: [ + device_first_data: [ ":audio_set_configurations_bfbs", ":audio_set_configurations_json", ":audio_set_scenarios_bfbs", -- GitLab From 84a18be486f9467f17c741d8e18f810f66ffa8e0 Mon Sep 17 00:00:00 2001 From: Jesse Melhuish Date: Wed, 4 Sep 2024 20:34:10 +0000 Subject: [PATCH 400/875] floss: Refactor BAS connection/disconnection Floss connects to BAS automatically, this means in some cases Floss needs to take responsibility to disconnect it: - A user calls ClientConnect and then expects ClientDisconnect to drop the entire connection. - A peer initiates some profile connections, then Floss connects to BAS. Since Floss is the initiator, the peer might not be disconnecting BAS from their end. This patch does: - Revise Message::OnDeviceConnectionStateChanged: It was not doing what its name told and was only fired in some specific cases - Add Message::ProfileDisconnected: Disconnect BAS when it's the last active profile - Remove BAS logic in ConnectAllEnabledProfiles as we would connect BAS on ACL/bond state changed - Remove BAS logic in DisconnectAllEnabledProfiles as it already disconnects all GATT - Cleanup BAS on GATT disconnected - We would connect BAS to dual device after this patch Bug: 369733365 Tag: #floss Test: mmm packages/modules/Bluetooth Test: Connect Sephero mini through app, then bond through btclient; Disconnecting through app would drop the entire connection after this patch Test: LR10 (dual device), BAS connects and doesn't affect FastPair Test: LE mouse, BAS works fine Test: bluetooth_Adapter{CL,LE,AU}Health.all_floss Test: CTSV Bluetooth LE Client Test Test: SmartLock and FastPair works fine Flag: EXEMPT, Floss-only change Change-Id: I6339e7d649871142c7c55dc2e1a7f3f53d245c18 --- .../rust/linux/stack/src/battery_service.rs | 56 ++++--- system/gd/rust/linux/stack/src/bluetooth.rs | 139 +++++++----------- .../gd/rust/linux/stack/src/bluetooth_gatt.rs | 17 +++ .../rust/linux/stack/src/bluetooth_media.rs | 8 + system/gd/rust/linux/stack/src/lib.rs | 73 ++++++--- 5 files changed, 151 insertions(+), 142 deletions(-) diff --git a/system/gd/rust/linux/stack/src/battery_service.rs b/system/gd/rust/linux/stack/src/battery_service.rs index 688d5fd3ca2..013b9412607 100644 --- a/system/gd/rust/linux/stack/src/battery_service.rs +++ b/system/gd/rust/linux/stack/src/battery_service.rs @@ -2,7 +2,6 @@ use crate::battery_manager::{Battery, BatterySet}; use crate::battery_provider_manager::{ BatteryProviderManager, IBatteryProviderCallback, IBatteryProviderManager, }; -use crate::bluetooth::BluetoothDevice; use crate::bluetooth_gatt::{ BluetoothGatt, BluetoothGattService, IBluetoothGatt, IBluetoothGattCallback, }; @@ -10,9 +9,9 @@ use crate::callbacks::Callbacks; use crate::Message; use crate::RPCProxy; use crate::{uuid, APIMessage, BluetoothAPI}; -use bt_topshim::btif::{BtAclState, BtBondState, BtTransport, DisplayAddress, RawAddress, Uuid}; +use bt_topshim::btif::{BtTransport, DisplayAddress, RawAddress, Uuid}; use bt_topshim::profiles::gatt::{GattStatus, LePhy}; -use log::debug; +use log::{debug, info}; use std::collections::HashMap; use std::convert::TryInto; use std::iter; @@ -23,6 +22,10 @@ use tokio::sync::mpsc::Sender; /// specification. pub const CHARACTERISTIC_BATTERY_LEVEL: &str = "00002A1-9000-0100-0800-000805F9B34FB"; +/// The app UUID BAS provides when connecting as a GATT client. Chosen at random. +/// TODO(b/233101174): make dynamic or decide on a static UUID +pub const BATTERY_SERVICE_GATT_CLIENT_APP_ID: &str = "e4d2acffcfaa42198f494606b7412117"; + /// Represents the Floss BatteryService implementation. pub struct BatteryService { gatt: Arc>>, @@ -55,10 +58,6 @@ pub enum BatteryServiceActions { OnCharacteristicRead(RawAddress, GattStatus, i32, Vec), /// Params: addr, handle, value OnNotify(RawAddress, i32, Vec), - /// Params: remote_device, transport - Connect(BluetoothDevice, BtAclState, BtBondState, BtTransport), - /// Params: remote_device - Disconnect(BluetoothDevice), } /// API for Floss implementation of the Bluetooth Battery Service (BAS). BAS is built on GATT and @@ -127,8 +126,7 @@ impl BatteryService { pub fn init(&self) { debug!("Registering GATT client for BatteryService"); self.gatt.lock().unwrap().register_client( - // TODO(b/233101174): make dynamic or decide on a static UUID - String::from("e4d2acffcfaa42198f494606b7412117"), + String::from(BATTERY_SERVICE_GATT_CLIENT_APP_ID), Box::new(GattCallback::new(self.tx.clone(), self.api_tx.clone())), false, ); @@ -144,6 +142,13 @@ impl BatteryService { BatteryServiceActions::OnClientConnectionState(status, _client_id, connected, addr) => { if !connected || status != GattStatus::Success { + info!( + "BAS: Dropping {} due to GATT state changed: connected={}, status={:?}", + DisplayAddress(&addr), + connected, + status + ); + self.drop_device(addr); return; } let client_id = match self.client_id { @@ -157,8 +162,8 @@ impl BatteryService { BatteryServiceActions::OnSearchComplete(addr, services, status) => { if status != GattStatus::Success { - debug!( - "GATT service discovery for {} failed with status {:?}", + info!( + "BAS: Service discovery for {} failed: status={:?}", DisplayAddress(&addr), status ); @@ -176,10 +181,16 @@ impl BatteryService { ) }); } + info!( + "BAS: Failed to get handle from {}: status={:?}", + DisplayAddress(&addr), + status + ); self.drop_device(addr); return; } }; + info!("BAS: Found handle from {}", DisplayAddress(&addr)); let client_id = match self.client_id { Some(id) => id, None => { @@ -221,21 +232,6 @@ impl BatteryService { callback.on_battery_info_updated(addr, battery_info.clone()); }); } - - BatteryServiceActions::Connect(device, acl_state, bond_state, transport) => { - if transport != BtTransport::Le - || acl_state != BtAclState::Connected - || bond_state != BtBondState::Bonded - { - return; - } - - self.init_device(device.address, transport); - } - - BatteryServiceActions::Disconnect(device) => { - self.drop_device(device.address); - } } } @@ -258,23 +254,22 @@ impl BatteryService { battery_set.clone() } - fn init_device(&self, remote_address: RawAddress, transport: BtTransport) { + pub(crate) fn init_device(&self, remote_address: RawAddress) { let client_id = match self.client_id { Some(id) => id, None => return, }; - debug!("Attempting GATT connection to {}", DisplayAddress(&remote_address)); self.gatt.lock().unwrap().client_connect( client_id, remote_address, false, - transport, + BtTransport::Le, false, LePhy::Phy1m, ); } - fn drop_device(&mut self, remote_address: RawAddress) { + pub(crate) fn drop_device(&mut self, remote_address: RawAddress) { if self.handles.contains_key(&remote_address) { // Let BatteryProviderManager know that BAS no longer has a battery for this device. self.battery_provider_manager.lock().unwrap().remove_battery_info( @@ -354,6 +349,7 @@ impl BatteryService { } /// Status enum for relaying the state of BAS or a particular device. +#[derive(Debug)] pub enum BatteryServiceStatus { /// Device does not report support for BAS. BatteryServiceNotSupported, diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index 3868212fc0f..20442315c08 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -43,7 +43,6 @@ use tokio::sync::mpsc::Sender; use tokio::task::JoinHandle; use tokio::time; -use crate::battery_service::BatteryServiceActions; use crate::bluetooth_admin::BluetoothAdminPolicyHelper; use crate::bluetooth_gatt::{ BluetoothGatt, GattActions, IBluetoothGatt, IScannerCallback, ScanResult, @@ -375,6 +374,7 @@ struct BluetoothDeviceContext { pub info: BluetoothDevice, pub last_seen: Instant, pub properties: HashMap, + pub is_hh_connected: bool, /// If user wants to connect to all profiles, when new profiles are discovered we will also try /// to connect them. @@ -398,6 +398,7 @@ impl BluetoothDeviceContext { info, last_seen, properties: HashMap::new(), + is_hh_connected: false, connect_to_new_profiles: false, }; device.update_properties(&properties); @@ -1296,6 +1297,10 @@ impl Bluetooth { || self.pending_create_bond.is_some() } + pub fn is_hh_connected(&self, device_address: &RawAddress) -> bool { + self.remote_devices.get(&device_address).map_or(false, |context| context.is_hh_connected) + } + /// Checks whether the list of device properties contains some UUID we should connect now /// This function also connects those UUIDs. fn check_new_property_and_potentially_connect_profiles( @@ -1417,37 +1422,6 @@ impl Bluetooth { }); } - Profile::Bas => { - has_supported_profile = true; - let tx = self.tx.clone(); - let device_context = match self.remote_devices.get(&addr) { - Some(context) => context, - None => continue, - }; - - let acl_state = device_context.ble_acl_state.clone(); - let bond_state = device_context.bond_state.clone(); - let device_to_send = device.clone(); - - let transport = match self.get_remote_type(device.clone()) { - BtDeviceType::Bredr => BtTransport::Bredr, - BtDeviceType::Ble => BtTransport::Le, - _ => device_context.acl_reported_transport.clone(), - }; - topstack::get_runtime().spawn(async move { - let _ = tx - .send(Message::BatteryService( - BatteryServiceActions::Connect( - device_to_send, - acl_state, - bond_state, - transport, - ), - )) - .await; - }); - } - // We don't connect most profiles _ => (), } @@ -1464,6 +1438,31 @@ impl Bluetooth { self.resume_discovery(); } } + + fn fire_device_connection_or_bonded_state_changed(&self, addr: RawAddress) { + if let Some(device) = self.remote_devices.get(&addr) { + let tx = self.tx.clone(); + let bredr_acl_state = device.bredr_acl_state.clone(); + let ble_acl_state = device.ble_acl_state.clone(); + let bond_state = device.bond_state.clone(); + let transport = match self.get_remote_type(device.info.clone()) { + BtDeviceType::Bredr => BtTransport::Bredr, + BtDeviceType::Ble => BtTransport::Le, + _ => device.acl_reported_transport.clone(), + }; + tokio::spawn(async move { + let _ = tx + .send(Message::OnDeviceConnectionOrBondStateChanged( + addr, + bredr_acl_state, + ble_acl_state, + bond_state, + transport, + )) + .await; + }); + } + } } #[btif_callbacks_dispatcher(dispatch_base_callbacks, BaseCallbacks)] @@ -1933,40 +1932,22 @@ impl BtifBluetoothCallbacks for Bluetooth { Instant::now(), vec![], )); - let acl_reported_transport = device.acl_reported_transport.clone(); - let acl_state = device.ble_acl_state.clone(); let device_info = device.info.clone(); - // Since this is a newly bonded device, we also need to trigger SDP on it. - self.fetch_remote_uuids(device_info.clone()); + self.fetch_remote_uuids(device_info); if self.get_wake_allowed_device_bonded() { self.create_uhid_for_suspend_wakesource(); } // Update the connectable mode since bonded list is changed. self.update_connectable_mode(); - - let transport = match self.get_remote_type(device_info.clone()) { - BtDeviceType::Bredr => BtTransport::Bredr, - BtDeviceType::Ble => BtTransport::Le, - _ => acl_reported_transport, - }; - - let tx = self.tx.clone(); - tokio::spawn(async move { - let _ = tx - .send(Message::OnDeviceConnectionStateChanged( - device_info.clone(), - acl_state, - BtBondState::Bonded, - transport, - )) - .await; - }); } BtBondState::Bonding => {} } } + // Modification to |self.remote_devices| has done, ok to fire the change event. + self.fire_device_connection_or_bonded_state_changed(addr); + // Resume discovery once the bonding process is complete. Discovery was paused before the // bond request to avoid ACL connection from interfering with active inquiry. if bond_state == BtBondState::NotBonded || bond_state == BtBondState::Bonded { @@ -2073,7 +2054,6 @@ impl BtifBluetoothCallbacks for Bluetooth { return; } - let txl = self.tx.clone(); let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new( BtBondState::NotBonded, BtAclState::Disconnected, @@ -2090,7 +2070,6 @@ impl BtifBluetoothCallbacks for Bluetooth { let info = device.info.clone(); device.acl_reported_transport = link_type; - let bond_state = device.bond_state.clone(); metrics::acl_connection_state_changed( addr, @@ -2103,26 +2082,10 @@ impl BtifBluetoothCallbacks for Bluetooth { match state { BtAclState::Connected => { - let acl_reported_transport = device.acl_reported_transport; Bluetooth::send_metrics_remote_device_info(device); self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_connected(info.clone()); }); - let transport = match self.get_remote_type(info.clone()) { - BtDeviceType::Bredr => BtTransport::Bredr, - BtDeviceType::Ble => BtTransport::Le, - _ => acl_reported_transport, - }; - tokio::spawn(async move { - let _ = txl - .send(Message::OnDeviceConnectionStateChanged( - info, - BtAclState::Connected, - bond_state, - transport, - )) - .await; - }); } BtAclState::Disconnected => { if !device.is_connected() { @@ -2131,11 +2094,12 @@ impl BtifBluetoothCallbacks for Bluetooth { }); device.connect_to_new_profiles = false; } - tokio::spawn(async move { - let _ = txl.send(Message::OnDeviceDisconnected(info)).await; - }); } }; + + // Modification to |self.remote_devices| has done, ok to fire the change event. + self.fire_device_connection_or_bonded_state_changed(addr); + // If we are bonding, skip the update here as we will update it after bonding complete anyway. // This is necessary for RTK controllers, which will break RNR after |Write Scan Enable| // command. Although this is a bug of RTK controllers, but as we could avoid unwanted page @@ -2848,18 +2812,6 @@ impl IBluetooth for Bluetooth { }); } - Profile::Bas => { - let tx = self.tx.clone(); - let device_to_send = device.clone(); - topstack::get_runtime().spawn(async move { - let _ = tx - .send(Message::BatteryService( - BatteryServiceActions::Disconnect(device_to_send), - )) - .await; - }); - } - // We don't connect most profiles _ => (), } @@ -3010,7 +2962,7 @@ impl BtifSdpCallbacks for Bluetooth { impl BtifHHCallbacks for Bluetooth { fn connection_state( &mut self, - mut address: RawAddress, + address: RawAddress, address_type: BtAddrType, transport: BtTransport, state: BthhConnectionState, @@ -3047,6 +2999,16 @@ impl BtifHHCallbacks for Bluetooth { state as u32, ); + let tx = self.tx.clone(); + self.remote_devices.entry(address).and_modify(|context| { + if context.is_hh_connected && state != BthhConnectionState::Connected { + tokio::spawn(async move { + let _ = tx.send(Message::ProfileDisconnected(address)).await; + }); + } + context.is_hh_connected = state == BthhConnectionState::Connected; + }); + if BtBondState::Bonded != self.get_bond_state_by_addr(&address) && (state != BthhConnectionState::Disconnecting && state != BthhConnectionState::Disconnected) @@ -3057,6 +3019,7 @@ impl BtifHHCallbacks for Bluetooth { ); // TODO(b/329837967): Determine correct reconnection // behavior based on device instead of the default + let mut address = address; self.hh.as_ref().unwrap().disconnect( &mut address, address_type, diff --git a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs index 10368fbf49c..d7361844d08 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs @@ -173,6 +173,14 @@ impl ContextMap { .collect() } + fn get_connected_applications_from_address(&self, address: &RawAddress) -> Vec { + self.get_client_ids_from_address(address) + .into_iter() + .filter_map(|id| self.get_by_client_id(id)) + .map(|client| client.uuid) + .collect() + } + fn get_callback_from_callback_id( &mut self, callback_id: u32, @@ -1872,6 +1880,10 @@ impl BluetoothGatt { pub fn handle_adv_action(&mut self, action: AdvertiserActions) { self.adv_manager.get_impl().handle_action(action); } + + pub(crate) fn get_connected_applications(&self, device_address: &RawAddress) -> Vec { + self.context_map.get_connected_applications_from_address(device_address) + } } #[derive(Debug, FromPrimitive, ToPrimitive)] @@ -2865,6 +2877,11 @@ impl BtifGattClientCallbacks for BluetoothGatt { } } } + + let tx = self.tx.clone(); + tokio::spawn(async move { + let _ = tx.send(Message::ProfileDisconnected(addr)).await; + }); } fn search_complete_cb(&mut self, conn_id: i32, _status: GattStatus) { diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs index b31cc1c7e23..4e6f6d28113 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_media.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs @@ -609,6 +609,10 @@ impl BluetoothMedia { false } + pub(crate) fn get_connected_profiles(&self, device_address: &RawAddress) -> HashSet { + self.connected_profiles.get(device_address).cloned().unwrap_or_default() + } + fn add_connected_profile(&mut self, addr: RawAddress, profile: Profile) { if self.is_profile_connected(&addr, &profile) { warn!("[{}]: profile is already connected", DisplayAddress(&addr)); @@ -2302,6 +2306,10 @@ impl BluetoothMedia { self.connected_profiles.remove(&addr); states.remove(&addr); guard.remove(&addr); + let tx = self.tx.clone(); + tokio::spawn(async move { + let _ = tx.send(Message::ProfileDisconnected(addr)).await; + }); return; } diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs index b13e66b523b..e540e68d3e8 100644 --- a/system/gd/rust/linux/stack/src/lib.rs +++ b/system/gd/rust/linux/stack/src/lib.rs @@ -20,7 +20,7 @@ pub mod suspend; pub mod uuid; use bluetooth_qa::{BluetoothQA, IBluetoothQA}; -use log::debug; +use log::{debug, info}; use num_derive::{FromPrimitive, ToPrimitive}; use std::sync::{Arc, Mutex}; use tokio::sync::mpsc::channel; @@ -29,7 +29,9 @@ use tokio::time::{sleep, Duration}; use crate::battery_manager::{BatteryManager, BatterySet}; use crate::battery_provider_manager::BatteryProviderManager; -use crate::battery_service::{BatteryService, BatteryServiceActions}; +use crate::battery_service::{ + BatteryService, BatteryServiceActions, BATTERY_SERVICE_GATT_CLIENT_APP_ID, +}; use crate::bluetooth::{ dispatch_base_callbacks, dispatch_hid_host_callbacks, dispatch_sdp_callbacks, AdapterActions, Bluetooth, BluetoothDevice, IBluetooth, @@ -45,7 +47,7 @@ use crate::dis::{DeviceInformation, ServiceCallbacks}; use crate::socket_manager::{BluetoothSocketManager, SocketActions}; use crate::suspend::Suspend; use bt_topshim::{ - btif::{BaseCallbacks, BtAclState, BtBondState, BtTransport, RawAddress}, + btif::{BaseCallbacks, BtAclState, BtBondState, BtTransport, DisplayAddress, RawAddress, Uuid}, profiles::{ a2dp::A2dpCallbacks, avrcp::AvrcpCallbacks, @@ -109,8 +111,14 @@ pub enum Message { // Follows IBluetooth's on_device_(dis)connected and bond_state callbacks // but doesn't require depending on Bluetooth. - OnDeviceConnectionStateChanged(BluetoothDevice, BtAclState, BtBondState, BtTransport), - OnDeviceDisconnected(BluetoothDevice), + // Params: Address, BR/EDR ACL state, BLE ACL state, bond state, transport + OnDeviceConnectionOrBondStateChanged( + RawAddress, + BtAclState, + BtAclState, + BtBondState, + BtTransport, + ), // Suspend related SuspendCallbackRegistered(u32), @@ -167,6 +175,11 @@ pub enum Message { // UHid callbacks UHidHfpOutputCallback(RawAddress, u8, u8), UHidTelephonyUseCallback(RawAddress, bool), + + // This message is sent when either HID, media, or GATT client, is disconnected. + // Note that meida sends this when the profiles are disconnected as a whole, that is, it will + // not be called when AVRCP is disconnected but not A2DP, as an example. + ProfileDisconnected(RawAddress), } /// Returns a callable object that dispatches a BTIF callback to Message @@ -432,27 +445,19 @@ impl Stack { bluetooth.lock().unwrap().handle_actions(action); } - // Any service needing an updated list of devices can have an - // update method triggered from here rather than needing a - // reference to Bluetooth. - Message::OnDeviceConnectionStateChanged( - device, - acl_state, + // Any service needing an updated list of devices can have an update method + // triggered from here rather than needing a reference to Bluetooth. + Message::OnDeviceConnectionOrBondStateChanged( + addr, + _bredr_acl_state, + ble_acl_state, bond_state, - transport, + _transport, ) => { - battery_service.lock().unwrap().handle_action(BatteryServiceActions::Connect( - device, acl_state, bond_state, transport, - )); - } - - // For battery service, use this to clean up internal handles. GATT connection is - // already dropped if ACL disconnect has occurred. - Message::OnDeviceDisconnected(device) => { - battery_service - .lock() - .unwrap() - .handle_action(BatteryServiceActions::Disconnect(device)); + if ble_acl_state == BtAclState::Connected && bond_state == BtBondState::Bonded { + info!("BAS: Connecting to {}", DisplayAddress(&addr)); + battery_service.lock().unwrap().init_device(addr); + } } Message::SuspendCallbackRegistered(id) => { @@ -599,6 +604,26 @@ impl Stack { .unwrap() .dispatch_uhid_telephony_use_callback(addr, state); } + + Message::ProfileDisconnected(addr) => { + let bas_app_uuid = + Uuid::from_string(String::from(BATTERY_SERVICE_GATT_CLIENT_APP_ID)) + .expect("BAS Uuid failed to be parsed"); + // Ideally we would also check that there are no open sockets for this device + // but Floss does not manage socket state so there is no reasonable way for us + // to know whether a socket is open or not. + if bluetooth_gatt.lock().unwrap().get_connected_applications(&addr) + == vec![bas_app_uuid] + && !bluetooth.lock().unwrap().is_hh_connected(&addr) + && bluetooth_media.lock().unwrap().get_connected_profiles(&addr).is_empty() + { + info!( + "BAS: Disconnecting from {} since it's the last active profile", + DisplayAddress(&addr) + ); + battery_service.lock().unwrap().drop_device(addr); + } + } } } } -- GitLab From 7f23913c4fe24bb1ee15e054c80669cc5d277ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Fri, 18 Oct 2024 13:33:31 +0000 Subject: [PATCH 401/875] ActiveDeviceManager: Fix handling disconnect of a streaming set member This patch fixes issue when after disconnecting LeAudio device while stream, music was transfered to the Speaker. ActiveDeviceManager, while handling disconnection of the first set member, incorrectly assumed that another set member is a fallback device. Then, ActiveDeviceManager instructed LeAudioService to remove itself from being Active device, but also set flag `hasFallbackDevice` which later cause the problem Bug: 367213572 Bug: 374320313 Test: atest ActiveDeviceManagerTest Flag: com.android.bluetooth.flags.adm_fix_disconnect_of_set_member Change-Id: I6ea853a2565f9ce56ef8eaa6df8d4d515c065a8d --- .../btservice/ActiveDeviceManager.java | 40 +++++ .../btservice/ActiveDeviceManagerTest.java | 160 ++++++++++++++++++ 2 files changed, 200 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java index 9b926f13069..8520bc371f2 100644 --- a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +++ b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java @@ -1041,6 +1041,23 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac return false; } + @GuardedBy("mLock") + private boolean areSameGroupMembers(BluetoothDevice firstDevice, BluetoothDevice secondDevice) { + + if (!Flags.admFixDisconnectOfSetMember()) { + /* This function shall return false without the fix flag. */ + return false; + } + + final LeAudioService leAudioService = mFactory.getLeAudioService(); + if (leAudioService == null) { + Log.e(TAG, "LeAudioService not available"); + return false; + } + + return leAudioService.getGroupId(firstDevice) == leAudioService.getGroupId(secondDevice); + } + /** * TODO: This method can return true when a fallback device for an unrelated profile is found. * Take disconnected profile as an argument, and find the exact fallback device. Also, split @@ -1083,6 +1100,13 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac setLeAudioActiveDevice(null, hasFallbackDevice); } else { Log.d(TAG, "Found a LE hearing aid fallback device: " + device); + if (areSameGroupMembers(recentlyRemovedDevice, device)) { + Log.d( + TAG, + "Do nothing, removed device belong to the same group as the" + + " fallback device."); + return true; + } setLeHearingAidActiveDevice(device); setHearingAidActiveDevice(null, hasFallbackDevice); setA2dpActiveDevice(null, hasFallbackDevice); @@ -1152,6 +1176,14 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac setHearingAidActiveDevice(null, true); } else { Log.d(TAG, "Found a LE audio fallback device: " + device); + if (areSameGroupMembers(recentlyRemovedDevice, device)) { + Log.d( + TAG, + "Do nothing, removed device belong to the same group as the fallback" + + " device."); + return true; + } + if (!setLeAudioActiveDevice(device)) { return false; } @@ -1181,6 +1213,14 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac setHearingAidActiveDevice(null, true); } else { Log.d(TAG, "Found a LE audio fallback device: " + device); + if (areSameGroupMembers(recentlyRemovedDevice, device)) { + Log.d( + TAG, + "Do nothing, removed device belong to the same group as the fallback" + + " device."); + return true; + } + setLeAudioActiveDevice(device); if (!Utils.isDualModeAudioEnabled()) { setA2dpActiveDevice(null, true); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index b50835e74aa..541f965969f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -67,6 +68,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.Spy; @@ -87,6 +89,7 @@ public class ActiveDeviceManagerTest { private BluetoothDevice mHearingAidDevice; private BluetoothDevice mLeAudioDevice; private BluetoothDevice mLeAudioDevice2; + private BluetoothDevice mLeAudioDevice3; private BluetoothDevice mLeHearingAidDevice; private BluetoothDevice mSecondaryAudioDevice; private BluetoothDevice mDualModeAudioDevice; @@ -146,6 +149,7 @@ public class ActiveDeviceManagerTest { mSecondaryAudioDevice = TestUtils.getTestDevice(mAdapter, 6); mDualModeAudioDevice = TestUtils.getTestDevice(mAdapter, 7); mLeAudioDevice2 = TestUtils.getTestDevice(mAdapter, 8); + mLeAudioDevice3 = TestUtils.getTestDevice(mAdapter, 9); mDeviceConnectionStack = new ArrayList<>(); mMostRecentDevice = null; mOriginalDualModeAudioState = Utils.isDualModeAudioEnabled(); @@ -161,6 +165,7 @@ public class ActiveDeviceManagerTest { when(mLeAudioService.getLeadDevice(mLeAudioDevice)).thenReturn(mLeAudioDevice); when(mLeAudioService.getLeadDevice(mLeAudioDevice2)).thenReturn(mLeAudioDevice2); + when(mLeAudioService.getLeadDevice(mLeAudioDevice3)).thenReturn(mLeAudioDevice3); when(mLeAudioService.getLeadDevice(mDualModeAudioDevice)).thenReturn(mDualModeAudioDevice); when(mLeAudioService.getLeadDevice(mLeHearingAidDevice)).thenReturn(mLeHearingAidDevice); @@ -839,6 +844,161 @@ public class ActiveDeviceManagerTest { verify(mLeAudioService).setActiveDevice(mLeAudioDevice); } + /** + * One LE Audio set, containing two buds, is connected. When one device got disconnected + * fallback device should not be set to true active device to fallback device. + */ + @Test + @EnableFlags(Flags.FLAG_ADM_FIX_DISCONNECT_OF_SET_MEMBER) + public void leAudioSecondDeviceDisconnected_noFallbackDeviceActive_ModeNormal() { + when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); + + InOrder order = inOrder(mLeAudioService); + + int groupId = 1; + List groupDevices = List.of(mLeAudioDevice, mLeAudioDevice2); + when(mLeAudioService.getLeadDevice(mLeAudioDevice2)).thenReturn(mLeAudioDevice); + + leAudioConnected(mLeAudioDevice); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice); + + leAudioConnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, never()).setActiveDevice(any()); + + when(mLeAudioService.getGroupId(any())).thenReturn(groupId); + when(mLeAudioService.getGroupDevices(groupId)).thenReturn(groupDevices); + + leAudioDisconnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, never()).setActiveDevice(any()); + } + + /** + * One LE Audio set, containing two buds, is connected. When one device got disconnected + * fallback device should not be set to true active device to fallback device. + */ + @Test + @EnableFlags(Flags.FLAG_ADM_FIX_DISCONNECT_OF_SET_MEMBER) + public void leAudioSecondDeviceDisconnected_noFallbackDeviceActive_ModeInCall() { + when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); + + InOrder order = inOrder(mLeAudioService); + + int groupId = 1; + List groupDevices = List.of(mLeAudioDevice, mLeAudioDevice2); + when(mLeAudioService.getLeadDevice(mLeAudioDevice2)).thenReturn(mLeAudioDevice); + + leAudioConnected(mLeAudioDevice); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice); + + leAudioConnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, never()).setActiveDevice(any()); + + when(mLeAudioService.getGroupId(any())).thenReturn(groupId); + when(mLeAudioService.getGroupDevices(groupId)).thenReturn(groupDevices); + + leAudioDisconnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, never()).setActiveDevice(any()); + } + + /** + * One LE Audio set, containing two buds, is connected. When one device got disconnected + * fallback device should not be set to true active device to fallback device. + */ + @Test + @EnableFlags(Flags.FLAG_ADM_FIX_DISCONNECT_OF_SET_MEMBER) + public void twoLeAudioSets_OneSetDisconnected_FallbackToAnotherOne_ModeNormal() { + when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); + + InOrder order = inOrder(mLeAudioService); + + int groupId = 1; + List groupDevices = List.of(mLeAudioDevice, mLeAudioDevice2); + + when(mLeAudioService.getLeadDevice(mLeAudioDevice2)).thenReturn(mLeAudioDevice); + when(mLeAudioService.getGroupId(mLeAudioDevice)).thenReturn(groupId); + when(mLeAudioService.getGroupId(mLeAudioDevice2)).thenReturn(groupId); + when(mLeAudioService.getGroupDevices(groupId)).thenReturn(groupDevices); + + int groupId2 = 2; + List groupDevicesId2 = List.of(mLeAudioDevice3); + + when(mLeAudioService.getGroupId(mLeAudioDevice3)).thenReturn(groupId2); + when(mLeAudioService.getGroupDevices(groupId2)).thenReturn(groupDevicesId2); + + leAudioConnected(mLeAudioDevice3); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice3); + + leAudioConnected(mLeAudioDevice); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService).setActiveDevice(mLeAudioDevice); + + leAudioConnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, never()).setActiveDevice(mLeAudioDevice2); + + leAudioDisconnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + // Should not encrease a number of this call. + order.verify(mLeAudioService, never()).setActiveDevice(any()); + + leAudioDisconnected(mLeAudioDevice); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice3); + } + + /** + * One LE Audio set, containing two buds, is connected. When one device got disconnected + * fallback device should not be set to true active device to fallback device. + */ + @Test + @EnableFlags(Flags.FLAG_ADM_FIX_DISCONNECT_OF_SET_MEMBER) + public void twoLeAudioSets_OneSetDisconnected_FallbackToAnotherOne_ModeInCall() { + when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); + + InOrder order = inOrder(mLeAudioService); + + int groupId = 1; + List groupDevices = List.of(mLeAudioDevice, mLeAudioDevice2); + + when(mLeAudioService.getLeadDevice(mLeAudioDevice2)).thenReturn(mLeAudioDevice); + when(mLeAudioService.getGroupId(mLeAudioDevice)).thenReturn(groupId); + when(mLeAudioService.getGroupId(mLeAudioDevice2)).thenReturn(groupId); + when(mLeAudioService.getGroupDevices(groupId)).thenReturn(groupDevices); + + int groupId2 = 2; + List groupDevicesId2 = List.of(mLeAudioDevice3); + + when(mLeAudioService.getGroupId(mLeAudioDevice3)).thenReturn(groupId2); + when(mLeAudioService.getGroupDevices(groupId2)).thenReturn(groupDevicesId2); + + leAudioConnected(mLeAudioDevice3); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService).setActiveDevice(mLeAudioDevice3); + + leAudioConnected(mLeAudioDevice); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService).setActiveDevice(mLeAudioDevice); + + leAudioConnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, never()).setActiveDevice(any()); + + leAudioDisconnected(mLeAudioDevice2); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, never()).setActiveDevice(any()); + + leAudioDisconnected(mLeAudioDevice); + mTestLooper.dispatchAll(); + order.verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice3); + } + /** A combo (A2DP + Headset) device is connected. Then an LE Audio is connected. */ @Test public void leAudioActive_clearA2dpAndHeadsetActive() { -- GitLab From 41e81e10b5ca1bc6f5b40784df965b4e6feaa1c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 17 Oct 2024 12:27:50 +0000 Subject: [PATCH 402/875] VCS: check group only for group set in `setDeviceVolume` Bug: 373308672 Test: atest VolumeControlServiceTest Change-Id: Ia0c0af6a1ba040059b623020560876790f773d9c --- .../bluetooth/vc/VolumeControlService.java | 11 ++++++----- .../bluetooth/vc/VolumeControlServiceTest.java | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 8932ae28d92..99f296b9be1 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -450,13 +450,14 @@ public class VolumeControlService extends ProfileService { Log.e(TAG, "leAudioService not available"); return; } - int groupId = leAudioService.getGroupId(device); - if (groupId == IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID) { - Log.e(TAG, "Device not a part of a group"); - return; - } if (isGroupOp) { + int groupId = leAudioService.getGroupId(device); + if (groupId == IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID) { + Log.e(TAG, "Device not a part of a group"); + return; + } + setGroupVolume(groupId, volume); } else { Log.i(TAG, "Setting individual device volume"); 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 a89342a3970..c7538991000 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 @@ -904,7 +904,23 @@ public class VolumeControlServiceTest { } @Test - public void serviceBinderRegisterUnregisterCallback() { + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_VOLUME_CONTROL_FOR_CONNECTED_DEVICES) + public void testServiceBinderSetDeviceVolumeNoGroupId() throws Exception { + int deviceVolume = 42; + when(mLeAudioService.getGroupId(mDevice)).thenReturn(LE_AUDIO_GROUP_ID_INVALID); + + generateDeviceAvailableMessageFromNative(mDevice, 1); + generateConnectionMessageFromNative( + mDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mService.getDevices()).contains(mDevice); + + mBinder.setDeviceVolume(mDevice, deviceVolume, false, mAttributionSource); + verify(mNativeInterface).setVolume(mDevice, deviceVolume); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(deviceVolume); + } + + @Test + public void testServiceBinderRegisterUnregisterCallback() throws Exception { IBluetoothVolumeControlCallback callback = Mockito.mock(IBluetoothVolumeControlCallback.class); Binder binder = Mockito.mock(Binder.class); -- GitLab From 43ab3cae2c92aac3e7cc8cba3d74d4c35bc4cec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 30 Sep 2024 14:16:14 +0000 Subject: [PATCH 403/875] pandora: add support to VCP tests Implements VCP tests that are supported by bluetooth stack. Tests that are skipped require mechanism to trigger sending write to Volume Control Point with "Unmute" OP code Bug: 369938109 Flag: TEST_ONLY Test: atest pts-bot:VCP -v Change-Id: I1fa01b7e184abe164da0420a70c46b4c1c2fb75d --- android/pandora/mmi2grpc/mmi2grpc/vcp.py | 76 +++++++++- .../server/configs/pts_bot_tests_config.json | 31 ++-- android/pandora/server/src/Server.kt | 1 + android/pandora/server/src/Vcp.kt | 132 ++++++++++++++++++ .../interfaces/pandora_experimental/vcp.proto | 47 +++++++ pandora/interfaces/python/Android.bp | 5 + 6 files changed, 271 insertions(+), 21 deletions(-) create mode 100644 android/pandora/server/src/Vcp.kt create mode 100644 pandora/interfaces/pandora_experimental/vcp.proto diff --git a/android/pandora/mmi2grpc/mmi2grpc/vcp.py b/android/pandora/mmi2grpc/mmi2grpc/vcp.py index 905f5519169..fa869abbb66 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/vcp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/vcp.py @@ -17,23 +17,33 @@ import threading from mmi2grpc._helpers import assert_description, match_description from mmi2grpc._proxy import ProfileProxy from mmi2grpc._rootcanal import Dongle + +from pandora_experimental.vcp_grpc import VCP +from pandora_experimental.gatt_grpc import GATT +from pandora.security_grpc import Security, SecurityStorage +from pandora.security_pb2 import LE_LEVEL3, PairingEventAnswer from pandora.host_grpc import Host from pandora.host_pb2 import PUBLIC, RANDOM from pandora.security_grpc import Security from pandora.security_pb2 import LE_LEVEL3, PairingEventAnswer from pandora_experimental.le_audio_grpc import LeAudio +from time import sleep + class VCPProxy(ProfileProxy): def __init__(self, channel, rootcanal): super().__init__(channel) + self.vcp = VCP(channel) + self.gatt = GATT(channel) + self.security_storage = SecurityStorage(channel) self.host = Host(channel) self.security = Security(channel) self.le_audio = LeAudio(channel) self.rootcanal = rootcanal self.connection = None - self.pairing_stream = None + self.pairing_stream = self.security.OnPairing() def test_started(self, test: str, description: str, pts_addr: bytes): self.rootcanal.select_pts_dongle(Dongle.LAIRD_BL654) @@ -49,13 +59,18 @@ class VCPProxy(ProfileProxy): the Implementation Under Test (IUT) can initiate a GATT connect request to the PTS. """ + self.security_storage.DeleteBond(public=pts_addr) self.connection = self.host.ConnectLE(own_address_type=RANDOM, public=pts_addr).connection - self.pairing_stream = self.security.OnPairing() def secure(): self.security.Secure(connection=self.connection, le=LE_LEVEL3) + def vcp_connect(): + self.vcp.WaitConnect(connection=self.connection) + threading.Thread(target=secure).start() + threading.Thread(target=vcp_connect).start() + return "OK" @match_description @@ -80,10 +95,14 @@ class VCPProxy(ProfileProxy): """ Please take action to discover the (Volume Control Point|Volume State|Volume Flags|Offset State|Volume Offset Control Point) - characteristic from the Volume (Offset)? Control. Discover the primary service if needed. + characteristic from the Volume (Offset )?Control. Discover the primary service if needed. Description: Verify that the Implementation Under Test \(IUT\) can send Discover All Characteristics command. """ + # PTS expects us to do discovery after bonding, but in fact Android does it as soon as + # encryption is completed. Invalidate GATT cache so the discovery takes place again + self.gatt.ClearCache(connection=self.connection) + return "OK" @match_description @@ -92,13 +111,26 @@ class VCPProxy(ProfileProxy): Please send Read Request to read (?P(Volume State|Volume Flags|Offset State)) characteristic with handle = (?P(0x[0-9A-Fa-f]{4})). """ + # After discovery Android reads these values by itself, after profile connection. + # Although, for some tests, this is used as validation, for example for tests with invalid + # behavior (BI tests). Just send GATT read to sattisfy this conditions, as VCP has no exposed + # (or even existing, native) interface to trigger read on demand. + def read(): + nonlocal handle + self.gatt.ReadCharacteristicFromHandle(\ + connection=self.connection, handle=int(handle, base=16)) + + worker = threading.Thread(target=read) + worker.start() + worker.join(timeout=30) + return "OK" - @assert_description - def USER_CONFIRM_SUPPORTED_CHARACTERISTIC(self, characteristics: str, **kwargs): + @match_description + def USER_CONFIRM_SUPPORTED_CHARACTERISTIC(self, body: str, **kwargs): """ Please verify that for each supported characteristic, attribute - handle/UUID pair(s) is returned to the upper tester.(?P(.|\n)*) + handle/UUID pair\(s\) is returned to the (.*)\.(?P.*) """ return "OK" @@ -109,6 +141,38 @@ class VCPProxy(ProfileProxy): Please write to Client Characteristic Configuration Descriptor of (?P(Volume State|Offset State)) characteristic to enable notification. """ + + # After discovery Android subscribes by itself, after profile connection + return "OK" + + def IUT_SEND_WRITE_REQUEST(self, description: str, **kwargs): + r""" + Please send write request to handle 0xXXXX with following value. + Characteristic name: + Op Code: [X (0xXX)] Op code name + Change Counter: + Value: + """ + + # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed) + sleep(2) + + if ("Set Absolute Volume" in description): + self.vcp.SetDeviceVolume(connection=self.connection, volume=42) + elif ("Unmute" in description): + # for now, there is no way to trigger this, and tests are skipped + return "No" + elif ("Set Volume Offset" in description): + self.vcp.SetVolumeOffset(connection=self.connection, offset=42) + elif ("Volume Control Point" in description and + "Op Code: " in description): + # Handles sending *any* OP Code on Volume Control Point + self.vcp.SetDeviceVolume(connection=self.connection, volume=42) + elif ("Volume Offset Control Point" in description and + "Op Code: " in description): + self.vcp.SetVolumeOffset(connection=self.connection, offset=42) + + return "OK" @assert_description diff --git a/android/pandora/server/configs/pts_bot_tests_config.json b/android/pandora/server/configs/pts_bot_tests_config.json index 3cfbe0d26ec..45b8679572d 100644 --- a/android/pandora/server/configs/pts_bot_tests_config.json +++ b/android/pandora/server/configs/pts_bot_tests_config.json @@ -686,7 +686,19 @@ "SM/PER/SCJW/BV-03-C", "SM/PER/SCPK/BI-03-C", "SM/PER/SCPK/BV-02-C", - "VCP/VC/CGGIT/CHA/BV-06-C" + "VCP/VC/CGGIT/CHA/BV-01-C", + "VCP/VC/CGGIT/CHA/BV-02-C", + "VCP/VC/CGGIT/CHA/BV-03-C", + "VCP/VC/CGGIT/CHA/BV-04-C", + "VCP/VC/CGGIT/CHA/BV-06-C", + "VCP/VC/CGGIT/SER/BV-01-C", + "VCP/VC/CGGIT/SER/BV-02-C", + "VCP/VC/SPE/BI-05-C", + "VCP/VC/SPE/BI-13-C", + "VCP/VC/SPE/BI-15-C", + "VCP/VC/SPE/BI-16-C", + "VCP/VC/VCCP/BV-05-C", + "VCP/VC/VOCP/BV-01-C" ], "flaky": [ "A2DP/SRC/SUS/BV-02-I", @@ -1145,20 +1157,8 @@ "SM/PER/SCPK/BV-03-C", "SM/PER/SIE/BV-01-C", "SM/PER/SIP/BV-01-C", - "VCP/VC/CGGIT/CHA/BV-01-C", - "VCP/VC/CGGIT/CHA/BV-02-C", - "VCP/VC/CGGIT/CHA/BV-03-C", - "VCP/VC/CGGIT/CHA/BV-04-C", - "VCP/VC/CGGIT/SER/BV-01-C", - "VCP/VC/CGGIT/SER/BV-02-C", - "VCP/VC/SPE/BI-05-C", "VCP/VC/SPE/BI-06-C", - "VCP/VC/SPE/BI-13-C", - "VCP/VC/SPE/BI-15-C", - "VCP/VC/SPE/BI-16-C", - "VCP/VC/VCCP/BV-05-C", - "VCP/VC/VCCP/BV-06-C", - "VCP/VC/VOCP/BV-01-C" + "VCP/VC/VCCP/BV-06-C" ], "ics": { "TSPC_4.0HCI_1_1": true, @@ -3168,7 +3168,8 @@ "SM": {}, "SPP": {}, "SUM ICS": {}, - "VCP": {} + "VCP": { + } }, "flags": [ { diff --git a/android/pandora/server/src/Server.kt b/android/pandora/server/src/Server.kt index 79993339e93..54830fd4e5c 100644 --- a/android/pandora/server/src/Server.kt +++ b/android/pandora/server/src/Server.kt @@ -68,6 +68,7 @@ class Server(context: Context) { BluetoothProfile.OPP to ::Opp, BluetoothProfile.MAP to ::Map, BluetoothProfile.LE_AUDIO to ::LeAudio, + BluetoothProfile.VOLUME_CONTROL to ::Vcp, ) .filter { bluetoothAdapter.isEnabled } .filter { bluetoothAdapter.getSupportedProfiles().contains(it.key) == true } diff --git a/android/pandora/server/src/Vcp.kt b/android/pandora/server/src/Vcp.kt new file mode 100644 index 00000000000..c8aa8c5802a --- /dev/null +++ b/android/pandora/server/src/Vcp.kt @@ -0,0 +1,132 @@ +/* + * Copyright (C) 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. + */ + +package com.android.pandora + +import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothDevice +import android.bluetooth.BluetoothDevice.TRANSPORT_LE +import android.bluetooth.BluetoothVolumeControl +import android.bluetooth.BluetoothManager +import android.bluetooth.BluetoothProfile +import android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.util.Log +import com.google.protobuf.Empty +import io.grpc.Status +import io.grpc.stub.StreamObserver +import java.io.Closeable +import java.io.PrintWriter +import java.io.StringWriter +import java.util.concurrent.Executors +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.shareIn +import pandora.vcp.VCPGrpc.VCPImplBase +import pandora.vcp.VcpProto.* +import pandora.HostProto.Connection + +@kotlinx.coroutines.ExperimentalCoroutinesApi +class Vcp(val context: Context) : VCPImplBase(), Closeable { + private val TAG = "PandoraVcp" + + private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default.limitedParallelism(1)) + + private val bluetoothManager = context.getSystemService(BluetoothManager::class.java)!! + private val bluetoothAdapter = bluetoothManager.adapter + + private val bluetoothVolumeControl = + getProfileProxy(context, BluetoothProfile.VOLUME_CONTROL) + + private val flow = + intentFlow( + context, + IntentFilter().apply { + addAction(BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED) + }, + scope, + ) + .shareIn(scope, SharingStarted.Eagerly) + + override fun close() { + // Deinit the CoroutineScope + scope.cancel() + } + + override fun setDeviceVolume( + request: SetDeviceVolumeRequest, + responseObserver: StreamObserver + ) { + grpcUnary(scope, responseObserver) { + val device = request.connection.toBluetoothDevice(bluetoothAdapter) + + Log.i(TAG, "setDeviceVolume(${device}, ${request.volume})") + + bluetoothVolumeControl.setDeviceVolume(device, request.volume, false) + + Empty.getDefaultInstance() + } + } + + override fun setVolumeOffset( + request: SetVolumeOffsetRequest, + responseObserver: StreamObserver + ) { + grpcUnary(scope, responseObserver) { + val device = request.connection.toBluetoothDevice(bluetoothAdapter) + + Log.i(TAG, "setVolumeOffset(${device}, ${request.offset})") + + bluetoothVolumeControl.setVolumeOffset(device, 1, request.offset) + + Empty.getDefaultInstance() + } + } + + override fun waitConnect( + request: WaitConnectRequest, + responseObserver: StreamObserver + ) { + grpcUnary(scope, responseObserver) { + val device = request.connection.toBluetoothDevice(bluetoothAdapter) + Log.i(TAG, "waitPeripheral(${device}") + if ( + bluetoothVolumeControl.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED + ) { + Log.d(TAG, "Manual call to setConnectionPolicy") + bluetoothVolumeControl.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED) + Log.d(TAG, "wait for bluetoothVolumeControl profile connection") + flow + .filter { it.getBluetoothDeviceExtra() == device } + .map { it.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR) } + .filter { it == BluetoothProfile.STATE_CONNECTED } + .first() + } + + Empty.getDefaultInstance() + } + } +} \ No newline at end of file diff --git a/pandora/interfaces/pandora_experimental/vcp.proto b/pandora/interfaces/pandora_experimental/vcp.proto new file mode 100644 index 00000000000..42641c8545a --- /dev/null +++ b/pandora/interfaces/pandora_experimental/vcp.proto @@ -0,0 +1,47 @@ +// Copyright (C) 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. + +syntax = "proto3"; + +package pandora.vcp; + +import "pandora/host.proto"; +option java_outer_classname = "VcpProto"; +import "google/protobuf/empty.proto"; + +service VCP { + // set absolute volume on remote device + rpc SetDeviceVolume(SetDeviceVolumeRequest) returns (google.protobuf.Empty); + // set volume offset on remote device + rpc SetVolumeOffset(SetVolumeOffsetRequest) returns (google.protobuf.Empty); + // Wait for device to be connected. + rpc WaitConnect(WaitConnectRequest) returns (google.protobuf.Empty); +} + +// Request of the `SetDeviceVolume` method +message SetDeviceVolumeRequest{ + // Connection crafted by grpc server + Connection connection = 1; + // Volume value to be set + int32 volume = 2; +} + +// Request of the `SetVolumeOffset` method +message SetVolumeOffsetRequest{ + // Connection crafted by grpc server + Connection connection = 1; + // Volume offset value to be set + int32 offset = 2; +} + +message WaitConnectRequest { + Connection connection = 1; +} diff --git a/pandora/interfaces/python/Android.bp b/pandora/interfaces/python/Android.bp index d295f2cfd32..c866c4a1387 100644 --- a/pandora/interfaces/python/Android.bp +++ b/pandora/interfaces/python/Android.bp @@ -95,6 +95,10 @@ genrule { "pandora_experimental/rfcomm_grpc_aio.py", "pandora_experimental/rfcomm_pb2.py", "pandora_experimental/rfcomm_pb2.pyi", + "pandora_experimental/vcp_grpc.py", + "pandora_experimental/vcp_grpc_aio.py", + "pandora_experimental/vcp_pb2.py", + "pandora_experimental/vcp_pb2.pyi", ], } @@ -129,6 +133,7 @@ filegroup { ":pandora_experimental-python-gen-src{pandora_experimental/pbap_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/py.typed}", ":pandora_experimental-python-gen-src{pandora_experimental/rfcomm_pb2.pyi}", + ":pandora_experimental-python-gen-src{pandora_experimental/vcp_pb2.pyi}", ], } -- GitLab From 2b126d8eb7fccead8231f5e9be929bd56fbb403c Mon Sep 17 00:00:00 2001 From: Anna Bauza Date: Wed, 23 Oct 2024 10:31:46 +0000 Subject: [PATCH 404/875] Fix regression due to default bypass change in IpcDataCache. Change-Id: I512f34b5293370abc2ff368d5e95b91b3bb7df2b Test: m . + install on device and observe state change Flag: EXEMPT bugfix Bug: 374222784 --- .../android/bluetooth/BluetoothAdapter.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index ce8b74f74f6..4c4571d4c78 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -1484,6 +1484,11 @@ public final class BluetoothAdapter { throw e.rethrowAsRuntimeException(); } } + @RequiresNoPermission + @Override + public boolean shouldBypassCache(IBluetooth serviceQuery) { + return false; + } }; private static final IpcDataCache.QueryHandler @@ -1498,6 +1503,11 @@ public final class BluetoothAdapter { throw e.rethrowAsRuntimeException(); } } + @RequiresNoPermission + @Override + public boolean shouldBypassCache(IBluetoothManager serviceQuery) { + return false; + } }; private static final String GET_STATE_API = "BluetoothAdapter_getState"; @@ -2405,6 +2415,11 @@ public final class BluetoothAdapter { throw e.rethrowAsRuntimeException(); } } + @RequiresNoPermission + @Override + public boolean shouldBypassCache(IBluetooth serviceQuery) { + return false; + } }; private static final String FILTERING_API = "BluetoothAdapter_isOffloadedFilteringSupported"; @@ -2948,6 +2963,11 @@ public final class BluetoothAdapter { throw e.rethrowAsRuntimeException(); } } + @RequiresNoPermission + @Override + public boolean shouldBypassCache(IBluetooth serviceQuery) { + return false; + } }; private static final String GET_CONNECTION_API = "BluetoothAdapter_getConnectionState"; @@ -3017,6 +3037,12 @@ public final class BluetoothAdapter { throw e.rethrowAsRuntimeException(); } } + @RequiresNoPermission + @Override + public boolean shouldBypassCache( + Pair> pairQuery) { + return false; + } }; private static final String PROFILE_API = "BluetoothAdapter_getProfileConnectionState"; -- GitLab From 86db5fe0e5490f4a6a8f34dc6638b59473cddae1 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Mon, 21 Oct 2024 15:25:14 +0800 Subject: [PATCH 405/875] Hcidoc: Print cid info Print the CID information for L2CAP connections. Bug: 374907568 Test: m -j Test: manual verification Flag: EXEMPT, floss changes only Change-Id: Id93d52a5ca819d29f63d9cdb92da80f3879315ea --- floss/hcidoc/src/groups/informational.rs | 54 ++++++++++++++++++------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/floss/hcidoc/src/groups/informational.rs b/floss/hcidoc/src/groups/informational.rs index e224f481b26..6e0d41fe3c2 100644 --- a/floss/hcidoc/src/groups/informational.rs +++ b/floss/hcidoc/src/groups/informational.rs @@ -237,7 +237,7 @@ impl AclInformation { initiator: InitiatorType, ts: NaiveDateTime, ) { - let mut profile = ProfileInformation::new(profile_type); + let mut profile = ProfileInformation::new(profile_type, profile_id); profile.report_start(initiator, ts); let old_profile = self.active_profiles.insert(profile_id, profile); if let Some(profile) = old_profile { @@ -254,7 +254,7 @@ impl AclInformation { let mut profile = self .active_profiles .remove(&profile_id) - .unwrap_or(ProfileInformation::new(profile_type)); + .unwrap_or(ProfileInformation::new(profile_type, profile_id)); profile.report_end(ts); self.inactive_profiles.push(profile); } @@ -278,11 +278,12 @@ impl AclInformation { fn report_l2cap_conn_rsp( &mut self, status: ConnectionResponseResult, - host_cid: Cid, - peer_cid: Cid, + cid_info: CidInformation, initiator: InitiatorType, ts: NaiveDateTime, ) { + let host_cid = cid_info.host_cid; + let peer_cid = cid_info.peer_cid; let cid_state_option = match initiator { InitiatorType::Host => self.host_cids.get(&host_cid), InitiatorType::Peer => self.peer_cids.get(&peer_cid), @@ -299,7 +300,7 @@ impl AclInformation { if let Some(psm) = psm_option { let profile_option = ProfileType::from_psm(psm); - let profile_id = ProfileId::L2capCid(host_cid); + let profile_id = ProfileId::L2capCid(cid_info); if status == ConnectionResponseResult::Success { self.host_cids.insert(host_cid, CidState::Connected(peer_cid, psm)); self.peer_cids.insert(peer_cid, CidState::Connected(host_cid, psm)); @@ -319,11 +320,11 @@ impl AclInformation { // L2cap disconnected so report profile connection closed if we were tracking it. fn report_l2cap_disconn_rsp( &mut self, - host_cid: Cid, - peer_cid: Cid, + cid_info: CidInformation, _initiator: InitiatorType, ts: NaiveDateTime, ) { + let host_cid = cid_info.host_cid; let host_cid_state_option = self.host_cids.remove(&host_cid); let host_psm = match host_cid_state_option { Some(cid_state) => match cid_state { @@ -334,6 +335,7 @@ impl AclInformation { None => None, }; + let peer_cid = cid_info.peer_cid; let peer_cid_state_option = self.peer_cids.remove(&peer_cid); let peer_psm = match peer_cid_state_option { Some(cid_state) => match cid_state { @@ -357,7 +359,7 @@ impl AclInformation { let profile_option = ProfileType::from_psm(psm); if let Some(profile) = profile_option { - let profile_id = ProfileId::L2capCid(host_cid); + let profile_id = ProfileId::L2capCid(cid_info); self.report_profile_end(profile, profile_id, ts) } } @@ -430,12 +432,31 @@ impl ProfileType { } } +#[derive(Clone, Copy, Eq, Hash, PartialEq)] +struct CidInformation { + host_cid: Cid, + peer_cid: Cid, +} + // Use to distinguish between the same profiles within one ACL connection. // Later we can add RFCOMM's DLCI, for example. +// This is used as the key of the map of active profiles in AclInformation. #[derive(Clone, Copy, Eq, Hash, PartialEq)] enum ProfileId { OnePerConnection(ProfileType), - L2capCid(Cid), + L2capCid(CidInformation), +} + +impl fmt::Display for ProfileId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let str = match self { + ProfileId::OnePerConnection(_) => "".to_string(), + ProfileId::L2capCid(cid_info) => { + format!("(CID: host={}, peer={})", cid_info.host_cid, cid_info.peer_cid) + } + }; + write!(f, "{}", str) + } } struct ProfileInformation { @@ -443,15 +464,17 @@ struct ProfileInformation { end_time: NaiveDateTime, profile_type: ProfileType, initiator: InitiatorType, + profile_id: ProfileId, } impl ProfileInformation { - pub fn new(profile_type: ProfileType) -> Self { + pub fn new(profile_type: ProfileType, profile_id: ProfileId) -> Self { ProfileInformation { start_time: INVALID_TS, end_time: INVALID_TS, profile_type: profile_type, initiator: InitiatorType::Unknown, + profile_id: profile_id, } } @@ -469,10 +492,11 @@ impl fmt::Display for ProfileInformation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!( f, - " {profile}, {initiator}, {timestamp_info}", + " {profile}, {initiator}, {timestamp_info} {profile_id}", profile = self.profile_type, initiator = self.initiator, - timestamp_info = print_start_end_timestamps(self.start_time, self.end_time) + timestamp_info = print_start_end_timestamps(self.start_time, self.end_time), + profile_id = self.profile_id, ) } } @@ -681,7 +705,8 @@ impl InformationalRule { return; } let conn = self.get_or_allocate_connection(&handle); - conn.report_l2cap_conn_rsp(status, host_cid, peer_cid, initiator, ts); + let cid_info = CidInformation { host_cid, peer_cid }; + conn.report_l2cap_conn_rsp(status, cid_info, initiator, ts); } fn report_l2cap_disconn_rsp( @@ -693,7 +718,8 @@ impl InformationalRule { ts: NaiveDateTime, ) { let conn = self.get_or_allocate_connection(&handle); - conn.report_l2cap_disconn_rsp(host_cid, peer_cid, initiator, ts); + let cid_info = CidInformation { host_cid, peer_cid }; + conn.report_l2cap_disconn_rsp(cid_info, initiator, ts); } } -- GitLab From 9325c3793064f725711d040b1accbfdeaba1057f Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Mon, 21 Oct 2024 18:34:15 +0800 Subject: [PATCH 406/875] Hcidoc: Add disconnection initiator information The initiator of disconnection can be different than the connection. Also print the disconnection initiator. Bug: 374907937 Test: m -j Test: Manual verification Flag: EXEMPT, floss only changes Change-Id: Ic8f8860a3d9d45fb9c2a9b4585774de92ca7063b --- floss/hcidoc/src/groups/informational.rs | 146 +++++++++++++++-------- 1 file changed, 93 insertions(+), 53 deletions(-) diff --git a/floss/hcidoc/src/groups/informational.rs b/floss/hcidoc/src/groups/informational.rs index 6e0d41fe3c2..a8654e74342 100644 --- a/floss/hcidoc/src/groups/informational.rs +++ b/floss/hcidoc/src/groups/informational.rs @@ -23,18 +23,27 @@ type Cid = u16; const INVALID_TS: NaiveDateTime = NaiveDateTime::MAX; -fn print_start_end_timestamps(start: NaiveDateTime, end: NaiveDateTime) -> String { - fn print_time(ts: NaiveDateTime) -> String { +fn print_timestamps_and_initiator( + start: NaiveDateTime, + start_initiator: InitiatorType, + end: NaiveDateTime, + end_initiator: InitiatorType, +) -> String { + fn print_time_initiator(ts: NaiveDateTime, initiator: InitiatorType) -> String { if ts == INVALID_TS { return "N/A".to_owned(); } - return format!("{}", ts.time()); + return format!("{} ({})", ts.time(), initiator); } if start == end && start != INVALID_TS { - return format!("{} - Failed", start.time()); + return format!("{} ({}) - Failed", start.time(), start_initiator); } - return format!("{} to {}", print_time(start), print_time(end)); + return format!( + "{} to {}", + print_time_initiator(start, start_initiator), + print_time_initiator(end, end_initiator) + ); } #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] @@ -74,7 +83,7 @@ impl AddressType { } } -#[derive(PartialEq)] +#[derive(Clone, Copy, PartialEq)] enum InitiatorType { Unknown, Host, @@ -84,9 +93,9 @@ enum InitiatorType { impl fmt::Display for InitiatorType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let str = match self { - InitiatorType::Unknown => "Unknown initiator", - InitiatorType::Host => "Host initiated", - InitiatorType::Peer => "Peer initiated", + InitiatorType::Unknown => "by ??", + InitiatorType::Host => "by host", + InitiatorType::Peer => "by peer", }; write!(f, "{}", str) } @@ -100,8 +109,8 @@ enum AclState { Connected, } -impl Into for AclState { - fn into(self) -> InitiatorType { +impl AclState { + fn get_connection_initiator(&self) -> InitiatorType { match self { AclState::Initiating => InitiatorType::Host, AclState::Accepting => InitiatorType::Peer, @@ -145,15 +154,20 @@ impl DeviceInformation { fn report_connection_start(&mut self, handle: ConnectionHandle, ts: NaiveDateTime) { let mut acl = AclInformation::new(handle); - let initiator = self.acl_state.into(); + let initiator = self.acl_state.get_connection_initiator(); acl.report_start(initiator, ts); self.acls.push(acl); self.acl_state = AclState::Connected; } - fn report_connection_end(&mut self, handle: ConnectionHandle, ts: NaiveDateTime) { + fn report_connection_end( + &mut self, + handle: ConnectionHandle, + initiator: InitiatorType, + ts: NaiveDateTime, + ) { let acl = self.get_or_allocate_connection(&handle); - acl.report_end(ts); + acl.report_end(initiator, ts); self.acl_state = AclState::None; } @@ -195,7 +209,8 @@ struct AclInformation { start_time: NaiveDateTime, end_time: NaiveDateTime, handle: ConnectionHandle, - initiator: InitiatorType, + start_initiator: InitiatorType, + end_initiator: InitiatorType, active_profiles: HashMap, inactive_profiles: Vec, host_cids: HashMap, @@ -208,7 +223,8 @@ impl AclInformation { start_time: INVALID_TS, end_time: INVALID_TS, handle: handle, - initiator: InitiatorType::Unknown, + start_initiator: InitiatorType::Unknown, + end_initiator: InitiatorType::Unknown, active_profiles: HashMap::new(), inactive_profiles: vec![], host_cids: HashMap::new(), @@ -217,16 +233,17 @@ impl AclInformation { } fn report_start(&mut self, initiator: InitiatorType, ts: NaiveDateTime) { - self.initiator = initiator; + self.start_initiator = initiator; self.start_time = ts; } - fn report_end(&mut self, ts: NaiveDateTime) { + fn report_end(&mut self, initiator: InitiatorType, ts: NaiveDateTime) { // disconnect the active profiles for (_, mut profile) in self.active_profiles.drain() { - profile.report_end(ts); + profile.report_end(initiator, ts); self.inactive_profiles.push(profile); } + self.end_initiator = initiator; self.end_time = ts; } @@ -249,13 +266,14 @@ impl AclInformation { &mut self, profile_type: ProfileType, profile_id: ProfileId, + initiator: InitiatorType, ts: NaiveDateTime, ) { let mut profile = self .active_profiles .remove(&profile_id) .unwrap_or(ProfileInformation::new(profile_type, profile_id)); - profile.report_end(ts); + profile.report_end(initiator, ts); self.inactive_profiles.push(profile); } @@ -311,7 +329,7 @@ impl AclInformation { // On failure, report start and end on the same time. if let Some(profile) = profile_option { self.report_profile_start(profile, profile_id, initiator, ts); - self.report_profile_end(profile, profile_id, ts); + self.report_profile_end(profile, profile_id, initiator, ts); } } } // TODO: debug on the else case. @@ -321,7 +339,7 @@ impl AclInformation { fn report_l2cap_disconn_rsp( &mut self, cid_info: CidInformation, - _initiator: InitiatorType, + initiator: InitiatorType, ts: NaiveDateTime, ) { let host_cid = cid_info.host_cid; @@ -360,7 +378,7 @@ impl AclInformation { let profile_option = ProfileType::from_psm(psm); if let Some(profile) = profile_option { let profile_id = ProfileId::L2capCid(cid_info); - self.report_profile_end(profile, profile_id, ts) + self.report_profile_end(profile, profile_id, initiator, ts) } } } @@ -369,10 +387,14 @@ impl fmt::Display for AclInformation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let _ = writeln!( f, - " Handle: {handle}, {initiator}, {timestamp_info}", + " Handle: {handle}, {timestamp_initiator_info}", handle = self.handle, - initiator = self.initiator, - timestamp_info = print_start_end_timestamps(self.start_time, self.end_time) + timestamp_initiator_info = print_timestamps_and_initiator( + self.start_time, + self.start_initiator, + self.end_time, + self.end_initiator + ), ); for profile in self.inactive_profiles.iter() { @@ -463,7 +485,8 @@ struct ProfileInformation { start_time: NaiveDateTime, end_time: NaiveDateTime, profile_type: ProfileType, - initiator: InitiatorType, + start_initiator: InitiatorType, + end_initiator: InitiatorType, profile_id: ProfileId, } @@ -473,17 +496,19 @@ impl ProfileInformation { start_time: INVALID_TS, end_time: INVALID_TS, profile_type: profile_type, - initiator: InitiatorType::Unknown, + start_initiator: InitiatorType::Unknown, + end_initiator: InitiatorType::Unknown, profile_id: profile_id, } } fn report_start(&mut self, initiator: InitiatorType, ts: NaiveDateTime) { - self.initiator = initiator; + self.start_initiator = initiator; self.start_time = ts; } - fn report_end(&mut self, ts: NaiveDateTime) { + fn report_end(&mut self, initiator: InitiatorType, ts: NaiveDateTime) { + self.end_initiator = initiator; self.end_time = ts; } } @@ -492,10 +517,14 @@ impl fmt::Display for ProfileInformation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!( f, - " {profile}, {initiator}, {timestamp_info} {profile_id}", + " {profile}, {timestamp_initiator_info} {profile_id}", profile = self.profile_type, - initiator = self.initiator, - timestamp_info = print_start_end_timestamps(self.start_time, self.end_time), + timestamp_initiator_info = print_timestamps_and_initiator( + self.start_time, + self.start_initiator, + self.end_time, + self.end_initiator + ), profile_id = self.profile_id, ) } @@ -508,9 +537,13 @@ struct InformationalRule { sco_handles: HashMap, /// unknownConnections store connections which is initiated before btsnoop starts. unknown_connections: HashMap, - /// When powering off, the controller might or might not reply disconnection request. Therefore - /// make this a special case. - pending_disconnect_due_to_host_power_off: HashSet, + /// Store the pending disconnection so we can retrieve who initiates it upon report. + /// This needs its own map instead of reusing the AclState, because that requires us to have the + /// address of the peer device, but on disconnection we are given only the handle - the address + /// might be unknown, or clash in case of a SCO connection. + /// Also, when powering off, the controller might or might not reply the disconnection request. + /// Therefore also store this information so we can correctly handle both scenario. + pending_disconnections: HashMap, // is powering off? } impl InformationalRule { @@ -520,7 +553,7 @@ impl InformationalRule { handles: HashMap::new(), sco_handles: HashMap::new(), unknown_connections: HashMap::new(), - pending_disconnect_due_to_host_power_off: HashSet::new(), + pending_disconnections: HashMap::new(), } } @@ -576,7 +609,7 @@ impl InformationalRule { let device = self.get_or_allocate_device(address); device.report_connection_start(handle, ts); self.handles.insert(handle, *address); - self.pending_disconnect_due_to_host_power_off.remove(&handle); + self.pending_disconnections.remove(&handle); } fn report_sco_connection_start( @@ -613,13 +646,21 @@ impl InformationalRule { } fn report_connection_end(&mut self, handle: ConnectionHandle, ts: NaiveDateTime) { + let initiator = match self.pending_disconnections.contains_key(&handle) { + true => InitiatorType::Host, + false => InitiatorType::Peer, + }; + // This might be a SCO disconnection event, so check that first if self.sco_handles.contains_key(&handle) { let acl_handle = self.sco_handles[&handle]; let conn = self.get_or_allocate_connection(&acl_handle); + // in case of HFP failure, the initiator here would be set to peer, which is incorrect, + // but when printing we detect by the timestamp that it was a failure anyway. conn.report_profile_end( ProfileType::Hfp, ProfileId::OnePerConnection(ProfileType::Hfp), + initiator, ts, ); return; @@ -628,8 +669,8 @@ impl InformationalRule { // Not recognized as SCO, assume it's an ACL handle. if let Some(address) = self.handles.get(&handle) { // This device is known - let device = self.devices.get_mut(address).unwrap(); - device.report_connection_end(handle, ts); + let device: &mut DeviceInformation = self.devices.get_mut(address).unwrap(); + device.report_connection_end(handle, initiator, ts); self.handles.remove(&handle); // remove the associated SCO handle, if any @@ -637,7 +678,7 @@ impl InformationalRule { } else { // Unknown device. let conn = self.get_or_allocate_unknown_connection(&handle); - conn.report_end(ts); + conn.report_end(initiator, ts); } } @@ -648,7 +689,7 @@ impl InformationalRule { self.report_connection_end(handle, ts); } self.sco_handles.clear(); - self.pending_disconnect_due_to_host_power_off.clear(); + self.pending_disconnections.clear(); } fn process_gap_data(&mut self, address: &Address, data: &GapData) { @@ -755,12 +796,11 @@ impl Rule for InformationalRule { EventChild::DisconnectionComplete(ev) => { // If disconnected because host is powering off, the event has been processed. // We can't just query the reason here because it's different across vendors. - if !self - .pending_disconnect_due_to_host_power_off - .remove(&ev.get_connection_handle()) - { - self.report_connection_end(ev.get_connection_handle(), packet.ts); + let handle = ev.get_connection_handle(); + if !self.pending_disconnections.get(&handle).unwrap_or(&false) { + self.report_connection_end(handle, packet.ts); } + self.pending_disconnections.remove(&handle); } EventChild::ExtendedInquiryResult(ev) => { @@ -858,12 +898,12 @@ impl Rule for InformationalRule { AclCommandChild::Disconnect(cmd) => { // If reason is power off, the host might not wait for connection complete event - if cmd.get_reason() - == DisconnectReason::RemoteDeviceTerminatedConnectionPowerOff - { - self.pending_disconnect_due_to_host_power_off - .insert(cmd.get_connection_handle()); - self.report_connection_end(cmd.get_connection_handle(), packet.ts); + let is_power_off = cmd.get_reason() + == DisconnectReason::RemoteDeviceTerminatedConnectionPowerOff; + let handle = cmd.get_connection_handle(); + self.pending_disconnections.insert(handle, is_power_off); + if is_power_off { + self.report_connection_end(handle, packet.ts); } } -- GitLab From d86585a62f65cd989a9465d1522a7a18139196d2 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Tue, 22 Oct 2024 17:21:08 +0800 Subject: [PATCH 407/875] RootCanal: Add Authenticated Payload Timeout Expired event This already exists on system/pdl/hci/hci_packets.pdl. Bug: 289858128 Test: m -j Flag: EXEMPT, tooling change Change-Id: Iaeb06fa41714743c2e65f2efd632cfd5646c91ca --- tools/rootcanal/packets/hci_packets.pdl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/rootcanal/packets/hci_packets.pdl b/tools/rootcanal/packets/hci_packets.pdl index ec34b4da0f1..db7c51d294f 100644 --- a/tools/rootcanal/packets/hci_packets.pdl +++ b/tools/rootcanal/packets/hci_packets.pdl @@ -749,6 +749,7 @@ enum EventCode : 8 { REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION = 0x3D, LE_META_EVENT = 0x3e, NUMBER_OF_COMPLETED_DATA_BLOCKS = 0x48, + AUTHENTICATED_PAYLOAD_TIMEOUT_EXPIRED = 0x57, ENCRYPTION_CHANGE_V2 = 0x59, VENDOR_SPECIFIC = 0xFF, } @@ -5134,6 +5135,11 @@ packet NumberOfCompletedDataBlocks : Event (event_code = NUMBER_OF_COMPLETED_DAT _payload_, // placeholder (unimplemented) } +packet AuthenticatedPayloadTimeoutExpired : Event (event_code = AUTHENTICATED_PAYLOAD_TIMEOUT_EXPIRED) { + connection_handle : 12, + _reserved_ : 4, +} + // LE Events packet LeConnectionComplete : LeMetaEvent (subevent_code = CONNECTION_COMPLETE) { status : ErrorCode, -- GitLab From b309d99f3f08dd94d0874a2ab00dd9b5dffab453 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Tue, 22 Oct 2024 17:30:46 +0800 Subject: [PATCH 408/875] Hcidoc: Use hci_packets.pdl in rootcanal The hci_packets.pdl in system/pdl doesn't seem to be fully compatible with the pdl-compiler. Therefore, use the one in rootcanal instead. Since they have different structure, some adjustments needs to be made. In particular, this one doesn't have nested HCI structure, and doesn't have GAP Data implementation. Bug: 289858128 Test: m -j Test: Manual verification Flag: EXEMPT, floss only changes Change-Id: I0ede46f80cc0e371bc69ccdbd9f2b60e9be6ccd8 --- floss/hcidoc/packets/build.rs | 2 +- floss/hcidoc/packets/lib.rs | 42 ++++ floss/hcidoc/src/groups/connections.rs | 232 ++++++++++------------- floss/hcidoc/src/groups/informational.rs | 86 ++++----- 4 files changed, 175 insertions(+), 187 deletions(-) diff --git a/floss/hcidoc/packets/build.rs b/floss/hcidoc/packets/build.rs index 7a08060febb..f9d0304a55e 100644 --- a/floss/hcidoc/packets/build.rs +++ b/floss/hcidoc/packets/build.rs @@ -44,7 +44,7 @@ fn generate_packets() { ); let out_file = File::create(out_dir.join("hci_packets.rs")).unwrap(); - let in_file = PathBuf::from("../../../system/pdl/hci/hci_packets.pdl"); + let in_file = PathBuf::from("../../../tools/rootcanal/packets/hci_packets.pdl"); println!("cargo:rerun-if-changed={}", in_file.display()); let output = Command::new("pdlc") diff --git a/floss/hcidoc/packets/lib.rs b/floss/hcidoc/packets/lib.rs index af9d8101452..4a71e58e13d 100644 --- a/floss/hcidoc/packets/lib.rs +++ b/floss/hcidoc/packets/lib.rs @@ -36,4 +36,46 @@ pub mod hci { bytes[0..6].try_into().unwrap() } } + + pub struct GapData { + pub data_type: GapDataType, + pub data: Vec, + } + + impl GapData { + pub fn parse(bytes: &[u8]) -> std::result::Result { + // In case of parsing EIR, we can get normal data, or all zeroes. Normal data always + // have at least 2 bytes: one for the length, and another for the type. Therefore we + // can terminate early if the data has less than 2 bytes. + if (bytes.len() == 0) { + return Err("no data to parse".to_string()); + } else if (bytes.len() == 1) { + if (bytes[0] != 0) { + return Err(format!("can't parse 1 byte of data: {}", bytes[0])); + } + return Ok(GapData { data_type: GapDataType::Invalid, data: vec![] }); + } + + let mut data_size = bytes[0] as usize; + if (data_size == 0) { + // Data size already include the data_type, so size = 0 is possible only when + // parsing EIR, where all data are zeroes. Here we just assume that assumption is + // correct, and don't really check all the elements. + return Ok(GapData { data_type: GapDataType::Invalid, data: bytes[2..].to_vec() }); + } + + if (data_size > bytes.len() - 1) { + return Err(format!( + "size {} is bigger than remaining length {}", + data_size, + bytes.len() - 1 + )); + } + let data_type = match GapDataType::try_from(bytes[1]) { + Ok(data_type) => Ok(data_type), + Err(_) => Err(format!("can't parse data type {}", bytes[1])), + }?; + return Ok(GapData { data_type, data: bytes[2..(data_size + 1)].to_vec() }); + } + } } diff --git a/floss/hcidoc/src/groups/connections.rs b/floss/hcidoc/src/groups/connections.rs index 9c1526f1b7a..0f22e73e5f1 100644 --- a/floss/hcidoc/src/groups/connections.rs +++ b/floss/hcidoc/src/groups/connections.rs @@ -8,11 +8,9 @@ use std::slice::Iter; use crate::engine::{Rule, RuleGroup, Signal}; use crate::parser::{Packet, PacketChild}; use hcidoc_packets::hci::{ - Acl, AclCommandChild, Address, AuthenticatedPayloadTimeoutExpired, CommandChild, - ConnectionManagementCommandChild, DisconnectReason, Enable, ErrorCode, EventChild, - InitiatorFilterPolicy, LeConnectionManagementCommandChild, LeMetaEventChild, - LeSecurityCommandChild, NumberOfCompletedPackets, OpCode, ScoConnectionCommandChild, - SecurityCommandChild, + Acl, Address, AuthenticatedPayloadTimeoutExpired, CommandChild, DisconnectReason, Enable, + ErrorCode, EventChild, InitiatorFilterPolicy, LeMetaEventChild, NumberOfCompletedPackets, + OpCode, }; enum ConnectionSignal { @@ -626,100 +624,77 @@ impl Rule for OddDisconnectionsRule { fn process(&mut self, packet: &Packet) { match &packet.inner { PacketChild::HciCommand(cmd) => match cmd.specialize() { - CommandChild::AclCommand(aclpkt) => match aclpkt.specialize() { - AclCommandChild::ConnectionManagementCommand(conn) => match conn.specialize() { - ConnectionManagementCommandChild::CreateConnection(cc) => { - self.process_classic_connection(cc.get_bd_addr(), packet); - } - ConnectionManagementCommandChild::AcceptConnectionRequest(ac) => { - self.process_classic_connection(ac.get_bd_addr(), packet); - } - ConnectionManagementCommandChild::ReadRemoteSupportedFeatures(rrsf) => { - self.process_remote_feat_cmd( - PendingRemoteFeature::Supported, - &rrsf.get_connection_handle(), - packet, - ); - } - ConnectionManagementCommandChild::ReadRemoteExtendedFeatures(rref) => { - self.process_remote_feat_cmd( - PendingRemoteFeature::Extended, - &rref.get_connection_handle(), - packet, - ); - } - // End ConnectionManagementCommand.specialize() - _ => {} - }, - AclCommandChild::ScoConnectionCommand(sco_con) => match sco_con.specialize() { - ScoConnectionCommandChild::SetupSynchronousConnection(ssc) => { - let address = - self.convert_sco_handle_to_address(ssc.get_connection_handle()); - self.process_sync_connection(address, packet); - } - ScoConnectionCommandChild::EnhancedSetupSynchronousConnection(esc) => { - let address = - self.convert_sco_handle_to_address(esc.get_connection_handle()); - self.process_sync_connection(address, packet); - } - ScoConnectionCommandChild::AcceptSynchronousConnection(asc) => { - self.process_sync_connection(asc.get_bd_addr(), packet); - } - ScoConnectionCommandChild::EnhancedAcceptSynchronousConnection(easc) => { - self.process_sync_connection(easc.get_bd_addr(), packet); - } - // End ScoConnectionCommand.specialize() - _ => {} - }, - AclCommandChild::LeConnectionManagementCommand(le_conn) => match le_conn - .specialize() - { - LeConnectionManagementCommandChild::LeCreateConnection(lcc) => { - self.process_le_create_connection( - lcc.get_peer_address(), - lcc.get_initiator_filter_policy(), - packet, - ); - } - LeConnectionManagementCommandChild::LeExtendedCreateConnection(lecc) => { - self.process_le_create_connection( - lecc.get_peer_address(), - lecc.get_initiator_filter_policy(), - packet, - ); - } - LeConnectionManagementCommandChild::LeAddDeviceToFilterAcceptList(laac) => { - self.process_add_accept_list(laac.get_address(), packet); - } - LeConnectionManagementCommandChild::LeRemoveDeviceFromFilterAcceptList( - lrac, - ) => { - self.process_remove_accept_list(lrac.get_address(), packet); - } - LeConnectionManagementCommandChild::LeClearFilterAcceptList(_lcac) => { - self.process_clear_accept_list(packet); - } - LeConnectionManagementCommandChild::LeReadRemoteFeatures(lrrf) => { - self.process_remote_feat_cmd( - PendingRemoteFeature::Le, - &lrrf.get_connection_handle(), - packet, - ); - } - // End LeConnectionManagementCommand.specialize() - _ => {} - }, - AclCommandChild::Disconnect(dc_conn) => { - self.process_disconnect_cmd( - dc_conn.get_reason(), - dc_conn.get_connection_handle(), - packet, - ); - } - - // End AclCommand.specialize() - _ => (), - }, + CommandChild::CreateConnection(cc) => { + self.process_classic_connection(cc.get_bd_addr(), packet); + } + CommandChild::AcceptConnectionRequest(ac) => { + self.process_classic_connection(ac.get_bd_addr(), packet); + } + CommandChild::ReadRemoteSupportedFeatures(rrsf) => { + self.process_remote_feat_cmd( + PendingRemoteFeature::Supported, + &rrsf.get_connection_handle(), + packet, + ); + } + CommandChild::ReadRemoteExtendedFeatures(rref) => { + self.process_remote_feat_cmd( + PendingRemoteFeature::Extended, + &rref.get_connection_handle(), + packet, + ); + } + CommandChild::SetupSynchronousConnection(ssc) => { + let address = self.convert_sco_handle_to_address(ssc.get_connection_handle()); + self.process_sync_connection(address, packet); + } + CommandChild::EnhancedSetupSynchronousConnection(esc) => { + let address = self.convert_sco_handle_to_address(esc.get_connection_handle()); + self.process_sync_connection(address, packet); + } + CommandChild::AcceptSynchronousConnection(asc) => { + self.process_sync_connection(asc.get_bd_addr(), packet); + } + CommandChild::EnhancedAcceptSynchronousConnection(easc) => { + self.process_sync_connection(easc.get_bd_addr(), packet); + } + CommandChild::LeCreateConnection(lcc) => { + self.process_le_create_connection( + lcc.get_peer_address(), + lcc.get_initiator_filter_policy(), + packet, + ); + } + CommandChild::LeExtendedCreateConnection(lecc) => { + self.process_le_create_connection( + lecc.get_peer_address(), + lecc.get_initiator_filter_policy(), + packet, + ); + } + CommandChild::LeAddDeviceToFilterAcceptList(laac) => { + self.process_add_accept_list(laac.get_address(), packet); + } + CommandChild::LeRemoveDeviceFromFilterAcceptList(lrac) => { + self.process_remove_accept_list(lrac.get_address(), packet); + } + CommandChild::LeClearFilterAcceptList(_lcac) => { + self.process_clear_accept_list(packet); + } + CommandChild::LeReadRemoteFeatures(lrrf) => { + self.process_remote_feat_cmd( + PendingRemoteFeature::Le, + &lrrf.get_connection_handle(), + packet, + ); + } + CommandChild::Disconnect(dc_conn) => { + self.process_disconnect_cmd( + dc_conn.get_reason(), + dc_conn.get_connection_handle(), + packet, + ); + } CommandChild::Reset(_) => { self.process_reset(); } @@ -754,6 +729,7 @@ impl Rule for OddDisconnectionsRule { EventChild::NumberOfCompletedPackets(nocp) => { self.process_nocp(&nocp, packet); } + EventChild::AuthenticatedPayloadTimeoutExpired(apte) => { self.process_apte(&apte, packet); } @@ -1008,44 +984,26 @@ impl Rule for LinkKeyMismatchRule { }, PacketChild::HciCommand(cmd) => match cmd.specialize() { - CommandChild::AclCommand(cmd) => match cmd.specialize() { - // Have an arm for Disconnect since sometimes we don't receive disconnect - // event when powering off. However, no need to actually match the reason - // since we just clean the handle in both cases. - AclCommandChild::Disconnect(cmd) => { - self.process_handle_auth( - ErrorCode::Success, - cmd.get_connection_handle(), - &packet, - ); - self.handles.remove(&cmd.get_connection_handle()); - } - - // CommandChild::AclCommand(cmd).specialize() - _ => {} - }, - - CommandChild::SecurityCommand(cmd) => match cmd.specialize() { - SecurityCommandChild::LinkKeyRequestReply(cmd) => { - self.process_reply_link_key(cmd.get_bd_addr(), true); - } - SecurityCommandChild::LinkKeyRequestNegativeReply(cmd) => { - self.process_reply_link_key(cmd.get_bd_addr(), false); - } - - // CommandChild::SecurityCommand(cmd).specialize() - _ => {} - }, - - CommandChild::LeSecurityCommand(cmd) => match cmd.specialize() { - LeSecurityCommandChild::LeStartEncryption(cmd) => { - self.pending_le_encrypt.insert(cmd.get_connection_handle()); - } - - // CommandChild::LeSecurityCommand(cmd).specialize() - _ => {} - }, - + // Have an arm for Disconnect since sometimes we don't receive disconnect + // event when powering off. However, no need to actually match the reason + // since we just clean the handle in both cases. + CommandChild::Disconnect(cmd) => { + self.process_handle_auth( + ErrorCode::Success, + cmd.get_connection_handle(), + &packet, + ); + self.handles.remove(&cmd.get_connection_handle()); + } + CommandChild::LinkKeyRequestReply(cmd) => { + self.process_reply_link_key(cmd.get_bd_addr(), true); + } + CommandChild::LinkKeyRequestNegativeReply(cmd) => { + self.process_reply_link_key(cmd.get_bd_addr(), false); + } + CommandChild::LeStartEncryption(cmd) => { + self.pending_le_encrypt.insert(cmd.get_connection_handle()); + } CommandChild::Reset(_) => { self.process_reset(); } diff --git a/floss/hcidoc/src/groups/informational.rs b/floss/hcidoc/src/groups/informational.rs index a8654e74342..dbaa6c8ae37 100644 --- a/floss/hcidoc/src/groups/informational.rs +++ b/floss/hcidoc/src/groups/informational.rs @@ -10,8 +10,8 @@ use std::io::Write; use crate::engine::{Rule, RuleGroup, Signal}; use crate::parser::{get_acl_content, AclContent, Packet, PacketChild}; use hcidoc_packets::hci::{ - AclCommandChild, Address, CommandChild, ConnectionManagementCommandChild, DisconnectReason, - ErrorCode, EventChild, GapData, GapDataType, LeMetaEventChild, + Address, CommandChild, DisconnectReason, ErrorCode, EventChild, GapData, GapDataType, + LeMetaEventChild, }; use hcidoc_packets::l2cap::{ConnectionResponseResult, ControlChild}; @@ -706,18 +706,20 @@ impl InformationalRule { fn process_raw_gap_data(&mut self, address: &Address, data: &[u8]) { let mut offset = 0; while offset < data.len() { - let chunk_size = usize::from(data[offset]); - let chunk_end = offset + chunk_size + 1; - - // Prevent out-of-bounds index - if chunk_end > data.len() { - return; + match GapData::parse(&data[offset..]) { + Ok(gap_data) => { + self.process_gap_data(&address, &gap_data); + // advance data len + 2 (size = 1, type = 1) + offset += gap_data.data.len() + 2; + } + Err(err) => { + eprintln!("[{}] GAP data is not parsed correctly: {}", address, err); + break; + } } - match GapData::parse(&data[offset..chunk_end]) { - Ok(gap_data) => self.process_gap_data(&address, &gap_data), - Err(_err) => {} + if offset >= data.len() { + break; } - offset = chunk_end; } } @@ -804,9 +806,10 @@ impl Rule for InformationalRule { } EventChild::ExtendedInquiryResult(ev) => { - for data in ev.get_extended_inquiry_response() { - self.process_gap_data(&ev.get_address(), data); - } + self.process_raw_gap_data( + &ev.get_address(), + ev.get_extended_inquiry_response(), + ); self.report_address_type(&ev.get_address(), AddressType::BREDR); } @@ -851,16 +854,14 @@ impl Rule for InformationalRule { self.report_address_type(&ev.get_peer_address(), AddressType::LE); } - // Use the Raw version because somehow LeAdvertisingReport doesn't work - LeMetaEventChild::LeAdvertisingReportRaw(ev) => { + LeMetaEventChild::LeAdvertisingReport(ev) => { for resp in ev.get_responses() { self.process_raw_gap_data(&resp.address, &resp.advertising_data); self.report_address_type(&resp.address, AddressType::LE); } } - // Use the Raw version because somehow LeExtendedAdvertisingReport doesn't work - LeMetaEventChild::LeExtendedAdvertisingReportRaw(ev) => { + LeMetaEventChild::LeExtendedAdvertisingReport(ev) => { for resp in ev.get_responses() { self.process_raw_gap_data(&resp.address, &resp.advertising_data); self.report_address_type(&resp.address, AddressType::LE); @@ -879,37 +880,24 @@ impl Rule for InformationalRule { CommandChild::Reset(_cmd) => { self.report_reset(packet.ts); } - - CommandChild::AclCommand(cmd) => match cmd.specialize() { - AclCommandChild::ConnectionManagementCommand(cmd) => match cmd.specialize() { - ConnectionManagementCommandChild::CreateConnection(cmd) => { - self.report_acl_state(&cmd.get_bd_addr(), AclState::Initiating); - self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR); - } - - ConnectionManagementCommandChild::AcceptConnectionRequest(cmd) => { - self.report_acl_state(&cmd.get_bd_addr(), AclState::Accepting); - self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR); - } - - // AclCommandChild::ConnectionManagementCommand(cmd).specialize() - _ => {} - }, - - AclCommandChild::Disconnect(cmd) => { - // If reason is power off, the host might not wait for connection complete event - let is_power_off = cmd.get_reason() - == DisconnectReason::RemoteDeviceTerminatedConnectionPowerOff; - let handle = cmd.get_connection_handle(); - self.pending_disconnections.insert(handle, is_power_off); - if is_power_off { - self.report_connection_end(handle, packet.ts); - } + CommandChild::CreateConnection(cmd) => { + self.report_acl_state(&cmd.get_bd_addr(), AclState::Initiating); + self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR); + } + CommandChild::AcceptConnectionRequest(cmd) => { + self.report_acl_state(&cmd.get_bd_addr(), AclState::Accepting); + self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR); + } + CommandChild::Disconnect(cmd) => { + // If reason is power off, the host might not wait for connection complete event + let is_power_off = cmd.get_reason() + == DisconnectReason::RemoteDeviceTerminatedConnectionPowerOff; + let handle = cmd.get_connection_handle(); + self.pending_disconnections.insert(handle, is_power_off); + if is_power_off { + self.report_connection_end(handle, packet.ts); } - - // CommandChild::AclCommand(cmd).specialize() - _ => {} - }, + } // PacketChild::HciCommand(cmd).specialize() _ => {} -- GitLab From 114d45c0a529e5e286e4a564718a3c0a4690830d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 23 Oct 2024 13:46:18 +0000 Subject: [PATCH 409/875] flags: Add fix_add_device_properties Bug: 375158716 Bug: 315241296 Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.fix_add_device_properties Change-Id: I45bbb2e4addb035f771597b2ebc470b58bf957d7 --- flags/framework.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/framework.aconfig b/flags/framework.aconfig index 1ce042e583c..32b88d447a9 100644 --- a/flags/framework.aconfig +++ b/flags/framework.aconfig @@ -70,4 +70,14 @@ flag { namespace: "bluetooth" description: "Support setting/retrieving the remote device metadata for a BluetoothDevice" bug: "374171574" +} + +flag { + name: "fix_add_device_properties" + namespace: "bluetooth" + description: "Make sure single entry for mDevices. Race fix." + bug: "375158716" + metadata { + purpose: PURPOSE_BUGFIX + } } \ No newline at end of file -- GitLab From 636011df0e4f7bd90eb5002888fce7d3c2ec5403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 23 Oct 2024 14:12:07 +0000 Subject: [PATCH 410/875] RemoteDevice: Fix for race condition on adding device properties There could be a case where addDeviceProperties is called multiple times for the same device which leads to situation of having more than one DeviceProperties for single device. This could lead to undefined behavior when reading properties e.g. bond state etc. It can happen on Bluetooth startup when there is many bonded devices. Bug: 374909756 Bug: 375158716 Test: atest RemoteDevicesTest Flag: com.android.bluetooth.flags.fix_add_device_properties Change-Id: I6292bbe3f68794b0b79f21f2f37e584fbceaec3a --- .../bluetooth/btservice/RemoteDevices.java | 8 +++++++- .../bluetooth/btservice/RemoteDevicesTest.java | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index c48e8b8e3c4..986dd52f402 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -290,10 +290,16 @@ public class RemoteDevices { @VisibleForTesting DeviceProperties addDeviceProperties(byte[] address) { synchronized (mDevices) { + String key = Utils.getAddressStringFromByte(address); + if (Flags.fixAddDeviceProperties() && mDevices.containsKey(key)) { + debugLog("Properties for device " + key + " are already added"); + return mDevices.get(key); + } + DeviceProperties prop = new DeviceProperties(); prop.setDevice(mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address))); prop.setAddress(address); - String key = Utils.getAddressStringFromByte(address); + DeviceProperties pv = mDevices.put(key, prop); if (pv == null) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java index 6129d254978..845a53b77c1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java @@ -17,6 +17,8 @@ import android.os.Bundle; import android.os.HandlerThread; import android.os.Message; import android.os.TestLooperManager; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; @@ -25,6 +27,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.Utils; import com.android.bluetooth.bas.BatteryService; import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; +import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hfp.HeadsetHalConstants; import org.junit.After; @@ -55,6 +58,7 @@ public class RemoteDevicesTest { private Context mTargetContext; private BluetoothManager mBluetoothManager; + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -760,6 +764,18 @@ public class RemoteDevicesTest { Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); } + @Test + @EnableFlags(Flags.FLAG_FIX_ADD_DEVICE_PROPERTIES) + public void testMultipleAddDeviceProperties() { + // Verify that device property is null initially + Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1)); + DeviceProperties prop1 = + mRemoteDevices.addDeviceProperties(Utils.getBytesFromAddress(TEST_BT_ADDR_1)); + DeviceProperties prop2 = + mRemoteDevices.addDeviceProperties(Utils.getBytesFromAddress(TEST_BT_ADDR_1)); + Assert.assertEquals(prop2, prop1); + } + @Test public void testSetgetHfAudioPolicyForRemoteAg() { // Verify that device property is null initially -- GitLab From 558a9cc698fb39016af944455ff3812af363d2cf Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Wed, 16 Oct 2024 10:13:19 -0700 Subject: [PATCH 411/875] stack::avct: Various cleanup 1. Expand avct initiator/acceptor enum syntax 2. Address cpplint errors 3. Update conventional logging a. Use 0x4 hex for l2cap cids b. Use hex for bitmasks 4. Remove dead code and unused definitions 5. Enumified key data types and added string representations 6. Statically scoped l2cap callbacks to translation unit 7. Highlighted issue with data narrowing on RC features Bug: 373471940 Test: m . Flag: EXEMPT, Refactor Change-Id: Ie3719d2b318fe068c8185fddd8d190ca1c5eeef9 --- system/bta/av/bta_av_act.cc | 47 ++--- system/bta/av/bta_av_int.h | 5 +- system/bta/av/bta_av_main.cc | 4 +- system/bta/jv/bta_jv_act.cc | 6 +- system/btif/avrcp/avrcp_service.cc | 3 +- system/profile/avrcp/avrcp_internal.h | 4 +- system/profile/avrcp/connection_handler.cc | 8 +- .../tests/avrcp_connection_handler_test.cc | 8 +- .../profile/avrcp/tests/avrcp_test_helper.h | 2 +- system/stack/avct/avct_api.cc | 42 ++--- system/stack/avct/avct_bcb_act.cc | 82 +++++---- system/stack/avct/avct_ccb.cc | 10 +- system/stack/avct/avct_int.h | 54 +++--- system/stack/avct/avct_l2c.cc | 136 +++++++------- system/stack/avct/avct_l2c_br.cc | 168 ++++++++---------- system/stack/avct/avct_lcb.cc | 41 +++-- system/stack/avct/avct_lcb_act.cc | 34 ++-- system/stack/avrc/avrc_api.cc | 24 +-- system/stack/avrc/avrc_sdp.cc | 18 +- system/stack/fuzzers/avrc_fuzzer.cc | 13 +- system/stack/include/avct_api.h | 25 ++- system/stack/include/avrc_api.h | 12 +- system/stack/include/bt_psm_types.h | 8 +- system/stack/test/stack_l2cap_test.cc | 2 +- system/test/mock/mock_stack_avct_api.cc | 2 +- system/test/mock/mock_stack_avrc_api.cc | 2 +- 26 files changed, 379 insertions(+), 381 deletions(-) diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc index fdc2cfcb981..a01920504d3 100644 --- a/system/bta/av/bta_av_act.cc +++ b/system/bta/av/bta_av_act.cc @@ -321,7 +321,7 @@ static void bta_av_rc_msg_cback(uint8_t handle, uint8_t label, uint8_t opcode, t * Returns the created rc handle * ******************************************************************************/ -uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl, uint8_t lidx) { +uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, tAVCT_ROLE role, uint8_t shdl, uint8_t lidx) { if ((!btif_av_src_sink_coexist_enabled() || (btif_av_src_sink_coexist_enabled() && !btif_av_is_sink_enabled() && btif_av_is_source_enabled())) && @@ -330,14 +330,13 @@ uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl, uint8_t l return BTA_AV_RC_HANDLE_NONE; } - tAVRC_CONN_CB ccb; RawAddress bda = RawAddress::kAny; uint8_t status = BTA_AV_RC_ROLE_ACP; int i; uint8_t rc_handle; - tBTA_AV_RCB* p_rcb; + tBTA_AV_RCB* p_rcb{nullptr}; - if (role == AVCT_INT) { + if (role == AVCT_ROLE_INITIATOR) { // Can't grab a stream control block that doesn't have a valid handle if (!shdl) { log::error("Can't grab stream control block for shdl = {} -> index = {}", shdl, shdl - 1); @@ -357,14 +356,16 @@ uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl, uint8_t l } } - ccb.ctrl_cback = base::Bind(bta_av_rc_ctrl_cback); - ccb.msg_cback = base::Bind(bta_av_rc_msg_cback); - ccb.company_id = p_bta_av_cfg->company_id; - ccb.conn = role; - /* note: BTA_AV_FEAT_RCTG = AVRC_CT_TARGET, BTA_AV_FEAT_RCCT = AVRC_CT_CONTROL - */ - ccb.control = p_cb->features & - (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA | AVRC_CT_PASSIVE); + tAVRC_CONN_CB ccb = { + .ctrl_cback = base::Bind(bta_av_rc_ctrl_cback), + .msg_cback = base::Bind(bta_av_rc_msg_cback), + .company_id = p_bta_av_cfg->company_id, + .conn = role, + // note: BTA_AV_FEAT_RCTG = AVRC_CT_TARGET, BTA_AV_FEAT_RCCT = AVRC_CT_CONTROL + .control = + static_cast(p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | + BTA_AV_FEAT_METADATA | AVRC_CT_PASSIVE)), + }; if (AVRC_Open(&rc_handle, &ccb, bda) != AVRC_SUCCESS) { DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(bda, IOT_CONF_KEY_AVRCP_CONN_FAIL_COUNT); @@ -392,8 +393,8 @@ uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl, uint8_t l p_cb->rc_acp_idx = (i + 1); log::verbose("rc_acp_handle:{} idx:{}", p_cb->rc_acp_handle, p_cb->rc_acp_idx); } - log::verbose("create {}, role: {}, shdl:{}, rc_handle:{}, lidx:{}, status:0x{:x}", i, role, shdl, - p_rcb->handle, lidx, p_rcb->status); + log::verbose("create {}, role: {}, shdl:{}, rc_handle:{}, lidx:{}, status:0x{:x}", i, + avct_role_text(role), shdl, p_rcb->handle, lidx, p_rcb->status); return rc_handle; } @@ -539,7 +540,7 @@ void bta_av_rc_opened(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) { /* listen to browsing channel when the connection is open, * if peer initiated AVRCP connection and local device supports browsing * channel */ - AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_ACP); + AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_ROLE_ACCEPTOR); if (p_cb->rcb[i].lidx == (BTA_AV_NUM_LINKS + 1) && shdl != 0) { /* rc is opened on the RC only ACP channel, but is for a specific @@ -618,7 +619,7 @@ void bta_av_rc_opened(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) { (rc_open.peer_tg_features & BTA_AV_FEAT_BROWSE))) { if ((p_cb->rcb[i].status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT) { log::verbose("opening AVRC Browse channel"); - AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_INT); + AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_ROLE_INITIATOR); } } return; @@ -649,7 +650,7 @@ void bta_av_rc_opened(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) { if ((p_cb->features & BTA_AV_FEAT_BROWSE) && (rc_open.peer_features & BTA_AV_FEAT_BROWSE) && ((p_cb->rcb[i].status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)) { log::verbose("opening AVRC Browse channel"); - AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_INT); + AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_ROLE_INITIATOR); } } @@ -1335,7 +1336,7 @@ void bta_av_conn_chg(tBTA_AV_DATA* p_data) { /* if the AVRCP is no longer listening, create the listening channel */ if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG) { - bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); + bta_av_rc_create(&bta_av_cb, AVCT_ROLE_ACCEPTOR, 0, BTA_AV_NUM_LINKS + 1); } } @@ -1554,7 +1555,7 @@ void bta_av_sig_chg(tBTA_AV_DATA* p_data) { p_lcb->conn_msk = 0; /* clear the connect mask */ /* start listening when the signal channel is open */ if (p_cb->features & BTA_AV_FEAT_RCTG) { - bta_av_rc_create(p_cb, AVCT_ACP, 0, p_lcb->lidx); + bta_av_rc_create(p_cb, AVCT_ROLE_ACCEPTOR, 0, p_lcb->lidx); } /* this entry is not used yet. */ p_cb->conn_lcb |= mask; /* mark it as used */ @@ -2118,7 +2119,8 @@ static void bta_av_rc_disc_done_all(tBTA_AV_DATA* /* p_data */) { ((p_cb->features & BTA_AV_FEAT_RCTG) && (peer_ct_features & BTA_AV_FEAT_RCCT))) { p_lcb = bta_av_find_lcb(p_scb->PeerAddress(), BTA_AV_LCB_FIND); if (p_lcb) { - rc_handle = bta_av_rc_create(p_cb, AVCT_INT, (uint8_t)(p_scb->hdi + 1), p_lcb->lidx); + rc_handle = bta_av_rc_create(p_cb, AVCT_ROLE_INITIATOR, (uint8_t)(p_scb->hdi + 1), + p_lcb->lidx); if (rc_handle != BTA_AV_RC_HANDLE_NONE) { p_cb->rcb[rc_handle].peer_ct_features = peer_ct_features; p_cb->rcb[rc_handle].peer_tg_features = peer_tg_features; @@ -2302,7 +2304,8 @@ void bta_av_rc_disc_done(tBTA_AV_DATA* p_data) { ((p_cb->features & BTA_AV_FEAT_RCTG) && (peer_features & BTA_AV_FEAT_RCCT))) { p_lcb = bta_av_find_lcb(p_scb->PeerAddress(), BTA_AV_LCB_FIND); if (p_lcb) { - rc_handle = bta_av_rc_create(p_cb, AVCT_INT, (uint8_t)(p_scb->hdi + 1), p_lcb->lidx); + rc_handle = bta_av_rc_create(p_cb, AVCT_ROLE_INITIATOR, (uint8_t)(p_scb->hdi + 1), + p_lcb->lidx); if (rc_handle < BTA_AV_NUM_RCB) { p_cb->rcb[rc_handle].peer_features = peer_features; p_cb->rcb[rc_handle].cover_art_psm = cover_art_psm; @@ -2484,7 +2487,7 @@ void bta_av_rc_closed(tBTA_AV_DATA* p_data) { bta_av_data.rc_close = rc_close; (*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, &bta_av_data); if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG) { - bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); + bta_av_rc_create(&bta_av_cb, AVCT_ROLE_ACCEPTOR, 0, BTA_AV_NUM_LINKS + 1); } } diff --git a/system/bta/av/bta_av_int.h b/system/bta/av/bta_av_int.h index 94c63226e02..4f9773344e8 100644 --- a/system/bta/av/bta_av_int.h +++ b/system/bta/av/bta_av_int.h @@ -37,6 +37,7 @@ #include "macros.h" #include "osi/include/list.h" #include "stack/include/a2dp_constants.h" +#include "stack/include/avct_api.h" #include "stack/include/avdt_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/hci_error_code.h" @@ -526,7 +527,7 @@ public: bool use_rc; /* true if AVRCP is allowed */ bool started; /* true if stream started */ bool use_rtp_header_marker_bit; /* true if the encoded data packets have RTP - * headers, and the Marker bit in the header + * headers, with the Marker bit in the header * is set according to RFC 6416 */ uint8_t co_started; /* non-zero, if stream started from call-out perspective */ bool recfg_sup; /* true if the first attempt to reconfigure the stream was @@ -708,7 +709,7 @@ bool bta_av_chk_start(tBTA_AV_SCB* p_scb); void bta_av_restore_switch(void); void bta_av_conn_cback(uint8_t handle, const RawAddress& bd_addr, uint8_t event, tAVDT_CTRL* p_data, uint8_t scb_index); -uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl, uint8_t lidx); +uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, tAVCT_ROLE role, uint8_t shdl, uint8_t lidx); void bta_av_stream_chg(tBTA_AV_SCB* p_scb, bool started); bool bta_av_is_scb_opening(tBTA_AV_SCB* p_scb); bool bta_av_is_scb_incoming(tBTA_AV_SCB* p_scb); diff --git a/system/bta/av/bta_av_main.cc b/system/bta/av/bta_av_main.cc index d8573d7f028..a992882a083 100644 --- a/system/bta/av/bta_av_main.cc +++ b/system/bta/av/bta_av_main.cc @@ -649,7 +649,7 @@ static void bta_av_api_register(tBTA_AV_DATA* p_data) { } /* start listening when A2DP is registered */ if (bta_av_cb.features & BTA_AV_FEAT_RCTG) { - bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); + bta_av_rc_create(&bta_av_cb, AVCT_ROLE_ACCEPTOR, 0, BTA_AV_NUM_LINKS + 1); } /* if the AV and AVK are both supported, it cannot support the CT role @@ -658,7 +658,7 @@ static void bta_av_api_register(tBTA_AV_DATA* p_data) { /* if TG is not supported, we need to register to AVCT now */ if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0) { bta_ar_reg_avct(); - bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); + bta_av_rc_create(&bta_av_cb, AVCT_ROLE_ACCEPTOR, 0, BTA_AV_NUM_LINKS + 1); } if (com::android::bluetooth::flags::avrcp_sdp_records()) { // Add control record for sink profile. diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc index 852204ed617..cb00b7b6f8c 100644 --- a/system/bta/jv/bta_jv_act.cc +++ b/system/bta/jv/bta_jv_act.cc @@ -38,8 +38,6 @@ #include "osi/include/allocator.h" #include "osi/include/properties.h" #include "stack/btm/btm_sec.h" -#include "stack/include/avct_api.h" // AVCT_PSM -#include "stack/include/avdt_api.h" // AVDT_PSM #include "stack/include/bt_hdr.h" #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" @@ -621,8 +619,8 @@ bool bta_jv_check_psm(uint16_t psm) { } break; - case AVCT_PSM: /* 0x17 */ - case AVDT_PSM: /* 0x19 */ + case BT_PSM_AVCTP: /* 0x17 */ + case BT_PSM_AVDTP: /* 0x19 */ if (!bta_sys_is_register(BTA_ID_AV)) { ret = true; } diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc index 577628eb2b0..ce1b1ce5770 100644 --- a/system/btif/avrcp/avrcp_service.cc +++ b/system/btif/avrcp/avrcp_service.cc @@ -32,6 +32,7 @@ #include "btif/include/btif_av.h" #include "btif/include/btif_common.h" #include "osi/include/osi.h" +#include "profile/avrcp/avrcp_config.h" #include "profile/avrcp/device.h" #include "stack/include/a2dp_api.h" #include "stack/include/bt_hdr.h" @@ -100,7 +101,7 @@ public: return AVRC_Open(p_handle, p_ccb, bd_addr); } - uint16_t OpenBrowse(uint8_t handle, uint8_t conn_role) override { + uint16_t OpenBrowse(uint8_t handle, tAVCT_ROLE conn_role) override { return AVRC_OpenBrowse(handle, conn_role); } diff --git a/system/profile/avrcp/avrcp_internal.h b/system/profile/avrcp/avrcp_internal.h index 665382ce61d..a863cb7cf51 100644 --- a/system/profile/avrcp/avrcp_internal.h +++ b/system/profile/avrcp/avrcp_internal.h @@ -16,11 +16,9 @@ #pragma once -#include "avrcp_config.h" #include "stack/include/a2dp_api.h" #include "stack/include/avrc_api.h" #include "stack/include/bt_hdr.h" -#include "stack/include/sdp_api.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" @@ -48,7 +46,7 @@ public: virtual uint16_t Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb, const RawAddress& bd_addr) = 0; - virtual uint16_t OpenBrowse(uint8_t handle, uint8_t conn_role) = 0; + virtual uint16_t OpenBrowse(uint8_t handle, tAVCT_ROLE conn_role) = 0; virtual uint16_t GetPeerMtu(uint8_t handle) = 0; diff --git a/system/profile/avrcp/connection_handler.cc b/system/profile/avrcp/connection_handler.cc index 6faf5cf0e70..96082941617 100644 --- a/system/profile/avrcp/connection_handler.cc +++ b/system/profile/avrcp/connection_handler.cc @@ -233,14 +233,14 @@ bool ConnectionHandler::AvrcpConnect(bool initiator, const RawAddress& bdaddr) { } open_cb.msg_cback = base::Bind(&ConnectionHandler::MessageCb, weak_ptr_factory_.GetWeakPtr()); open_cb.company_id = AVRC_CO_GOOGLE; - open_cb.conn = initiator ? AVRC_CONN_INT : AVRC_CONN_ACP; // 0 if initiator, 1 if acceptor + open_cb.conn = initiator ? AVCT_ROLE_INITIATOR : AVCT_ROLE_ACCEPTOR; // TODO (apanicke): We shouldn't need RCCT to do absolute volume. The current // AVRC_API requires it though. open_cb.control = BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA | AVRC_CT_PASSIVE; uint8_t handle = 0; uint16_t status = avrc_->Open(&handle, &open_cb, bdaddr); - log::info("handle=0x{:x} status= 0x{:x}", handle, status); + log::info("handle=0x{:x} status=0x{:x}", handle, status); return status == AVRC_SUCCESS; } @@ -266,7 +266,7 @@ void ConnectionHandler::InitiatorControlCb(uint8_t handle, uint8_t event, uint16 bool supports_browsing = feature_iter->second & BTA_AV_FEAT_BROWSE; if (supports_browsing) { - avrc_->OpenBrowse(handle, AVCT_INT); + avrc_->OpenBrowse(handle, AVCT_ROLE_INITIATOR); } // TODO (apanicke): Implement a system to cache SDP entries. For most @@ -395,7 +395,7 @@ void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event, uint16_ }; if (SdpLookup(*peer_addr, base::Bind(sdp_lambda, this, handle), false)) { - avrc_->OpenBrowse(handle, AVCT_ACP); + avrc_->OpenBrowse(handle, AVCT_ROLE_ACCEPTOR); } else { // SDP search failed, this could be due to a collision between outgoing // and incoming connection. In any case, we need to reject the current diff --git a/system/profile/avrcp/tests/avrcp_connection_handler_test.cc b/system/profile/avrcp/tests/avrcp_connection_handler_test.cc index 73334576f14..080bda09f39 100644 --- a/system/profile/avrcp/tests/avrcp_connection_handler_test.cc +++ b/system/profile/avrcp/tests/avrcp_connection_handler_test.cc @@ -206,7 +206,7 @@ TEST_F(AvrcpConnectionHandlerTest, remoteDeviceConnectionTest) { // Set an Expectation that OpenBrowse will be called in acceptor mode when the // device connects. - EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_ACP)).Times(1); + EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_ROLE_ACCEPTOR)).Times(1); if (com::android::bluetooth::flags::avrcp_connect_a2dp_with_delay()) { // Set an expectation that SDP for audio will be performed @@ -374,7 +374,7 @@ TEST_F(AvrcpConnectionHandlerTest, multipleRemoteDeviceConnectionTest) { // Set an Expectation that OpenBrowse will be called in acceptor mode when the // device connects on handle 1 - EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_ACP)).Times(1); + EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_ROLE_ACCEPTOR)).Times(1); // Call the callback with a message saying that a remote device has connected conn_cb.ctrl_cback.Run(1, AVRC_OPEN_IND_EVT, 0, &RawAddress::kAny); @@ -391,7 +391,7 @@ TEST_F(AvrcpConnectionHandlerTest, multipleRemoteDeviceConnectionTest) { // Set an Expectation that OpenBrowse will be called in acceptor mode when the // device connects on handle 2 - EXPECT_CALL(mock_avrcp_, OpenBrowse(2, AVCT_ACP)).Times(1); + EXPECT_CALL(mock_avrcp_, OpenBrowse(2, AVCT_ROLE_ACCEPTOR)).Times(1); // Call the callback with a message saying that a remote device has connected // with a different address @@ -504,7 +504,7 @@ TEST_F(AvrcpConnectionHandlerTest, connectToBrowsableRemoteDeviceTest) { // Set an Expectation that OpenBrowse will be called since browsing is listed // as supported in SDP - EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_INT)).Times(1); + EXPECT_CALL(mock_avrcp_, OpenBrowse(1, AVCT_ROLE_INITIATOR)).Times(1); // Call the callback with a message saying that a remote device has connected // with a different address diff --git a/system/profile/avrcp/tests/avrcp_test_helper.h b/system/profile/avrcp/tests/avrcp_test_helper.h index 7a2f63ab2a7..ea6ed4d828d 100644 --- a/system/profile/avrcp/tests/avrcp_test_helper.h +++ b/system/profile/avrcp/tests/avrcp_test_helper.h @@ -80,7 +80,7 @@ public: MOCK_METHOD4(FindService, uint16_t(uint16_t, const RawAddress&, tAVRC_SDP_DB_PARAMS*, tAVRC_FIND_CBACK)); MOCK_METHOD3(Open, uint16_t(uint8_t*, tAVRC_CONN_CB*, const RawAddress&)); - MOCK_METHOD2(OpenBrowse, uint16_t(uint8_t, uint8_t)); + MOCK_METHOD2(OpenBrowse, uint16_t(uint8_t, tAVCT_ROLE)); MOCK_METHOD1(GetPeerMtu, uint16_t(uint8_t)); MOCK_METHOD1(GetBrowseMtu, uint16_t(uint8_t)); MOCK_METHOD1(Close, uint16_t(uint8_t)); diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index 10c441d8767..2c4426f1a5d 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -33,6 +33,7 @@ #include "internal_include/bt_target.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" +#include "stack/include/bt_psm_types.h" #include "stack/include/l2cap_interface.h" #include "types/raw_address.h" @@ -68,20 +69,20 @@ void AVCT_Register() { /* register PSM with L2CAP */ if (!stack::l2cap::get_interface().L2CA_RegisterWithSecurity( - AVCT_PSM, avct_l2c_appl, true /* enable_snoop */, nullptr, kAvrcMtu, 0, sec)) { - log::error("Unable to register with L2CAP AVCT profile psm:AVCT_PSM[0x0017]"); + BT_PSM_AVCTP, avct_l2c_appl, true /* enable_snoop */, nullptr, kAvrcMtu, 0, sec)) { + log::error("Unable to register with L2CAP AVCT profile psm:{}", bt_psm_text(BT_PSM_AVCTP)); } /* Include the browsing channel which uses eFCR */ - tL2CAP_ERTM_INFO ertm_info; - ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE; + tL2CAP_ERTM_INFO ertm_info = { + .preferred_mode = L2CAP_FCR_ERTM_MODE, + }; if (!stack::l2cap::get_interface().L2CA_RegisterWithSecurity( - AVCT_BR_PSM, avct_l2c_br_appl, true /*enable_snoop*/, &ertm_info, kAvrcBrMtu, + BT_PSM_AVCTP_BROWSE, avct_l2c_br_appl, true /*enable_snoop*/, &ertm_info, kAvrcBrMtu, AVCT_MIN_BROWSE_MTU, sec)) { - log::error( - "Unable to register with L2CAP AVCT_BR profile " - "psm:AVCT_BR_PSM[0x001b]"); + log::error("Unable to register with L2CAP AVCT_BROWSE profile psm:{}", + bt_psm_text(BT_PSM_AVCTP_BROWSE)); } } @@ -103,10 +104,10 @@ void AVCT_Deregister(void) { log::verbose("AVCT_Deregister"); /* deregister PSM with L2CAP */ - stack::l2cap::get_interface().L2CA_Deregister(AVCT_PSM); + stack::l2cap::get_interface().L2CA_Deregister(BT_PSM_AVCTP); /* deregister AVCT_BR_PSM with L2CAP */ - stack::l2cap::get_interface().L2CA_Deregister(AVCT_BR_PSM); + stack::l2cap::get_interface().L2CA_Deregister(BT_PSM_AVCTP_BROWSE); } /******************************************************************************* @@ -131,7 +132,7 @@ uint16_t AVCT_CreateConn(uint8_t* p_handle, tAVCT_CC* p_cc, const RawAddress& pe tAVCT_CCB* p_ccb; tAVCT_LCB* p_lcb; - log::verbose("AVCT_CreateConn: {}, control:{}", p_cc->role, p_cc->control); + log::verbose("AVCT_CreateConn:{}, control:0x{:x}", avct_role_text(p_cc->role), p_cc->control); /* Allocate ccb; if no ccbs, return failure */ p_ccb = avct_ccb_alloc(p_cc); @@ -142,7 +143,7 @@ uint16_t AVCT_CreateConn(uint8_t* p_handle, tAVCT_CC* p_cc, const RawAddress& pe *p_handle = avct_ccb_to_idx(p_ccb); /* if initiator connection */ - if (p_cc->role == AVCT_INT) { + if (p_cc->role == AVCT_ROLE_INITIATOR) { /* find link; if none allocate a new one */ p_lcb = avct_lcb_by_bd(peer_addr); if (p_lcb == NULL) { @@ -162,9 +163,10 @@ uint16_t AVCT_CreateConn(uint8_t* p_handle, tAVCT_CC* p_cc, const RawAddress& pe if (result == AVCT_SUCCESS) { /* bind lcb to ccb */ p_ccb->p_lcb = p_lcb; - log::verbose("ch_state: {}", p_lcb->ch_state); - tAVCT_LCB_EVT avct_lcb_evt; - avct_lcb_evt.p_ccb = p_ccb; + log::verbose("ch_state:{}", avct_ch_state_text(p_lcb->ch_state)); + tAVCT_LCB_EVT avct_lcb_evt = { + .p_ccb = p_ccb, + }; avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, &avct_lcb_evt); } } @@ -226,13 +228,13 @@ uint16_t AVCT_RemoveConn(uint8_t handle) { * Returns AVCT_SUCCESS if successful, otherwise error. * ******************************************************************************/ -uint16_t AVCT_CreateBrowse(uint8_t handle, uint8_t role) { +uint16_t AVCT_CreateBrowse(uint8_t handle, tAVCT_ROLE role) { uint16_t result = AVCT_SUCCESS; tAVCT_CCB* p_ccb; tAVCT_BCB* p_bcb; int index; - log::verbose("AVCT_CreateBrowse: {}", role); + log::verbose("AVCT_CreateBrowse: role:{}", avct_role_text(role)); /* map handle to ccb */ p_ccb = avct_ccb_by_idx(handle); @@ -246,7 +248,7 @@ uint16_t AVCT_CreateBrowse(uint8_t handle, uint8_t role) { } /* if initiator connection */ - if (role == AVCT_INT) { + if (role == AVCT_ROLE_INITIATOR) { /* the link control block must exist before this function is called as INT. */ if ((p_ccb->p_lcb == NULL) || (p_ccb->p_lcb->allocated == 0)) { @@ -266,7 +268,7 @@ uint16_t AVCT_CreateBrowse(uint8_t handle, uint8_t role) { /* bind bcb to ccb */ p_ccb->p_bcb = p_bcb; p_bcb->peer_addr = p_ccb->p_lcb->peer_addr; - log::verbose("ch_state: {}", p_bcb->ch_state); + log::verbose("Created BCB ch_state:{}", avct_ch_state_text(p_bcb->ch_state)); tAVCT_LCB_EVT avct_lcb_evt; avct_lcb_evt.p_ccb = p_ccb; avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, &avct_lcb_evt); @@ -390,7 +392,7 @@ uint16_t AVCT_MsgReq(uint8_t handle, uint8_t label, uint8_t cr, BT_HDR* p_msg) { if (p_msg == NULL) { return AVCT_NO_RESOURCES; } - log::verbose("len: {} layer_specific: {}", p_msg->len, p_msg->layer_specific); + log::verbose("msg_len:{} msg_layer_specific:{}", p_msg->len, p_msg->layer_specific); /* map handle to ccb */ p_ccb = avct_ccb_by_idx(handle); diff --git a/system/stack/avct/avct_bcb_act.cc b/system/stack/avct/avct_bcb_act.cc index 96938883707..37a5d20a978 100644 --- a/system/stack/avct/avct_bcb_act.cc +++ b/system/stack/avct/avct_bcb_act.cc @@ -25,8 +25,6 @@ * *****************************************************************************/ -#define LOG_TAG "bluetooth" - #include #include #include @@ -39,11 +37,29 @@ #include "stack/avct/avct_int.h" #include "stack/include/avct_api.h" #include "stack/include/bt_hdr.h" +#include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" #include "stack/include/l2cap_interface.h" using namespace bluetooth; +static void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_chnl_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_send_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_open_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_open_fail(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_close_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_close_cfm(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_cong_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_bind_conn(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_bind_fail(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_unbind_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_chk_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_discard_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_dealloc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); +static void avct_bcb_free_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); + /* action function list */ const tAVCT_BCB_ACTION avct_bcb_action[] = { avct_bcb_chnl_open, /* AVCT_LCB_CHNL_OPEN */ @@ -91,7 +107,7 @@ static BT_HDR* avct_bcb_msg_asmbl(tAVCT_BCB* /* p_bcb */, BT_HDR* p_buf) { /* must be single packet - can not fragment */ if (pkt_type != AVCT_PKT_TYPE_SINGLE) { osi_free_and_reset((void**)&p_buf); - log::warn("Pkt type={} - fragmentation not allowed. drop it", pkt_type); + log::warn("Pkt type:{} - fragmentation not allowed. drop it", pkt_type); } return p_buf; } @@ -109,19 +125,15 @@ static BT_HDR* avct_bcb_msg_asmbl(tAVCT_BCB* /* p_bcb */, BT_HDR* p_buf) { void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* /* p_data */) { uint16_t result = AVCT_RESULT_FAIL; tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); - tL2CAP_ERTM_INFO ertm_info; - - /* Set the FCR options: Browsing channel mandates ERTM */ - ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE; /* call l2cap connect req */ p_bcb->ch_state = AVCT_CH_CONN; if (com::android::bluetooth::flags::use_encrypt_req_for_av()) { p_bcb->ch_lcid = stack::l2cap::get_interface().L2CA_ConnectReqWithSecurity( - AVCT_BR_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); + BT_PSM_AVCTP_BROWSE, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); } else { p_bcb->ch_lcid = stack::l2cap::get_interface().L2CA_ConnectReqWithSecurity( - AVCT_BR_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE); + BT_PSM_AVCTP_BROWSE, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE); } if (p_bcb->ch_lcid == 0) { /* if connect req failed, send ourselves close event */ @@ -166,7 +178,7 @@ bool is_valid_role_check(const tAVCT_CCB* p_ccb) { return com::android::bluetooth::flags:: associate_browse_l2cap_request_with_active_control_channel() ? true - : p_ccb->cc.role == AVCT_ACP; + : p_ccb->cc.role == AVCT_ROLE_ACCEPTOR; } } // namespace @@ -264,7 +276,7 @@ void avct_bcb_close_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* /* p_data */) { for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) { - if (p_ccb->cc.role == AVCT_INT) { + if (p_ccb->cc.role == AVCT_ROLE_INITIATOR) { (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_DISCONN_CFM_EVT, 0, &p_lcb->peer_addr); } else { @@ -288,26 +300,19 @@ void avct_bcb_close_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* /* p_data */) { * ******************************************************************************/ void avct_bcb_close_cfm(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { - tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; - uint8_t event = 0; /* Whether BCB initiated channel close */ - bool ch_close = p_bcb->ch_close; - tAVCT_CTRL_CBACK* p_cback; - + const bool ch_close = p_bcb->ch_close; p_bcb->ch_close = false; p_bcb->allocated = 0; + + tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) { /* if this ccb initiated close send disconnect cfm otherwise ind */ - if (ch_close) { - event = AVCT_BROWSE_DISCONN_CFM_EVT; - } else { - event = AVCT_BROWSE_DISCONN_IND_EVT; - } - - p_cback = p_ccb->cc.p_ctrl_cback; - p_ccb->p_bcb = NULL; - if (p_ccb->p_lcb == NULL) { + uint8_t event = ch_close ? AVCT_BROWSE_DISCONN_CFM_EVT : AVCT_BROWSE_DISCONN_IND_EVT; + tAVCT_CTRL_CBACK* p_cback = p_ccb->cc.p_ctrl_cback; + p_ccb->p_bcb = nullptr; + if (p_ccb->p_lcb == nullptr) { avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL); } (*p_cback)(avct_ccb_to_idx(p_ccb), event, p_data->result, &p_bcb->peer_addr); @@ -397,11 +402,10 @@ void avct_bcb_bind_fail(tAVCT_BCB* /* p_bcb */, tAVCT_LCB_EVT* p_data) { ******************************************************************************/ void avct_bcb_cong_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; - uint8_t event; tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); /* set event */ - event = (p_data->cong) ? AVCT_BROWSE_CONG_IND_EVT : AVCT_BROWSE_UNCONG_IND_EVT; + uint8_t event = (p_data->cong) ? AVCT_BROWSE_CONG_IND_EVT : AVCT_BROWSE_UNCONG_IND_EVT; /* send event to all ccbs on this lcb */ for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { @@ -435,7 +439,8 @@ void avct_bcb_discard_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { p_bcb->p_tx_msg->layer_specific = (p_data->ul_msg.cr << 8) + p_data->ul_msg.label; /* the channel is closed, opening or closing - open it again */ - log::verbose("ch_state: {}, allocated:{}->{}", p_bcb->ch_state, p_bcb->allocated, + log::verbose("ch_state:{} bcb_allocated:{} ccb_lcb_allocated:{}", + avct_ch_state_text(p_bcb->ch_state), p_bcb->allocated, p_data->ul_msg.p_ccb->p_lcb->allocated); p_bcb->allocated = p_data->ul_msg.p_ccb->p_lcb->allocated; avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT*)p_data->ul_msg.p_ccb); @@ -464,7 +469,7 @@ void avct_bcb_send_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { /* initialize packet type and other stuff */ if (curr_msg_len > (p_bcb->peer_mtu - AVCT_HDR_LEN_SINGLE)) { - log::error("msg len ({}) exceeds peer mtu({}-{})!!", curr_msg_len, p_bcb->peer_mtu, + log::error("msg_len:{} exceeds peer mtu:{} header-{})!!", curr_msg_len, p_bcb->peer_mtu, AVCT_HDR_LEN_SINGLE); osi_free_and_reset((void**)&p_data->ul_msg.p_buf); return; @@ -488,7 +493,7 @@ void avct_bcb_send_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { /* send message to L2CAP */ if (stack::l2cap::get_interface().L2CA_DataWrite(p_bcb->ch_lcid, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { - log::warn("Unable to write L2CAP data peer:{} cid:{}", p_bcb->peer_addr, p_bcb->ch_lcid); + log::warn("Unable to write L2CAP data peer:{} cid:0x{:04x}", p_bcb->peer_addr, p_bcb->ch_lcid); } } @@ -543,7 +548,7 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { } if (p_data->p_buf->len < AVCT_HDR_LEN_SINGLE) { - log::warn("Invalid AVCTP packet length {}: must be at least {}", p_data->p_buf->len, + log::warn("Invalid AVCTP packet length:{} must be at least:{}", p_data->p_buf->len, AVCT_HDR_LEN_SINGLE); osi_free_and_reset((void**)&p_data->p_buf); return; @@ -558,7 +563,7 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { /* check for invalid cr_ipid */ if (cr_ipid == AVCT_CR_IPID_INVALID) { - log::warn("Invalid cr_ipid {}", cr_ipid); + log::warn("Invalid cr_ipid:{}", cr_ipid); osi_free_and_reset((void**)&p_data->p_buf); return; } @@ -583,7 +588,7 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { } /* PID not found; drop message */ - log::warn("No ccb for PID={:x}", pid); + log::warn("No ccb for PID=0x{:x}", pid); osi_free_and_reset((void**)&p_data->p_buf); /* if command send reject */ @@ -597,7 +602,8 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { p_buf->layer_specific = AVCT_DATA_BROWSE; if (stack::l2cap::get_interface().L2CA_DataWrite(p_bcb->ch_lcid, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { - log::warn("Unable to write L2CAP data peer:{} cid:{}", p_bcb->peer_addr, p_bcb->ch_lcid); + log::warn("Unable to write L2CAP data peer:{} cid:0x{:04x}", p_bcb->peer_addr, + p_bcb->ch_lcid); } } } @@ -615,13 +621,13 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) { void avct_bcb_dealloc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* /* p_data */) { tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; - log::verbose("{}", p_bcb->allocated); + log::verbose("BCB allocated:{}", p_bcb->allocated); for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) { /* if ccb allocated and */ if ((p_ccb->allocated) && (p_ccb->p_bcb == p_bcb)) { p_ccb->p_bcb = NULL; - log::verbose("used by ccb: {}", idx); + log::verbose("used by ccb idx:{}", idx); break; } } @@ -716,6 +722,6 @@ tAVCT_BCB* avct_bcb_by_lcid(uint16_t lcid) { } /* out of lcbs */ - log::warn("No bcb for lcid {:x}", lcid); - return NULL; + log::warn("No bcb for lcid 0x{:04x}", lcid); + return nullptr; } diff --git a/system/stack/avct/avct_ccb.cc b/system/stack/avct/avct_ccb.cc index 6210fd2fa7b..6ffa34c3fbb 100644 --- a/system/stack/avct/avct_ccb.cc +++ b/system/stack/avct/avct_ccb.cc @@ -23,8 +23,6 @@ * ******************************************************************************/ -#define LOG_TAG "avctp" - #include #include @@ -53,7 +51,7 @@ tAVCT_CCB* avct_ccb_alloc(tAVCT_CC* p_cc) { if (!p_ccb->allocated) { p_ccb->allocated = AVCT_ALOC_LCB; memcpy(&p_ccb->cc, p_cc, sizeof(tAVCT_CC)); - log::verbose("avct_ccb_alloc {}", i); + log::verbose("Allocated ccb idx:{}", i); break; } } @@ -80,7 +78,7 @@ tAVCT_CCB* avct_ccb_alloc(tAVCT_CC* p_cc) { void avct_ccb_dealloc(tAVCT_CCB* p_ccb, uint8_t event, uint16_t result, const RawAddress* bd_addr) { tAVCT_CTRL_CBACK* p_cback = p_ccb->cc.p_ctrl_cback; - log::verbose("avct_ccb_dealloc {}", avct_ccb_to_idx(p_ccb)); + log::verbose("Deallocating idx:{}", avct_ccb_to_idx(p_ccb)); if (p_ccb->p_bcb == NULL) { memset(p_ccb, 0, sizeof(tAVCT_CCB)); @@ -131,11 +129,11 @@ tAVCT_CCB* avct_ccb_by_idx(uint8_t idx) { /* verify ccb is allocated */ if (!p_ccb->allocated) { p_ccb = NULL; - log::warn("ccb {} not allocated", idx); + log::warn("ccb idx:{} not allocated", idx); } } else { p_ccb = NULL; - log::warn("No ccb for idx {}", idx); + log::warn("No ccb for idx:{}", idx); } return p_ccb; } diff --git a/system/stack/avct/avct_int.h b/system/stack/avct/avct_int.h index 08005230627..9efe7ad25eb 100644 --- a/system/stack/avct/avct_int.h +++ b/system/stack/avct/avct_int.h @@ -24,7 +24,10 @@ #ifndef AVCT_INT_H #define AVCT_INT_H +#include + #include "avct_api.h" +#include "include/macros.h" #include "internal_include/bt_target.h" #include "osi/include/fixed_queue.h" #include "stack/include/bt_hdr.h" @@ -48,10 +51,22 @@ enum { }; /* "states" used for L2CAP channel */ -#define AVCT_CH_IDLE 0 /* No connection */ -#define AVCT_CH_CONN 1 /* Waiting for connection confirm */ -#define AVCT_CH_CFG 2 /* Waiting for configuration complete */ -#define AVCT_CH_OPEN 3 /* Channel opened */ +enum tAVCT_CH { + AVCT_CH_IDLE = 0, /* No connection */ + AVCT_CH_CONN = 1, /* Waiting for connection confirm */ + AVCT_CH_CFG = 2, /* Waiting for configuration complete */ + AVCT_CH_OPEN = 3, /* Channel opened */ +}; + +inline std::string avct_ch_state_text(const int& state) { + switch (state) { + CASE_RETURN_STRING(AVCT_CH_IDLE); + CASE_RETURN_STRING(AVCT_CH_CONN); + CASE_RETURN_STRING(AVCT_CH_CFG); + CASE_RETURN_STRING(AVCT_CH_OPEN); + } + RETURN_UNKNOWN_TYPE_STRING(int, state); +} /* "no event" indicator used by ccb dealloc */ #define AVCT_NO_EVT 0xFF @@ -59,16 +74,6 @@ enum { /***************************************************************************** * data types ****************************************************************************/ -/* sub control block type - common data members for tAVCT_LCB and tAVCT_BCB */ -typedef struct { - uint16_t peer_mtu; /* peer l2c mtu */ - uint16_t ch_result; /* L2CAP connection result value */ - uint16_t ch_lcid; /* L2CAP channel LCID */ - uint8_t allocated; /* 0, not allocated. index+1, otherwise. */ - uint8_t state; /* The state machine state */ - uint8_t ch_state; /* L2CAP channel state */ -} tAVCT_SCB; - /* link control block type */ typedef struct { uint16_t peer_mtu; /* peer l2c mtu */ @@ -89,7 +94,7 @@ typedef struct { uint16_t peer_mtu; /* peer l2c mtu */ uint16_t ch_result; /* L2CAP connection result value */ uint16_t ch_lcid; /* L2CAP channel LCID */ - uint8_t allocated; /* 0, not allocated. index+1, otherwise. */ + uint8_t allocated; // 0: no link allocated. otherwise link index+1 uint8_t state; /* The state machine state */ uint8_t ch_state; /* L2CAP channel state */ uint16_t conflict_lcid; /* L2CAP channel LCID */ @@ -173,23 +178,6 @@ void avct_lcb_free_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data); /* BCB action functions */ typedef void (*tAVCT_BCB_ACTION)(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_unbind_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_open_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_open_fail(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_close_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_close_cfm(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_bind_conn(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_chk_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_chnl_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_bind_fail(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_cong_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_discard_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_send_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); -void avct_bcb_free_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); - -void avct_bcb_dealloc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data); extern const tAVCT_BCB_ACTION avct_bcb_action[]; extern const uint8_t avct_lcb_pkt_type_len[]; @@ -203,6 +191,8 @@ tAVCT_CCB* avct_ccb_by_idx(uint8_t idx); extern bool avct_msg_ind_for_src_sink_coexist(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data, uint8_t label, uint8_t cr_ipid, uint16_t pid); +std::string avct_sm_state_text(const int& state); + /***************************************************************************** * global data ****************************************************************************/ diff --git a/system/stack/avct/avct_l2c.cc b/system/stack/avct/avct_l2c.cc index adca67c8511..ffb3a64d3a9 100644 --- a/system/stack/avct/avct_l2c.cc +++ b/system/stack/avct/avct_l2c.cc @@ -21,8 +21,6 @@ * This AVCTP module interfaces to L2CAP * ******************************************************************************/ -#define LOG_TAG "avctp" - #include #include "avct_api.h" @@ -32,18 +30,20 @@ #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" +#include "stack/include/l2cdefs.h" #include "types/raw_address.h" using namespace bluetooth; /* callback function declarations */ -void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t psm, uint8_t id); -void avct_l2c_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result); -void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t result, tL2CAP_CFG_INFO* p_cfg); -void avct_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg); -void avct_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed); -void avct_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested); -void avct_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf); +static void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t psm, + uint8_t id); +static void avct_l2c_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result); +static void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t result, tL2CAP_CFG_INFO* p_cfg); +static void avct_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg); +static void avct_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed); +static void avct_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested); +static void avct_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf); static void avct_on_l2cap_error(uint16_t lcid, uint16_t result); /* L2CAP callback function structure */ @@ -103,21 +103,19 @@ static bool avct_l2c_is_passive(tAVCT_LCB* p_lcb) { ******************************************************************************/ void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t /* psm */, uint8_t /* id */) { - tAVCT_LCB* p_lcb; tL2CAP_CONN result = tL2CAP_CONN::L2CAP_CONN_OK; /* do we already have a channel for this peer? */ - p_lcb = avct_lcb_by_bd(bd_addr); - if (p_lcb == NULL) { + tAVCT_LCB* p_lcb = avct_lcb_by_bd(bd_addr); + if (p_lcb == nullptr) { /* no, allocate lcb */ p_lcb = avct_lcb_alloc(bd_addr); - if (p_lcb == NULL) { + if (p_lcb == nullptr) { /* no ccb available, reject L2CAP connection */ result = tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES; } - } - /* else we already have a channel for this peer */ - else { + } else { + /* else we already have a channel for this peer */ if (!avct_l2c_is_passive(p_lcb) || (p_lcb->ch_state == AVCT_CH_OPEN)) { /* this LCB included CT role - reject */ result = tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES; @@ -125,19 +123,8 @@ void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16 /* TG role only - accept the connection from CT. move the channel ID to * the conflict list */ p_lcb->conflict_lcid = p_lcb->ch_lcid; - log::verbose("avct_l2c_connect_ind_cback conflict_lcid:0x{:x}", p_lcb->conflict_lcid); - } - } - - if (p_lcb) { - log::verbose("avct_l2c_connect_ind_cback: 0x{:x}, res: {}, ch_state: {}", lcid, result, - p_lcb->ch_state); - } - - /* If we reject the connection, send DisconnectReq */ - if (result != tL2CAP_CONN::L2CAP_CONN_OK) { - if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { - log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}", bd_addr, lcid); + log::verbose("Accept connection from controller lcid:0x{:04x} conflict_lcid:0x{:04x}", lcid, + p_lcb->conflict_lcid); } } @@ -146,10 +133,13 @@ void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16 if (btif_av_src_sink_coexist_enabled()) { tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { - if (p_ccb && p_ccb->allocated && (p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP)) { + if (p_ccb && p_ccb->allocated && (p_ccb->p_lcb == NULL) && + (p_ccb->cc.role == AVCT_ROLE_ACCEPTOR)) { p_ccb->p_lcb = p_lcb; - log::verbose("ACP bind {} ccb to lcb, alloc {}, lcb {}, role {}, pid 0x{:x}", i, - p_ccb->allocated, fmt::ptr(p_ccb->p_lcb), p_ccb->cc.role, p_ccb->cc.pid); + log::verbose( + "Source and sink coexistance enabled acceptor bind ccb to lcb idx:{} " + "allocated:{} role {} pid 0x{:x}", + i, p_ccb->allocated, avct_role_text(p_ccb->cc.role), p_ccb->cc.pid); } } } @@ -158,10 +148,19 @@ void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16 /* transition to configuration state */ p_lcb->ch_state = AVCT_CH_CFG; + } else { + /* If we reject the connection, send DisconnectReq */ + if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { + log::warn("Unable to send L2CAP disconnect request peer:{} lcid:0x{:04x}", bd_addr, lcid); + } } if (p_lcb) { - log::verbose("ch_state cni: {}", p_lcb->ch_state); + log::debug("Received remote connection request peer:{} lcid:0x{:04x} res:{} ch_state:{}", + bd_addr, lcid, l2cap_result_code_text(result), avct_ch_state_text(p_lcb->ch_state)); + } else { + log::info("Ignoring remote connection request peer:{} lcid:0x{:04x} res:{} ch_state:{}", + bd_addr, lcid, l2cap_result_code_text(result), avct_ch_state_text(p_lcb->ch_state)); } } @@ -186,7 +185,8 @@ static void avct_on_l2cap_error(uint16_t lcid, uint16_t result) { /* Send L2CAP disconnect req */ if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { - log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}", p_lcb->peer_addr, lcid); + log::warn("Unable to send L2CAP disconnect request peer:{} lcid:0x{:04x}", p_lcb->peer_addr, + lcid); } } } @@ -207,36 +207,34 @@ void avct_l2c_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result) { /* look up lcb for this channel */ p_lcb = avct_lcb_by_lcid(lcid); if (p_lcb != NULL) { - log::verbose( - "avct_l2c_connect_cfm_cback lcid:0x{:x} result: {} ch_state: {}, " - "conflict_lcid:0x{:x}", - lcid, result, p_lcb->ch_state, p_lcb->conflict_lcid); + log::verbose("lcid:0x{:04x} result:{} ch_state:{} conflict_lcid:0x{:04x}", lcid, result, + avct_ch_state_text(p_lcb->ch_state), p_lcb->conflict_lcid); /* if in correct state */ if (p_lcb->ch_state == AVCT_CH_CONN) { /* if result successful */ if (result == tL2CAP_CONN::L2CAP_CONN_OK) { /* set channel state */ p_lcb->ch_state = AVCT_CH_CFG; - } - /* else failure */ - else { - log::error("invoked with non OK status"); + } else { + /* else failure */ + log::error("invoked with non OK status lcid:0x{:04x} result:{}", lcid, + l2cap_result_code_text(result)); } } else if (p_lcb->conflict_lcid == lcid) { /* we must be in AVCT_CH_CFG state for the ch_lcid channel */ - log::verbose("avct_l2c_connect_cfm_cback ch_state: {}, conflict_lcid:0x{:x}", p_lcb->ch_state, + log::verbose("ch_state:{} conflict_lcid:0x{:04x}", avct_ch_state_text(p_lcb->ch_state), p_lcb->conflict_lcid); if (result == tL2CAP_CONN::L2CAP_CONN_OK) { /* just in case the peer also accepts our connection - Send L2CAP * disconnect req */ if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { - log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}", p_lcb->peer_addr, - lcid); + log::warn("Unable to send L2CAP disconnect request peer:{} cid:0x{:04x}", + p_lcb->peer_addr, lcid); } } p_lcb->conflict_lcid = 0; } - log::verbose("ch_state cnc: {}", p_lcb->ch_state); + log::verbose("ch_state:{}", avct_ch_state_text(p_lcb->ch_state)); } } @@ -250,22 +248,29 @@ void avct_l2c_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result) { * Returns void * ******************************************************************************/ -void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t /* initiator */, tL2CAP_CFG_INFO* p_cfg) { +void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t is_initiator_local, tL2CAP_CFG_INFO* p_cfg) { avct_l2c_config_ind_cback(lcid, p_cfg); - tAVCT_LCB* p_lcb; - /* look up lcb for this channel */ - p_lcb = avct_lcb_by_lcid(lcid); - if (p_lcb != NULL) { - log::verbose("avct_l2c_config_cfm_cback: 0x{:x}, ch_state: {},", lcid, p_lcb->ch_state); - /* if in correct state */ - if (p_lcb->ch_state == AVCT_CH_CFG) { - p_lcb->ch_state = AVCT_CH_OPEN; - avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); - } - log::verbose("ch_state cfc: {}", p_lcb->ch_state); + tAVCT_LCB* p_lcb = avct_lcb_by_lcid(lcid); + if (p_lcb == nullptr) { + log::warn("Received config confirm for unknown peer lcid::0x{:04x} is_initiator_local:{}", lcid, + is_initiator_local); + return; + } + + /* if in correct state */ + if (p_lcb->ch_state == AVCT_CH_CFG) { + p_lcb->ch_state = AVCT_CH_OPEN; + avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); + } else { + log::warn( + "Received config confirm in wrong state lcid:0x{:04x} ch_state:{} " + "is_initiator_local:{}", + lcid, avct_ch_state_text(p_lcb->ch_state), is_initiator_local); } + log::verbose("ch_state lcid:0x{:04x} ch_state:{} is_initiator_local:{}", lcid, + avct_ch_state_text(p_lcb->ch_state), is_initiator_local); } /******************************************************************************* @@ -284,7 +289,8 @@ void avct_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) { /* look up lcb for this channel */ p_lcb = avct_lcb_by_lcid(lcid); if (p_lcb != NULL) { - log::verbose("avct_l2c_config_ind_cback: 0x{:x}, ch_state: {}", lcid, p_lcb->ch_state); + log::verbose("avct_l2c_config_ind_cback: 0x{:04x}, ch_state:{}", lcid, + avct_ch_state_text(p_lcb->ch_state)); /* store the mtu in tbl */ if (p_cfg->mtu_present) { p_lcb->peer_mtu = p_cfg->mtu; @@ -339,7 +345,7 @@ void avct_l2c_disconnect(uint16_t lcid, uint16_t result) { tAVCT_LCB_EVT avct_lcb_evt; avct_lcb_evt.result = res; avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); - log::verbose("ch_state dc: {}", p_lcb->ch_state); + log::verbose("ch_state:{}", p_lcb->ch_state); } } @@ -377,15 +383,13 @@ void avct_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested) { * ******************************************************************************/ void avct_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) { - tAVCT_LCB* p_lcb; - - log::verbose("avct_l2c_data_ind_cback: 0x{:x}", lcid); + log::verbose("lcid: 0x{:02x}", lcid); /* look up lcb for this channel */ - p_lcb = avct_lcb_by_lcid(lcid); + tAVCT_LCB* p_lcb = avct_lcb_by_lcid(lcid); if (p_lcb != NULL) { avct_lcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, (tAVCT_LCB_EVT*)&p_buf); - } else /* prevent buffer leak */ - { + } else { + /* prevent buffer leak */ log::warn("ERROR -> avct_l2c_data_ind_cback drop buffer"); osi_free(p_buf); } diff --git a/system/stack/avct/avct_l2c_br.cc b/system/stack/avct/avct_l2c_br.cc index 4c5ccc503b5..3f76e0b76fc 100644 --- a/system/stack/avct/avct_l2c_br.cc +++ b/system/stack/avct/avct_l2c_br.cc @@ -24,30 +24,29 @@ * *****************************************************************************/ -#define LOG_TAG "avctp" - #include -#include "avct_api.h" -#include "avct_int.h" #include "internal_include/bt_target.h" #include "osi/include/allocator.h" +#include "stack/avct/avct_int.h" +#include "stack/include/avct_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" +#include "stack/include/l2cdefs.h" #include "types/raw_address.h" using namespace bluetooth; /* callback function declarations */ -void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t psm, - uint8_t id); -void avct_l2c_br_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result); -void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t result, tL2CAP_CFG_INFO* p_cfg); -void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg); -void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed); -void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested); -void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf); -void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result); +static void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t psm, + uint8_t id); +static void avct_l2c_br_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result); +static void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t result, tL2CAP_CFG_INFO* p_cfg); +static void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg); +static void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed); +static void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested); +static void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf); +static void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result); /* L2CAP callback function structure */ const tL2CAP_APPL_INFO avct_l2c_br_appl = {avct_l2c_br_connect_ind_cback, @@ -77,9 +76,8 @@ const tL2CAP_APPL_INFO avct_l2c_br_appl = {avct_l2c_br_connect_ind_cback, ******************************************************************************/ static bool avct_l2c_br_is_passive(tAVCT_BCB* p_bcb) { bool is_passive = false; - tAVCT_LCB* p_lcb; tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; - p_lcb = avct_lcb_by_bcb(p_bcb); + tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb); int i; for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { @@ -106,12 +104,10 @@ static bool avct_l2c_br_is_passive(tAVCT_BCB* p_bcb) { ******************************************************************************/ void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t /* psm */, uint8_t /* id */) { - tAVCT_LCB* p_lcb; tL2CAP_CONN result = tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES; - tAVCT_BCB* p_bcb; - tL2CAP_ERTM_INFO ertm_info; + tAVCT_BCB* p_bcb{nullptr}; - p_lcb = avct_lcb_by_bd(bd_addr); + tAVCT_LCB* p_lcb = avct_lcb_by_bd(bd_addr); if (p_lcb != NULL) { /* control channel exists */ p_bcb = avct_bcb_by_lcb(p_lcb); @@ -136,26 +132,20 @@ void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uin } } } - /* else no control channel yet, reject */ - - /* Set the FCR options: Browsing channel mandates ERTM */ - ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE; - - /* If we reject the connection, send DisconnectReq */ - if (result != tL2CAP_CONN::L2CAP_CONN_OK) { - log::verbose("Connection rejected to lcid:0x{:x}", lcid); - if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { - log::warn("Unable to send L2CAP disconnect request cid:{}", lcid); - } - } /* if result ok, proceed with connection */ if (result == tL2CAP_CONN::L2CAP_CONN_OK) { /* store LCID */ p_bcb->ch_lcid = lcid; - /* transition to configuration state */ p_bcb->ch_state = AVCT_CH_CFG; + } else { + /* else no control channel yet, reject */ + /* If we reject the connection, send DisconnectReq */ + log::verbose("Connection rejected to lcid:0x{:x}", lcid); + if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { + log::warn("Unable to send L2CAP disconnect request cid:0x{:04x}", lcid); + } } } @@ -174,7 +164,7 @@ void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result) { p_bcb->ch_result = result; /* Send L2CAP disconnect req */ - avct_l2c_br_disconnect(lcid, 0); + avct_l2c_br_disconnect(lcid, 0 /* is_ack_needed */); } /******************************************************************************* @@ -188,24 +178,23 @@ void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result) { * ******************************************************************************/ void avct_l2c_br_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result) { - tAVCT_BCB* p_bcb; - /* look up bcb for this channel */ - p_bcb = avct_bcb_by_lcid(lcid); - - if (p_bcb == NULL) { + tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid); + if (p_bcb == nullptr) { + log::warn( + "Received browse connect confirm callback without a browse control channel " + "lcid:0x{:02x} status:{}", + lcid, l2cap_result_code_text(result)); return; } - /* if in correct state */ if (p_bcb->ch_state == AVCT_CH_CONN) { /* if result successful */ if (result == tL2CAP_CONN::L2CAP_CONN_OK) { /* set channel state */ p_bcb->ch_state = AVCT_CH_CFG; - } - /* else failure */ - else { - log::error("Invoked with non OK status"); + } else { + log::error("Invoked with non OK lcid:0x{:04x} state:{} status:{}", lcid, + avct_ch_state_text(p_bcb->ch_state), l2cap_result_code_text(result)); } } else if (p_bcb->conflict_lcid == lcid) { /* we must be in AVCT_CH_CFG state for the ch_lcid channel */ @@ -214,8 +203,12 @@ void avct_l2c_br_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result) { * disconnect req */ log::verbose("Disconnect conflict_lcid:0x{:x}", p_bcb->conflict_lcid); if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { - log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}", p_bcb->peer_addr, lcid); + log::warn("Unable to send L2CAP disconnect request peer:{} lcid:0x{:04x}", p_bcb->peer_addr, + lcid); } + } else { + log::error("Invoked with failure peer:{} lcid:0x{:04x} conflict_lcid:0x{:04x} status:{}", + p_bcb->peer_addr, lcid, p_bcb->conflict_lcid, l2cap_result_code_text(result)); } p_bcb->conflict_lcid = 0; } @@ -231,19 +224,21 @@ void avct_l2c_br_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result) { * Returns void * ******************************************************************************/ -void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t /* initiator */, tL2CAP_CFG_INFO* p_cfg) { +void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t initiator, tL2CAP_CFG_INFO* p_cfg) { + log::verbose("lcid:0x{:04x} initiator:{}", lcid, initiator); avct_l2c_br_config_ind_cback(lcid, p_cfg); - tAVCT_BCB* p_lcb; - - /* look up lcb for this channel */ - p_lcb = avct_bcb_by_lcid(lcid); - if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CFG)) { + /* look up bcb for this channel */ + tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid); + if ((p_bcb == NULL) || (p_bcb->ch_state != AVCT_CH_CFG)) { + log::warn( + "Got config confirm callback with no browse channel or browse channel not in " + "configuration state"); return; } - p_lcb->ch_state = AVCT_CH_OPEN; - avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); + p_bcb->ch_state = AVCT_CH_OPEN; + avct_bcb_event(p_bcb, AVCT_LCB_LL_OPEN_EVT, NULL); } /******************************************************************************* @@ -257,26 +252,27 @@ void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t /* initiator */, tL2CA * ******************************************************************************/ void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) { - tAVCT_BCB* p_lcb; - uint16_t max_mtu = BT_DEFAULT_BUFFER_SIZE - L2CAP_MIN_OFFSET - BT_HDR_SIZE; + log::verbose("lcid:0x{:04x}", lcid); + const uint16_t max_mtu = BT_DEFAULT_BUFFER_SIZE - L2CAP_MIN_OFFSET - BT_HDR_SIZE; - /* look up lcb for this channel */ - p_lcb = avct_bcb_by_lcid(lcid); - if (p_lcb == NULL) { + /* look up bcb for this channel */ + tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid); + if (p_bcb == NULL) { + log::warn("Unable to find browse control block lcid:0x{:02x}", lcid); return; } /* store the mtu in tbl */ - p_lcb->peer_mtu = L2CAP_DEFAULT_MTU; + p_bcb->peer_mtu = L2CAP_DEFAULT_MTU; if (p_cfg->mtu_present) { - p_lcb->peer_mtu = p_cfg->mtu; + p_bcb->peer_mtu = p_cfg->mtu; } - if (p_lcb->peer_mtu > max_mtu) { - p_lcb->peer_mtu = max_mtu; + if (p_bcb->peer_mtu > max_mtu) { + p_bcb->peer_mtu = max_mtu; } - log::verbose("peer_mtu:{} use:{}", p_lcb->peer_mtu, max_mtu); + log::verbose("peer_mtu:{} max_mtu:{}", p_bcb->peer_mtu, max_mtu); } /******************************************************************************* @@ -290,41 +286,37 @@ void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) { * ******************************************************************************/ void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool /* ack_needed */) { - tAVCT_BCB* p_lcb; uint16_t result = AVCT_RESULT_FAIL; - /* look up lcb for this channel */ - p_lcb = avct_bcb_by_lcid(lcid); - if (p_lcb == NULL) { + /* look up bcb for this channel */ + tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid); + if (p_bcb == NULL) { return; } tAVCT_LCB_EVT avct_lcb_evt; avct_lcb_evt.result = result; - avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); + avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); } void avct_l2c_br_disconnect(uint16_t lcid, uint16_t result) { if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { - log::warn("Unable to send L2CAP disconnect request cid:{}", lcid); + log::warn("Unable to send L2CAP disconnect request cid:0x{:04x}", lcid); } - tAVCT_BCB* p_lcb; - uint16_t res; - - /* look up lcb for this channel */ - p_lcb = avct_bcb_by_lcid(lcid); - if (p_lcb == NULL) { + /* look up bcb for this channel */ + tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid); + if (p_bcb == NULL) { return; } /* result value may be previously stored */ - res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result; - p_lcb->ch_result = 0; + uint16_t res = (p_bcb->ch_result != 0) ? p_bcb->ch_result : result; + p_bcb->ch_result = 0; tAVCT_LCB_EVT avct_lcb_evt; avct_lcb_evt.result = res; - avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); + avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); } /******************************************************************************* @@ -338,17 +330,15 @@ void avct_l2c_br_disconnect(uint16_t lcid, uint16_t result) { * ******************************************************************************/ void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested) { - tAVCT_BCB* p_lcb; - - /* look up lcb for this channel */ - p_lcb = avct_bcb_by_lcid(lcid); - if (p_lcb == NULL) { + /* look up bcb for this channel */ + tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid); + if (p_bcb == NULL) { return; } tAVCT_LCB_EVT avct_lcb_evt; avct_lcb_evt.cong = is_congested; - avct_bcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, &avct_lcb_evt); + avct_bcb_event(p_bcb, AVCT_LCB_LL_CONG_EVT, &avct_lcb_evt); } /******************************************************************************* @@ -362,17 +352,15 @@ void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested) { * ******************************************************************************/ void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) { - tAVCT_BCB* p_lcb; - tAVCT_LCB_EVT evt_data; - - /* look up lcb for this channel */ - p_lcb = avct_bcb_by_lcid(lcid); - if (p_lcb == NULL) { + /* look up bcb for this channel */ + tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid); + if (p_bcb == NULL) { /* prevent buffer leak */ osi_free(p_buf); return; } + tAVCT_LCB_EVT evt_data{}; evt_data.p_buf = p_buf; - avct_bcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, &evt_data); + avct_bcb_event(p_bcb, AVCT_LCB_LL_MSG_EVT, &evt_data); } diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc index 01673e08548..26d4a731605 100644 --- a/system/stack/avct/avct_lcb.cc +++ b/system/stack/avct/avct_lcb.cc @@ -23,17 +23,15 @@ * ******************************************************************************/ -#define LOG_TAG "avctp" - #include #include #include "avct_api.h" #include "avct_int.h" #include "device/include/device_iot_config.h" +#include "include/macros.h" #include "internal_include/bt_target.h" #include "osi/include/allocator.h" -#include "osi/include/osi.h" #include "types/raw_address.h" using namespace bluetooth; @@ -54,6 +52,16 @@ const char* const avct_lcb_evt_str[] = {"UL_BIND_EVT", "UL_UNBIND_EVT", "UL_MS /* lcb state machine states */ enum { AVCT_LCB_IDLE_ST, AVCT_LCB_OPENING_ST, AVCT_LCB_OPEN_ST, AVCT_LCB_CLOSING_ST }; +std::string avct_sm_state_text(const int& state) { + switch (state) { + CASE_RETURN_STRING(AVCT_LCB_IDLE_ST); + CASE_RETURN_STRING(AVCT_LCB_OPENING_ST); + CASE_RETURN_STRING(AVCT_LCB_OPEN_ST); + CASE_RETURN_STRING(AVCT_LCB_CLOSING_ST); + } + RETURN_UNKNOWN_TYPE_STRING(int, state); +} + /* state machine action enumeration list */ enum { AVCT_LCB_CHNL_OPEN, @@ -162,7 +170,7 @@ void avct_lcb_event(tAVCT_LCB* p_lcb, uint8_t event, tAVCT_LCB_EVT* p_data) { uint8_t action; int i; - log::verbose("LCB lcb={} event={} state={}", p_lcb->allocated, avct_lcb_evt_str[event], + log::verbose("LCB lcb_allocated={} event={} state={}", p_lcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_lcb->state]); /* look up the state table for the current state */ @@ -197,22 +205,18 @@ void avct_lcb_event(tAVCT_LCB* p_lcb, uint8_t event, tAVCT_LCB_EVT* p_data) { * ******************************************************************************/ void avct_bcb_event(tAVCT_BCB* p_bcb, uint8_t event, tAVCT_LCB_EVT* p_data) { - tAVCT_LCB_ST_TBL state_table; - uint8_t action; - int i; - - log::verbose("BCB lcb={} event={} state={}", p_bcb->allocated, avct_lcb_evt_str[event], - avct_lcb_st_str[p_bcb->state]); + log::info("BCB bcb_allocated={} event={} state={}", p_bcb->allocated, avct_lcb_evt_str[event], + avct_lcb_st_str[p_bcb->state]); /* look up the state table for the current state */ - state_table = avct_lcb_st_tbl[p_bcb->state]; + tAVCT_LCB_ST_TBL state_table = avct_lcb_st_tbl[p_bcb->state]; /* set next state */ p_bcb->state = state_table[event][AVCT_LCB_NEXT_STATE]; /* execute action functions */ - for (i = 0; i < AVCT_LCB_ACTIONS; i++) { - action = state_table[event][i]; + for (int i = 0; i < AVCT_LCB_ACTIONS; i++) { + uint8_t action = state_table[event][i]; if (action != AVCT_LCB_IGNORE) { (*avct_bcb_action[action])(p_bcb, p_data); } else { @@ -246,7 +250,7 @@ tAVCT_LCB* avct_lcb_by_bd(const RawAddress& bd_addr) { /* if no lcb found */ p_lcb = NULL; - log::verbose("No lcb for addr {}", bd_addr); + log::verbose("No lcb for addr:{}", bd_addr); } return p_lcb; } @@ -269,7 +273,7 @@ tAVCT_LCB* avct_lcb_alloc(const RawAddress& bd_addr) { if (!p_lcb->allocated) { p_lcb->allocated = (uint8_t)(i + 1); p_lcb->peer_addr = bd_addr; - log::verbose("avct_lcb_alloc {}", p_lcb->allocated); + log::verbose("lcb_allocated:{}", p_lcb->allocated); p_lcb->tx_q = fixed_queue_new(SIZE_MAX); p_lcb->peer_mtu = L2CAP_LE_MIN_MTU; break; @@ -295,14 +299,14 @@ tAVCT_LCB* avct_lcb_alloc(const RawAddress& bd_addr) { * ******************************************************************************/ void avct_lcb_dealloc(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* /* p_data */) { - log::verbose("allocated: {}", p_lcb->allocated); + log::verbose("lcb_allocated:{}", p_lcb->allocated); // Check if the LCB is still referenced tAVCT_CCB* p_ccb = &avct_cb.ccb[0]; for (size_t i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { if (p_ccb->allocated && p_ccb->p_lcb == p_lcb) { - log::verbose("LCB in use; lcb index: {}", i); + log::verbose("LCB in use; lcb index:{}", i); return; } } @@ -382,8 +386,7 @@ bool avct_lcb_last_ccb(tAVCT_LCB* p_lcb, tAVCT_CCB* p_ccb_last) { log::warn("avct_lcb_last_ccb"); for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { - log::warn("{:x}: aloc:{}, lcb:0x{}/0x{}, ccb:0x{}/0x{}", i, p_ccb->allocated, - fmt::ptr(p_ccb->p_lcb), fmt::ptr(p_lcb), fmt::ptr(p_ccb), fmt::ptr(p_ccb_last)); + log::warn("index:{} allocated:{}, ", i, p_ccb->allocated); if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb != p_ccb_last)) { return false; } diff --git a/system/stack/avct/avct_lcb_act.cc b/system/stack/avct/avct_lcb_act.cc index e06bf57634a..986bce7d34b 100644 --- a/system/stack/avct/avct_lcb_act.cc +++ b/system/stack/avct/avct_lcb_act.cc @@ -33,7 +33,9 @@ #include "internal_include/bt_target.h" #include "osi/include/allocator.h" #include "stack/avct/avct_defs.h" +#include "stack/include/avct_api.h" #include "stack/include/bt_hdr.h" +#include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" #include "stack/include/l2cap_interface.h" @@ -190,10 +192,10 @@ void avct_lcb_chnl_open(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* /* p_data */) { p_lcb->ch_state = AVCT_CH_CONN; if (com::android::bluetooth::flags::use_encrypt_req_for_av()) { p_lcb->ch_lcid = stack::l2cap::get_interface().L2CA_ConnectReqWithSecurity( - AVCT_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); + BT_PSM_AVCTP, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); } else { p_lcb->ch_lcid = stack::l2cap::get_interface().L2CA_ConnectReqWithSecurity( - AVCT_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE); + BT_PSM_AVCTP, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE); } if (p_lcb->ch_lcid == 0) { /* if connect req failed, send ourselves close event */ @@ -239,7 +241,7 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { bool is_originater = false; for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { - if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && p_ccb->cc.role == AVCT_INT) { + if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && p_ccb->cc.role == AVCT_ROLE_INITIATOR) { log::verbose("find int handle {}", i); is_originater = true; } @@ -250,16 +252,16 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { /* if ccb allocated and */ /** M: to avoid avctp collision, make sure the collision can be checked @{ */ - log::verbose("{} ccb to lcb, alloc {}, lcb {}, role {}, pid 0x{:x}", i, p_ccb->allocated, - fmt::ptr(p_ccb->p_lcb), p_ccb->cc.role, p_ccb->cc.pid); + log::verbose("{} ccb to lcb, alloc {}, role {}, pid 0x{:04x}", i, p_ccb->allocated, + avct_role_text(p_ccb->cc.role), p_ccb->cc.pid); if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) { /* if bound to this lcb send connect confirm event */ - if (p_ccb->cc.role == AVCT_INT) { + if (p_ccb->cc.role == AVCT_ROLE_INITIATOR) { /** @} */ bind = true; if (!stack::l2cap::get_interface().L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH)) { - log::warn("Unable to set L2CAP transmit high priority peer:{} cid:{}", + log::warn("Unable to set L2CAP transmit high priority peer:{} lcid:0x{:04x}", p_ccb->p_lcb->peer_addr, p_lcb->ch_lcid); } p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT, 0, @@ -269,7 +271,7 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { */ /** M: to avoid avctp collision, make sure the collision can be checked @{ */ - else if ((p_ccb->cc.role == AVCT_ACP) && avct_lcb_has_pid(p_lcb, p_ccb->cc.pid)) { + else if ((p_ccb->cc.role == AVCT_ROLE_ACCEPTOR) && avct_lcb_has_pid(p_lcb, p_ccb->cc.pid)) { /* bind ccb to lcb and send connect ind event */ if (is_originater) { log::error("int exist, unbind acp handle:{}", i); @@ -279,7 +281,7 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { p_ccb->p_lcb = p_lcb; if (!stack::l2cap::get_interface().L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH)) { - log::warn("Unable to set L2CAP transmit high priority peer:{} cid:{}", + log::warn("Unable to set L2CAP transmit high priority peer:{} lcid:0x{:04x}", p_ccb->p_lcb->peer_addr, p_lcb->ch_lcid); } p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT, 0, @@ -297,7 +299,7 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { bind = true; if (!stack::l2cap::get_interface().L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH)) { - log::warn("Unable to set L2CAP transmit high priority peer:{} cid:{}", + log::warn("Unable to set L2CAP transmit high priority peer:{} lcid:0x{:04x}", p_ccb->p_lcb->peer_addr, p_lcb->ch_lcid); } p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT, 0, @@ -305,14 +307,14 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { } /* if unbound acceptor and lcb doesn't already have a ccb for this PID */ - else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) && + else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ROLE_ACCEPTOR) && (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL)) { /* bind ccb to lcb and send connect ind event */ bind = true; p_ccb->p_lcb = p_lcb; if (!stack::l2cap::get_interface().L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH)) { - log::warn("Unable to set L2CAP transmit high priority peer:{} cid:{}", + log::warn("Unable to set L2CAP transmit high priority peer:{} lcid:0x{:04x}", p_ccb->p_lcb->peer_addr, p_lcb->ch_lcid); } p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT, 0, @@ -369,7 +371,7 @@ void avct_lcb_close_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* /* p_data */) { for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) { - if (p_ccb->cc.role == AVCT_INT) { + if (p_ccb->cc.role == AVCT_ROLE_INITIATOR) { avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT, 0, &p_lcb->peer_addr); } else { p_ccb->p_lcb = NULL; @@ -406,7 +408,7 @@ void avct_lcb_close_cfm(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { event = AVCT_DISCONNECT_IND_EVT; } - if (p_ccb->cc.role == AVCT_INT) { + if (p_ccb->cc.role == AVCT_ROLE_INITIATOR) { avct_ccb_dealloc(p_ccb, event, p_data->result, &p_lcb->peer_addr); } else { p_ccb->p_lcb = NULL; @@ -714,7 +716,7 @@ void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { } /* PID not found; drop message */ - log::warn("No ccb for PID={:x}", pid); + log::warn("No ccb for PID=0x{:04x}", pid); osi_free_and_reset((void**)&p_data->p_buf); /* if command send reject */ @@ -727,7 +729,7 @@ void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { UINT16_TO_BE_STREAM(p, pid); if (stack::l2cap::get_interface().L2CA_DataWrite(p_lcb->ch_lcid, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { - log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_lcb->peer_addr, + log::warn("Unable to write L2CAP data peer:{} lcid:0x{:04x} len:{}", p_lcb->peer_addr, p_lcb->ch_lcid, p_buf->len); } } diff --git a/system/stack/avrc/avrc_api.cc b/system/stack/avrc/avrc_api.cc index 2acddeb5e0f..a2d75c218a5 100644 --- a/system/stack/avrc/avrc_api.cc +++ b/system/stack/avrc/avrc_api.cc @@ -1062,16 +1062,15 @@ uint16_t AVRC_GetProfileVersion() { * *****************************************************************************/ uint16_t AVRC_Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb, const RawAddress& peer_addr) { - uint16_t status; - tAVCT_CC cc; - - cc.p_ctrl_cback = avrc_ctrl_cback; /* Control callback */ - cc.p_msg_cback = avrc_msg_cback; /* Message callback */ - cc.pid = UUID_SERVCLASS_AV_REMOTE_CONTROL; /* Profile ID */ - cc.role = p_ccb->conn; /* Initiator/acceptor role */ - cc.control = p_ccb->control; /* Control role (Control/Target) */ - - status = AVCT_CreateConn(p_handle, &cc, peer_addr); + tAVCT_CC cc = { + .p_ctrl_cback = avrc_ctrl_cback, /* Control callback */ + .p_msg_cback = avrc_msg_cback, /* Message callback */ + .pid = UUID_SERVCLASS_AV_REMOTE_CONTROL, /* Profile ID */ + .role = p_ccb->conn, /* Initiator/acceptor role */ + .control = p_ccb->control, /* Control role (Control/Target) */ + }; + + uint16_t status = AVCT_CreateConn(p_handle, &cc, peer_addr); if (status == AVCT_SUCCESS) { avrc_cb.ccb[*p_handle] = *p_ccb; memset(&avrc_cb.ccb_int[*p_handle], 0, sizeof(tAVRC_CONN_INT_CB)); @@ -1080,7 +1079,8 @@ uint16_t AVRC_Open(uint8_t* p_handle, tAVRC_CONN_CB* p_ccb, const RawAddress& pe avrc_cb.ccb_int[*p_handle].tle = alarm_new("avrcp.commandTimer"); avrc_cb.ccb_int[*p_handle].cmd_q = fixed_queue_new(SIZE_MAX); } - log::verbose("role: {}, control:{} status:{}, handle:{}", cc.role, cc.control, status, *p_handle); + log::verbose("role: {}, control:0x{:x} status:{}, handle:{}", avct_role_text(cc.role), cc.control, + status, *p_handle); return status; } @@ -1123,7 +1123,7 @@ uint16_t AVRC_Close(uint8_t handle) { * the connection. * *****************************************************************************/ -uint16_t AVRC_OpenBrowse(uint8_t handle, uint8_t conn_role) { +uint16_t AVRC_OpenBrowse(uint8_t handle, tAVCT_ROLE conn_role) { return AVCT_CreateBrowse(handle, conn_role); } diff --git a/system/stack/avrc/avrc_sdp.cc b/system/stack/avrc/avrc_sdp.cc index d4ed5bb4211..61ba721b5fc 100644 --- a/system/stack/avrc/avrc_sdp.cc +++ b/system/stack/avrc/avrc_sdp.cc @@ -28,6 +28,7 @@ #include "avrc_api.h" #include "avrc_int.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" @@ -64,16 +65,19 @@ static uint16_t a2dp_attr_list_sdp[] = { * Returns Nothing. * *****************************************************************************/ -static void avrc_sdp_cback(const RawAddress& /* bd_addr */, tSDP_STATUS status) { - log::verbose("status: {}", status); +static void avrc_sdp_cback(const RawAddress& bd_addr, tSDP_STATUS status) { + log::verbose("peer:{} status: {}", bd_addr, status); /* reset service_uuid, so can start another find service */ avrc_cb.service_uuid = 0; /* return info from sdp record in app callback function */ - avrc_cb.find_cback.Run(status); - - return; + if (!avrc_cb.find_cback.is_null()) { + avrc_cb.find_cback.Run(status); + } else { + log::warn("Received SDP callback with NULL callback peer:{} status:{}", bd_addr, + sdp_status_text(status)); + } } /****************************************************************************** @@ -246,7 +250,7 @@ uint16_t AVRC_AddRecord(uint16_t service_uuid, const char* p_service_name, tSDP_PROTOCOL_ELEM avrc_proto_desc_list[AVRC_NUM_PROTO_ELEMS]; avrc_proto_desc_list[0].num_params = 1; avrc_proto_desc_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; - avrc_proto_desc_list[0].params[0] = AVCT_PSM; + avrc_proto_desc_list[0].params[0] = BT_PSM_AVCTP; avrc_proto_desc_list[0].params[1] = 0; for (index = 1; index < AVRC_NUM_PROTO_ELEMS; index++) { avrc_proto_desc_list[index].num_params = 1; @@ -270,7 +274,7 @@ uint16_t AVRC_AddRecord(uint16_t service_uuid, const char* p_service_name, avrc_add_proto_desc_lists[i].num_elems = 2; avrc_add_proto_desc_lists[i].list_elem[0].num_params = 1; avrc_add_proto_desc_lists[i].list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP; - avrc_add_proto_desc_lists[i].list_elem[0].params[0] = AVCT_BR_PSM; + avrc_add_proto_desc_lists[i].list_elem[0].params[0] = BT_PSM_AVCTP_BROWSE; avrc_add_proto_desc_lists[i].list_elem[0].params[1] = 0; avrc_add_proto_desc_lists[i].list_elem[1].num_params = 1; avrc_add_proto_desc_lists[i].list_elem[1].protocol_uuid = UUID_PROTOCOL_AVCTP; diff --git a/system/stack/fuzzers/avrc_fuzzer.cc b/system/stack/fuzzers/avrc_fuzzer.cc index 1592b707fd5..be0c80f32c3 100644 --- a/system/stack/fuzzers/avrc_fuzzer.cc +++ b/system/stack/fuzzers/avrc_fuzzer.cc @@ -20,18 +20,17 @@ #include #include -#include #include #include "osi/include/allocator.h" #include "stack/include/avct_api.h" #include "stack/include/avrc_api.h" +#include "stack/include/bt_psm_types.h" #include "test/fake/fake_osi.h" #include "test/mock/mock_btif_config.h" #include "test/mock/mock_stack_acl.h" #include "test/mock/mock_stack_btm_dev.h" #include "test/mock/mock_stack_l2cap_api.h" -#include "test/mock/mock_stack_l2cap_ble.h" #include "types/bluetooth/uuid.h" // TODO(b/369381361) Enfore -Wmissing-prototypes @@ -81,11 +80,11 @@ public: [](uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu, uint16_t required_remote_mtu, uint16_t sec_level) { - log::assert_that(psm == AVCT_PSM || psm == AVCT_BR_PSM, - "assert failed: psm == AVCT_PSM || psm == AVCT_BR_PSM"); - if (psm == AVCT_PSM) { + log::assert_that(psm == BT_PSM_AVCTP || psm == BT_PSM_AVCTP_BROWSE, + "assert failed: psm == BT_PSM_AVCTP || psm == BT_PSM_AVCTP_BROWSE"); + if (psm == BT_PSM_AVDTP) { avct_appl = p_cb_info; - } else if (psm == AVCT_BR_PSM) { + } else if (psm == BT_PSM_AVCTP_BROWSE) { avct_br_appl = p_cb_info; } return psm; @@ -186,7 +185,7 @@ static void Fuzz(const uint8_t* data, size_t size) { tAVRC_CONN_CB ccb = { .ctrl_cback = base::Bind(ctrl_cb), .msg_cback = base::Bind(msg_cb), - .conn = (uint8_t)(is_initiator ? AVCT_INT : AVCT_ACP), + .conn = (is_initiator ? AVCT_ROLE_INITIATOR : AVCT_ROLE_ACCEPTOR), .control = (uint8_t)(is_controller ? AVCT_CONTROL : AVCT_TARGET), }; diff --git a/system/stack/include/avct_api.h b/system/stack/include/avct_api.h index 0ac2399b937..0cf58171baa 100644 --- a/system/stack/include/avct_api.h +++ b/system/stack/include/avct_api.h @@ -26,8 +26,9 @@ #define AVCT_API_H #include +#include -#include "internal_include/bt_target.h" +#include "include/macros.h" #include "stack/include/bt_hdr.h" #include "types/raw_address.h" @@ -42,10 +43,6 @@ #define AVCT_PID_IN_USE 3 /* PID already in use */ #define AVCT_NOT_OPEN 4 /* Connection not open */ -/* PSM for AVCT. */ -#define AVCT_PSM 0x0017 -#define AVCT_BR_PSM 0x001B - /* Protocol revision numbers */ #define AVCT_REV_1_0 0x0100 #define AVCT_REV_1_2 0x0102 @@ -69,8 +66,18 @@ #define AVCT_BROWSE_OFFSET 17 /* the default offset for browsing channel */ /* Connection role. */ -#define AVCT_INT 0 /* Initiator connection */ -#define AVCT_ACP 1 /* Acceptor connection */ +typedef enum { + AVCT_ROLE_INITIATOR = 0, /* Initiator connection */ + AVCT_ROLE_ACCEPTOR = 1, /* Acceptor connection */ +} tAVCT_ROLE; + +inline std::string avct_role_text(const tAVCT_ROLE& role) { + switch (role) { + CASE_RETURN_TEXT(AVCT_ROLE_INITIATOR); + CASE_RETURN_TEXT(AVCT_ROLE_ACCEPTOR); + } + RETURN_UNKNOWN_TYPE_STRING(tAVCT_ROLE, role); +} /* Control role. */ #define AVCT_TARGET 1 /* target */ @@ -116,7 +123,7 @@ typedef struct { tAVCT_CTRL_CBACK* p_ctrl_cback; /* Control callback */ tAVCT_MSG_CBACK* p_msg_cback; /* Message callback */ uint16_t pid; /* Profile ID */ - uint8_t role; /* Initiator/acceptor role */ + tAVCT_ROLE role; /* Initiator/acceptor role */ uint8_t control; /* Control role (Control/Target) */ } tAVCT_CC; @@ -207,7 +214,7 @@ uint16_t AVCT_RemoveConn(uint8_t handle); * Returns AVCT_SUCCESS if successful, otherwise error. * ******************************************************************************/ -uint16_t AVCT_CreateBrowse(uint8_t handle, uint8_t role); +uint16_t AVCT_CreateBrowse(uint8_t handle, tAVCT_ROLE role); /******************************************************************************* * diff --git a/system/stack/include/avrc_api.h b/system/stack/include/avrc_api.h index 918bdfb4366..589ddb5021b 100644 --- a/system/stack/include/avrc_api.h +++ b/system/stack/include/avrc_api.h @@ -65,12 +65,6 @@ /* If conflict, allow the other side to succeed */ #define AVRC_CT_PASSIVE 4 -/* Connection role */ -/* initiator */ -#define AVRC_CONN_INT AVCT_INT -/* Acceptor */ -#define AVRC_CONN_ACP AVCT_ACP - /* AVRC CTRL events */ /* AVRC_OPEN_IND_EVT event is sent when the connection is successfully opened. * This eventis sent in response to an AVRC_Open(). */ @@ -201,7 +195,7 @@ typedef struct { * attribute filter * to be ATTR_ID_SERVICE_CLASS_ID_LIST, * ATTR_ID_BT_PROFILE_DESC_LIST, - * ATTR_ID_SUPPORTED_FEATURES, ATTR_ID_SERVICE_NAME and + * ATTR_ID_SUPPORTED_FEATURES, ATTR_ID_SERVICE_NAME, * ATTR_ID_PROVIDER_NAME. * If not NULL, the input is taken as the filter. */ } tAVRC_SDP_DB_PARAMS; @@ -229,7 +223,7 @@ typedef struct { tAVRC_CTRL_CBACK ctrl_cback; /* application control callback */ tAVRC_MSG_CBACK msg_cback; /* application message callback */ uint32_t company_id; /* the company ID */ - uint8_t conn; /* Connection role (Initiator/acceptor) */ + tAVCT_ROLE conn; /* Connection role (Initiator/acceptor) */ uint8_t control; /* Control role (Control/Target) */ } tAVRC_CONN_CB; @@ -460,7 +454,7 @@ uint16_t AVRC_Close(uint8_t handle); * the connection. * *****************************************************************************/ -uint16_t AVRC_OpenBrowse(uint8_t handle, uint8_t conn_role); +uint16_t AVRC_OpenBrowse(uint8_t handle, tAVCT_ROLE conn_role); /****************************************************************************** * diff --git a/system/stack/include/bt_psm_types.h b/system/stack/include/bt_psm_types.h index a5bb3e47e45..3f0716110b8 100644 --- a/system/stack/include/bt_psm_types.h +++ b/system/stack/include/bt_psm_types.h @@ -36,9 +36,9 @@ enum tBT_PSM : uint16_t { BT_PSM_UPNP = 0x0015, BT_PSM_AVCTP = 0x0017, BT_PSM_AVDTP = 0x0019, - BT_PSM_AVCTP_13 = 0x001B, /* Advanced Control - Browsing */ - BT_PSM_UDI_CP = 0x001D, /* Unrestricted Digital Information Profile C-Plane */ - BT_PSM_ATT = 0x001F, /* Attribute Protocol */ + BT_PSM_AVCTP_BROWSE = 0x001B, /* Advanced Control - Browsing */ + BT_PSM_UDI_CP = 0x001D, /* Unrestricted Digital Information Profile C-Plane */ + BT_PSM_ATT = 0x001F, /* Attribute Protocol */ BT_PSM_EATT = 0x0027, /* We will not allocate a PSM in the reserved range to 3rd party apps */ @@ -58,7 +58,7 @@ inline std::string bt_psm_text(const tBT_PSM& psm) { CASE_RETURN_STRING_HEX04(BT_PSM_UPNP); CASE_RETURN_STRING_HEX04(BT_PSM_AVCTP); CASE_RETURN_STRING_HEX04(BT_PSM_AVDTP); - CASE_RETURN_STRING_HEX04(BT_PSM_AVCTP_13); + CASE_RETURN_STRING_HEX04(BT_PSM_AVCTP_BROWSE); CASE_RETURN_STRING_HEX04(BT_PSM_UDI_CP); CASE_RETURN_STRING_HEX04(BT_PSM_ATT); CASE_RETURN_STRING_HEX04(BT_PSM_EATT); diff --git a/system/stack/test/stack_l2cap_test.cc b/system/stack/test/stack_l2cap_test.cc index d2d19bf39ea..ffe78055bc7 100644 --- a/system/stack/test/stack_l2cap_test.cc +++ b/system/stack/test/stack_l2cap_test.cc @@ -287,7 +287,7 @@ TEST_F(StackL2capTest, bt_psm_text) { {BT_PSM_UPNP, "BT_PSM_UPNP"}, {BT_PSM_AVCTP, "BT_PSM_AVCTP"}, {BT_PSM_AVDTP, "BT_PSM_AVDTP"}, - {BT_PSM_AVCTP_13, "BT_PSM_AVCTP_13"}, + {BT_PSM_AVCTP_BROWSE, "BT_PSM_AVCTP_BROWSE"}, {BT_PSM_UDI_CP, "BT_PSM_UDI_CP"}, {BT_PSM_ATT, "BT_PSM_ATT"}, {BT_PSM_EATT, "BT_PSM_EATT"}, diff --git a/system/test/mock/mock_stack_avct_api.cc b/system/test/mock/mock_stack_avct_api.cc index 42dae210436..a63348f30c3 100644 --- a/system/test/mock/mock_stack_avct_api.cc +++ b/system/test/mock/mock_stack_avct_api.cc @@ -24,7 +24,7 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" -uint16_t AVCT_CreateBrowse(uint8_t /* handle */, uint8_t /* role */) { +uint16_t AVCT_CreateBrowse(uint8_t /* handle */, tAVCT_ROLE /* role */) { inc_func_call_count(__func__); return 0; } diff --git a/system/test/mock/mock_stack_avrc_api.cc b/system/test/mock/mock_stack_avrc_api.cc index 5409f753452..22b3f15f196 100644 --- a/system/test/mock/mock_stack_avrc_api.cc +++ b/system/test/mock/mock_stack_avrc_api.cc @@ -58,7 +58,7 @@ uint16_t AVRC_Open(uint8_t* /* p_handle */, tAVRC_CONN_CB* /* p_ccb */, inc_func_call_count(__func__); return 0; } -uint16_t AVRC_OpenBrowse(uint8_t /* handle */, uint8_t /* conn_role */) { +uint16_t AVRC_OpenBrowse(uint8_t /* handle */, tAVCT_ROLE /* conn_role */) { inc_func_call_count(__func__); return 0; } -- GitLab From 4f585543cf8c044b5b0e84966fd33ee7cbea559d Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 22 Oct 2024 15:07:15 -0700 Subject: [PATCH 412/875] btif_a2dp_source: Trace offload a2dp sessions Metric trace generation was skipped when the a2dp session was offloaded; resulting in skewed codec statistics. Bug: 346590002 Test: m com.android.btservices Test: Manual streaming tests Flag: EXEMPT, minor bugfix Change-Id: Ied6372c3c4d751b0fbd10b13372acf181e95affa --- system/btif/src/btif_a2dp.cc | 2 ++ system/btif/src/btif_a2dp_source.cc | 56 ++++++++++++----------------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/system/btif/src/btif_a2dp.cc b/system/btif/src/btif_a2dp.cc index f8036bf8c8f..01127c3a68d 100644 --- a/system/btif/src/btif_a2dp.cc +++ b/system/btif/src/btif_a2dp.cc @@ -130,6 +130,8 @@ void btif_a2dp_on_offload_started(const RawAddress& peer_addr, tBTA_AV_STATUS st switch (status) { case BTA_AV_SUCCESS: + // Call required to update the session state for metrics. + btif_a2dp_source_start_audio_req(); ack = BluetoothAudioStatus::SUCCESS; break; case BTA_AV_FAIL_RESOURCES: diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index af1e7244b01..aa333b73287 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -753,7 +753,6 @@ void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) { } } else { bluetooth::audio::a2dp::ack_stream_suspended(BluetoothAudioStatus::SUCCESS); - return; } if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) { @@ -789,7 +788,6 @@ void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { } } else if (btif_av_is_a2dp_offload_running()) { bluetooth::audio::a2dp::ack_stream_suspended(BluetoothAudioStatus::SUCCESS); - return; } // ensure tx frames are immediately suspended @@ -811,60 +809,54 @@ static void btif_a2dp_source_audio_tx_start_event(void) { log::info("streaming {} state={}", btif_a2dp_source_is_streaming(), btif_a2dp_source_cb.StateStr()); + btif_a2dp_source_cb.stats.Reset(); + btif_a2dp_source_cb.stats.session_start_us = bluetooth::common::time_get_os_boottime_us(); + btif_a2dp_source_cb.stats.session_end_us = 0; + + A2dpCodecConfig* codec_config = bta_av_get_a2dp_current_codec(); + if (codec_config != nullptr) { + btif_a2dp_source_cb.stats.codec_index = codec_config->codecIndex(); + } + if (btif_av_is_a2dp_offload_running()) { return; } - /* Reset the media feeding state */ log::assert_that(btif_a2dp_source_cb.encoder_interface != nullptr, "assert failed: btif_a2dp_source_cb.encoder_interface != nullptr"); - btif_a2dp_source_cb.encoder_interface->feeding_reset(); - log::verbose("starting timer {} ms", + log::verbose("starting media encoder timer with interval {}ms", btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms()); - /* audio engine starting, reset tx suspended flag */ - btif_a2dp_source_cb.tx_flush = false; - wakelock_acquire(); + btif_a2dp_source_cb.encoder_interface->feeding_reset(); + btif_a2dp_source_cb.tx_flush = false; + btif_a2dp_source_cb.sw_audio_is_encoding = true; btif_a2dp_source_cb.media_alarm.SchedulePeriodic( btif_a2dp_source_thread.GetWeakPtr(), FROM_HERE, base::BindRepeating(&btif_a2dp_source_audio_handle_timer), std::chrono::milliseconds( btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms())); - btif_a2dp_source_cb.sw_audio_is_encoding = true; - - btif_a2dp_source_cb.stats.Reset(); - // Assign session_start_us to 1 when - // bluetooth::common::time_get_os_boottime_us() is 0 to indicate - // btif_a2dp_source_start_audio_req() has been called - btif_a2dp_source_cb.stats.session_start_us = bluetooth::common::time_get_os_boottime_us(); - if (btif_a2dp_source_cb.stats.session_start_us == 0) { - btif_a2dp_source_cb.stats.session_start_us = 1; - } - btif_a2dp_source_cb.stats.session_end_us = 0; - A2dpCodecConfig* codec_config = bta_av_get_a2dp_current_codec(); - if (codec_config != nullptr) { - btif_a2dp_source_cb.stats.codec_index = codec_config->codecIndex(); - } } static void btif_a2dp_source_audio_tx_stop_event(void) { log::info("streaming {} state={}", btif_a2dp_source_is_streaming(), btif_a2dp_source_cb.StateStr()); + btif_a2dp_source_cb.stats.session_end_us = bluetooth::common::time_get_os_boottime_us(); + + btif_a2dp_source_update_metrics(); + btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats, + &btif_a2dp_source_cb.accumulated_stats); + if (btif_av_is_a2dp_offload_running()) { return; } + if (!btif_a2dp_source_is_streaming()) { return; } - btif_a2dp_source_cb.stats.session_end_us = bluetooth::common::time_get_os_boottime_us(); - btif_a2dp_source_update_metrics(); - btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats, - &btif_a2dp_source_cb.accumulated_stats); - /* Drain data still left in the queue */ static constexpr size_t AUDIO_STREAM_OUTPUT_BUFFER_SZ = 28 * 512; uint8_t p_buf[AUDIO_STREAM_OUTPUT_BUFFER_SZ * 2]; @@ -1250,15 +1242,11 @@ static void btif_a2dp_source_update_metrics(void) { A2dpSessionMetrics metrics; metrics.codec_index = stats.codec_index; metrics.is_a2dp_offload = btif_av_is_a2dp_offload_running(); + // session_start_us is 0 when btif_a2dp_source_start_audio_req() is not called // mark the metric duration as invalid (-1) in this case if (stats.session_start_us != 0) { - int64_t session_end_us = stats.session_end_us == 0 - ? bluetooth::common::time_get_os_boottime_us() - : stats.session_end_us; - if (static_cast(session_end_us) > stats.session_start_us) { - metrics.audio_duration_ms = (session_end_us - stats.session_start_us) / 1000; - } + metrics.audio_duration_ms = (stats.session_end_us - stats.session_start_us) / 1000; } if (enqueue_stats.total_updates > 1) { -- GitLab From 50fbe743a987bdb9e0b243396373c2df0367710a Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 23 Oct 2024 13:49:22 -0700 Subject: [PATCH 413/875] AdapterService: Don't check in teardown If teardown throw an exception, this is what will be displayed in case of test failure. Even if there is an actual & different test failure. By moving the check within the test, we will now be having the real failure instead, and triage will be able to be more efficient Bug: 375091640 Test: atest BluetoothIntrumentationTests Flag: TEST_ONLY Change-Id: Icd7117029c99a796ff0b4c18f794935fe9b432c9 --- .../btservice/AdapterServiceTest.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) 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 7dadb2cc339..f73e0f064e0 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 @@ -346,7 +346,6 @@ public class AdapterServiceTest { // Restores the foregroundUserId to the ID prior to the test setup Utils.setForegroundUserId(mForegroundUserId); - assertThat(mLooper.nextMessage()).isNull(); mAdapterService.cleanup(); mAdapterService.unregisterRemoteCallback(mIBluetoothCallback); AdapterNativeInterface.setInstance(null); @@ -567,6 +566,7 @@ public class AdapterServiceTest { @Test public void testEnable() { doEnable(false); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -580,6 +580,7 @@ public class AdapterServiceTest { verify(mNativeInterface).setScanMode(eq(halExpectedScanMode)); assertThat(mAdapterService.getScanMode()).isEqualTo(expectedScanMode); + assertThat(mLooper.nextMessage()).isNull(); } /** Test: Turn Bluetooth on/off. Check whether the AdapterService gets started and stopped. */ @@ -587,6 +588,7 @@ public class AdapterServiceTest { public void testEnableDisable() { doEnable(false); doDisable(false); + assertThat(mLooper.nextMessage()).isNull(); } /** @@ -613,6 +615,7 @@ public class AdapterServiceTest { Config.init(mockContext); doEnable(true); doDisable(true); + assertThat(mLooper.nextMessage()).isNull(); } /** Test: Don't start GATT Check whether the AdapterService quits gracefully */ @@ -646,6 +649,7 @@ public class AdapterServiceTest { verifyStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); + assertThat(mLooper.nextMessage()).isNull(); } /** Test: Don't stop GATT Check whether the AdapterService quits gracefully */ @@ -679,6 +683,7 @@ public class AdapterServiceTest { verifyStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -691,6 +696,7 @@ public class AdapterServiceTest { dropNextMessage(MESSAGE_PROFILE_SERVICE_REGISTERED); dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -700,6 +706,7 @@ public class AdapterServiceTest { assertThat(mAdapterService.getBluetoothGatt()).isNull(); assertThat(mAdapterService.getBluetoothScan()).isNotNull(); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -741,6 +748,7 @@ public class AdapterServiceTest { assertThat(mAdapterService.getBluetoothScan()).isNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -808,6 +816,7 @@ public class AdapterServiceTest { assertThat(mAdapterService.getState()).isEqualTo(STATE_BLE_ON); mAdapterService.unregisterRemoteCallback(callback); + assertThat(mLooper.nextMessage()).isNull(); } /** Test: Don't start a classic profile Check whether the AdapterService quits gracefully */ @@ -851,6 +860,7 @@ public class AdapterServiceTest { // Ensure GATT is still running assertThat(mAdapterService.getBluetoothGatt()).isNotNull(); + assertThat(mLooper.nextMessage()).isNull(); } /** Test: Don't stop a classic profile Check whether the AdapterService quits gracefully */ @@ -885,6 +895,7 @@ public class AdapterServiceTest { verifyStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); + assertThat(mLooper.nextMessage()).isNull(); } /** Test: Toggle snoop logging setting Check whether the AdapterService restarts fully */ @@ -933,6 +944,7 @@ public class AdapterServiceTest { // Restore earlier setting BluetoothProperties.snoop_log_mode(snoopSetting); + assertThat(mLooper.nextMessage()).isNull(); } /** @@ -943,6 +955,7 @@ public class AdapterServiceTest { @Test public void testObfuscateBluetoothAddress_NullAddress() { assertThat(mAdapterService.obfuscateAddress(null)).isEmpty(); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -963,6 +976,7 @@ public class AdapterServiceTest { // Verify we can get correct identity address identityAddress = mAdapterService.getIdentityAddress(TEST_BT_ADDR_1); assertThat(identityAddress).isEqualTo(TEST_BT_ADDR_2); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -972,6 +986,7 @@ public class AdapterServiceTest { assertThat(mAdapterService.getByteIdentityAddress(device)).isNull(); assertThat(mAdapterService.getIdentityAddress(device.getAddress())).isNull(); + assertThat(mLooper.nextMessage()).isNull(); } public static byte[] getMetricsSalt(Map> adapterConfig) { @@ -1021,6 +1036,7 @@ public class AdapterServiceTest { @Test public void testGetMetricId_NullAddress() { assertThat(mAdapterService.getMetricId(null)).isEqualTo(0); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -1033,6 +1049,7 @@ public class AdapterServiceTest { doReturn(new byte[0]).when(mNativeInterface).dumpMetrics(); mAdapterService.dump(fd, writer, new String[] {"--proto-bin"}); mAdapterService.dump(fd, writer, new String[] {"random", "arguments"}); + assertThat(mLooper.nextMessage()).isNull(); } @Test @@ -1070,5 +1087,6 @@ public class AdapterServiceTest { Files.deleteIfExists(randomFileUnderBluedroidPath); Files.deleteIfExists(randomFileUnderBluetoothPath); } + assertThat(mLooper.nextMessage()).isNull(); } } -- GitLab From a4391a5f6acca03e421fa3c68d9ab2ec2678c112 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 23 Oct 2024 11:11:52 -0700 Subject: [PATCH 414/875] Add flag a2dp_source_threading_fix Bug: 374166531 Bug: 315241296 Flag: com.android.bluetooth.flags.a2dp_source_threading_fix Test: m com.android.btservices Change-Id: I246b88b0cbad6f938e56a658ff29044ba2e58b26 --- flags/a2dp.aconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/flags/a2dp.aconfig b/flags/a2dp.aconfig index 2026a474461..ba1943b9447 100644 --- a/flags/a2dp.aconfig +++ b/flags/a2dp.aconfig @@ -147,3 +147,14 @@ flag { purpose: PURPOSE_BUGFIX } } + + +flag { + name: "a2dp_source_threading_fix" + namespace: "bluetooth" + description: "Schedule A2DP source setup operations to bt_main_thread to prevent races" + bug: "374166531" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From 7e55631009150634dda67c5f2a2f57c1941b410e Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 23 Oct 2024 13:49:10 -0700 Subject: [PATCH 415/875] btif_a2dp_source: Remove sanity checks from timer handler Bug: 352246888 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: I510ef41cea620151d0b9b3c400e60c2c692d361b --- system/btif/src/btif_a2dp_source.cc | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 1e631232ab7..d1e425ed039 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -886,29 +886,26 @@ static void btif_a2dp_source_audio_tx_stop_event(void) { } static void btif_a2dp_source_audio_handle_timer(void) { - if (btif_av_is_a2dp_offload_running()) { - return; - } - uint64_t timestamp_us = bluetooth::common::time_get_audio_server_tick_us(); uint64_t stats_timestamp_us = bluetooth::common::time_get_os_boottime_us(); log_tstamps_us("A2DP Source tx scheduling timer", timestamp_us); - if (!btif_a2dp_source_is_streaming()) { - log::error("ERROR Media task Scheduled after Suspend"); - return; - } log::assert_that(btif_a2dp_source_cb.encoder_interface != nullptr, "assert failed: btif_a2dp_source_cb.encoder_interface != nullptr"); + size_t transmit_queue_length = fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue); + #ifdef __ANDROID__ ATRACE_INT("btif TX queue", transmit_queue_length); #endif + if (btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length != nullptr) { btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length(transmit_queue_length); } + btif_a2dp_source_cb.encoder_interface->send_frames(timestamp_us); + bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_enqueue_stats, stats_timestamp_us, btif_a2dp_source_cb.encoder_interval_ms * 1000); @@ -934,17 +931,13 @@ static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) { return bytes_read; } +/// Callback invoked by the encoder for sending encoded audio frames to the +/// remote Bluetooth device. Runs on the source worker thread. static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n, uint32_t /*bytes_read*/) { uint64_t now_us = bluetooth::common::time_get_os_boottime_us(); - /* Check if timer was stopped (media task stopped) */ - if (!btif_a2dp_source_is_streaming()) { - osi_free(p_buf); - return false; - } - - /* Check if the transmission queue has been flushed */ + // Check if the transmission queue has been flushed. if (btif_a2dp_source_cb.tx_flush) { log::verbose("tx suspended, discarded frame"); @@ -1007,12 +1000,10 @@ static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n, } } - /* Update the statistics */ + // Update the statistics. btif_a2dp_source_cb.stats.tx_queue_total_frames += frames_n; btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet = std::max(frames_n, btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet); - log::assert_that(btif_a2dp_source_cb.encoder_interface != nullptr, - "assert failed: btif_a2dp_source_cb.encoder_interface != nullptr"); fixed_queue_enqueue(btif_a2dp_source_cb.tx_audio_queue, p_buf); -- GitLab From d0e8bb0d1fd651146da534046dd16ca8614155b1 Mon Sep 17 00:00:00 2001 From: Sarvesh Kalwit Date: Wed, 23 Oct 2024 22:02:24 +0000 Subject: [PATCH 416/875] Fix empty data mask detection The ScanFilter class also denotes no-op data masks as a single 0 byte. Update the MSFT Advertisement Monitor creation logic to handle this case. Bug: 360391998 Bug: 365787977 Flag: com.android.bluetooth.flags.le_scan_msft_support Test: atest BluetoothInstrumentationTests:ScanManagerTest Change-Id: Icb36acf9c050b95097da6d846e264161e2a97c6a --- .../com/android/bluetooth/le_scan/MsftAdvMonitor.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java b/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java index acf80cfd76e..657ea4d5a99 100644 --- a/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java +++ b/android/app/src/com/android/bluetooth/le_scan/MsftAdvMonitor.java @@ -70,7 +70,7 @@ class MsftAdvMonitor { mMonitor.rssi_sampling_period = RSSI_SAMPLING_PERIOD; mMonitor.condition_type = MSFT_CONDITION_TYPE_PATTERNS; - if (filter.getServiceDataUuid() != null && filter.getServiceDataMask() == null) { + if (filter.getServiceDataUuid() != null && dataMaskIsEmpty(filter.getServiceDataMask())) { Pattern pattern = new Pattern(); pattern.ad_type = (byte) 0x16; // Bluetooth Core Spec Part A, Section 1 pattern.start_byte = FILTER_PATTERN_START_POSITION; @@ -86,8 +86,7 @@ class MsftAdvMonitor { mPatterns.add(pattern); } else if (filter.getAdvertisingData() != null && filter.getAdvertisingData().length != 0 - && (filter.getAdvertisingDataMask() == null - || filter.getAdvertisingDataMask().length == 0)) { + && dataMaskIsEmpty(filter.getAdvertisingDataMask())) { Pattern pattern = new Pattern(); pattern.ad_type = (byte) filter.getAdvertisingDataType(); pattern.start_byte = FILTER_PATTERN_START_POSITION; @@ -112,4 +111,10 @@ class MsftAdvMonitor { Address getAddress() { return mAddress; } + + private boolean dataMaskIsEmpty(byte[] mask) { + if (mask == null || mask.length == 0) return true; + if (mask.length == 1 && mask[0] == 0) return true; + return false; + } } -- GitLab From 3a0ab1a200e6e4b92e641d258472177fca2af4ad Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 23 Oct 2024 15:46:20 -0700 Subject: [PATCH 417/875] Adapter: static cache for getState Since: * getState does not requires any permission * has only one unique and identique value for the whole system Then I believe we do not need to pass any parameter to the cache and we also do not need to cache multiples entries Bug: 374222784 Bug: 362569584 Flag: com.android.bluetooth.flags.get_state_from_system_server Test: m . Change-Id: I692f62675f3d90d6446ced8e8e29e12f51ba692f --- .../android/bluetooth/BluetoothAdapter.java | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 4c4571d4c78..f345bb5502f 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -1491,24 +1491,29 @@ public final class BluetoothAdapter { } }; - private static final IpcDataCache.QueryHandler - sBluetoothGetSystemStateQuery = - new IpcDataCache.QueryHandler<>() { - @RequiresNoPermission - @Override - public @InternalAdapterState Integer apply(IBluetoothManager serviceQuery) { - try { - return serviceQuery.getState(); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } - } - @RequiresNoPermission - @Override - public boolean shouldBypassCache(IBluetoothManager serviceQuery) { - return false; - } - }; + private static final IpcDataCache.QueryHandler sBluetoothGetSystemStateQuery = + new IpcDataCache.QueryHandler<>() { + @RequiresNoPermission + @Override + public @InternalAdapterState Integer apply(Void query) { + try { + IBluetoothManager service = + IBluetoothManager.Stub.asInterface( + BluetoothFrameworkInitializer.getBluetoothServiceManager() + .getBluetoothManagerServiceRegisterer() + .get()); + return service.getState(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @RequiresNoPermission + @Override + public boolean shouldBypassCache(Void query) { + return false; + } + }; private static final String GET_STATE_API = "BluetoothAdapter_getState"; @@ -1518,9 +1523,9 @@ public final class BluetoothAdapter { private static final IpcDataCache sBluetoothGetStateCache = new BluetoothCache<>(GET_STATE_API, sBluetoothGetStateQuery); - private static final IpcDataCache sBluetoothGetSystemStateCache = + private static final IpcDataCache sBluetoothGetSystemStateCache = new IpcDataCache<>( - 8, + 1, IBluetoothManager.IPC_CACHE_MODULE_SYSTEM, GET_SYSTEM_STATE_API, GET_SYSTEM_STATE_API, @@ -1546,14 +1551,7 @@ public final class BluetoothAdapter { /** Fetch the current bluetooth state. If the service is down, return OFF. */ private @InternalAdapterState int getStateInternal() { if (Flags.getStateFromSystemServer()) { - try { - return sBluetoothGetSystemStateCache.query(mManagerService); - } catch (RuntimeException runtime) { - if (runtime.getCause() instanceof RemoteException e) { - throw e.rethrowFromSystemServer(); - } - throw runtime; - } + return sBluetoothGetSystemStateCache.query(null); } mServiceLock.readLock().lock(); try { -- GitLab From 5cd9c5e8688abdbd0917c34d45baf4e89d9eb36a Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 23 Oct 2024 16:43:14 -0700 Subject: [PATCH 418/875] Errorprone enforce NullablePrimitive NullableVoid Bug: 344658662 Test: m com.android.btservice Flag: Exempt refactor annotation only Change-Id: I20d951cb49b289b6eb880cb8d175f62242b1306c --- Android.bp | 2 ++ .../com/android/bluetooth/btservice/RemoteDevices.java | 3 --- framework/api/system-current.txt | 8 ++++---- framework/java/android/bluetooth/OobData.java | 4 +--- .../android/bluetooth/le/DistanceMeasurementSession.java | 4 ++-- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Android.bp b/Android.bp index 4a5ba15f664..71d6d402c26 100644 --- a/Android.bp +++ b/Android.bp @@ -143,6 +143,8 @@ java_defaults { "-Xep:NonAtomicVolatileUpdate:ERROR", "-Xep:NonCanonicalType:ERROR", "-Xep:NotJavadoc:ERROR", + "-Xep:NullablePrimitive:ERROR", + "-Xep:NullableVoid:ERROR", "-Xep:ObjectEqualsForPrimitives:ERROR", "-Xep:OperatorPrecedence:ERROR", "-Xep:ReferenceEquality:ERROR", diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index c48e8b8e3c4..66bf8f1f739 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -42,8 +42,6 @@ import android.os.ParcelUuid; import android.os.SystemProperties; import android.util.Log; -import androidx.annotation.NonNull; - import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.R; import com.android.bluetooth.Utils; @@ -1315,7 +1313,6 @@ public class RemoteDevices { mAdapterService.aclStateChangeBroadcastCallback(connectionChangeConsumer); } - @NonNull private void sendPairingCancelIntent(BluetoothDevice device) { Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 7eef1c1d6a7..7aa89155b14 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -1166,8 +1166,8 @@ package android.bluetooth { method @NonNull public byte[] getDeviceAddressWithType(); method @Nullable public byte[] getDeviceName(); method @Nullable public byte[] getLeAppearance(); - method @NonNull public int getLeDeviceRole(); - method @NonNull public int getLeFlags(); + method public int getLeDeviceRole(); + method public int getLeFlags(); method @Nullable public byte[] getLeTemporaryKey(); method @NonNull public byte[] getRandomizerHash(); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -1382,9 +1382,9 @@ package android.bluetooth.le { public static interface DistanceMeasurementSession.Callback { method public void onResult(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.le.DistanceMeasurementResult); - method public void onStartFail(@NonNull int); + method public void onStartFail(int); method public void onStarted(@NonNull android.bluetooth.le.DistanceMeasurementSession); - method public void onStopped(@NonNull android.bluetooth.le.DistanceMeasurementSession, @NonNull int); + method public void onStopped(@NonNull android.bluetooth.le.DistanceMeasurementSession, int); } @Deprecated public final class ResultStorageDescriptor implements android.os.Parcelable { diff --git a/framework/java/android/bluetooth/OobData.java b/framework/java/android/bluetooth/OobData.java index a90516d6164..e6c5f945d85 100644 --- a/framework/java/android/bluetooth/OobData.java +++ b/framework/java/android/bluetooth/OobData.java @@ -750,7 +750,6 @@ public final class OobData implements Parcelable { * 55 of LMP Feature Mask Definitions. 0x05- 0x07 Reserved * @hide */ - @NonNull @SystemApi @LeFlag public int getLeFlags() { @@ -766,7 +765,6 @@ public final class OobData implements Parcelable { * Preferred 0x04 - 0xFF Reserved * @hide */ - @NonNull @SystemApi public @LeRole int getLeDeviceRole() { return mLeDeviceRole; @@ -849,7 +847,7 @@ public final class OobData implements Parcelable { } // For Parcelable - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = + public static final @NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public OobData createFromParcel(Parcel in) { return new OobData(in); diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java index d91fbade2c4..a36887ba9ba 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java @@ -177,7 +177,7 @@ public final class DistanceMeasurementSession { * @hide */ @SystemApi - void onStartFail(@NonNull @Reason int reason); + void onStartFail(@Reason int reason); /** * Invoked when a distance measurement session stopped. @@ -186,7 +186,7 @@ public final class DistanceMeasurementSession { * @hide */ @SystemApi - void onStopped(@NonNull DistanceMeasurementSession session, @NonNull @Reason int reason); + void onStopped(@NonNull DistanceMeasurementSession session, @Reason int reason); /** * Invoked when get distance measurement result. -- GitLab From a3eefca823137793026feb798bf5d1440ceaa1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Ko=C5=82odziejczyk?= Date: Wed, 25 Sep 2024 12:42:40 +0000 Subject: [PATCH 419/875] broadcast: Remove redundant broadcast start Since Audio Framework driven BIG creation was introduced, there is no need for external call for starting broadacst. Broadcast start is now driven by Audio Framework callbacks. Bug: 369554930 Bug: 347204335 Test: atest LeAudioBroadcastServiceTest Test: atest bluetooth_test_broadcaster bluetooth_test_broadcaster_state_machine Flag: leaudio_big_depends_on_audio_state Change-Id: I02db58b85f1f117115845431ed7990cab4328554 --- .../bluetooth/le_audio/LeAudioService.java | 197 +++++++----- .../le_audio/LeAudioBroadcastServiceTest.java | 304 ++++++++++-------- .../bta/le_audio/broadcaster/broadcaster.cc | 13 +- .../le_audio/broadcaster/broadcaster_test.cc | 99 +++--- .../le_audio/broadcaster/mock_state_machine.h | 1 + 5 files changed, 334 insertions(+), 280 deletions(-) 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 c93e10febd7..0683607ef5a 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -117,6 +117,9 @@ public class LeAudioService extends ProfileService { // Timeout for state machine thread join, to prevent potential ANR. private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; + /* 5 seconds timeout for Broadcast streaming state transition */ + private static final int CREATE_BROADCAST_TIMEOUT_MS = 5000; + private static LeAudioService sLeAudioService; /** Indicates group audio support for none direction */ @@ -151,9 +154,6 @@ public class LeAudioService extends ProfileService { .setSampleRate(BluetoothLeAudioCodecConfig.SAMPLE_RATE_48000) .build(); - /* 5 seconds timeout for Broadcast streaming state transition */ - private static final int DIALING_OUT_TIMEOUT_MS = 5000; - private AdapterService mAdapterService; private DatabaseManager mDatabaseManager; private HandlerThread mStateMachinesThread; @@ -165,6 +165,8 @@ public class LeAudioService extends ProfileService { private final ReentrantReadWriteLock mGroupReadWriteLock = new ReentrantReadWriteLock(); private final Lock mGroupReadLock = mGroupReadWriteLock.readLock(); private final Lock mGroupWriteLock = mGroupReadWriteLock.writeLock(); + private CreateBroadcastTimeoutEvent mCreateBroadcastTimeoutEvent; + ServiceFactory mServiceFactory = new ServiceFactory(); private final LeAudioNativeInterface mNativeInterface; @@ -182,7 +184,6 @@ public class LeAudioService extends ProfileService { BluetoothDevice mLeAudioDeviceInactivatedForHfpHandover = null; LeAudioBroadcasterNativeInterface mLeAudioBroadcasterNativeInterface = null; - private DialingOutTimeoutEvent mDialingOutTimeoutEvent = null; @VisibleForTesting AudioManager mAudioManager; LeAudioTmapGattServer mTmapGattServer; int mTmapRoleMask; @@ -653,7 +654,7 @@ public class LeAudioService extends ProfileService { mIsSinkStreamMonitorModeEnabled = false; mIsBroadcastPausedFromOutside = false; - clearBroadcastTimeoutCallback(); + clearCreateBroadcastTimeoutCallback(); if (!Flags.leaudioSynchronizeStart()) { mHandler.removeCallbacks(this::init); @@ -1148,29 +1149,48 @@ public class LeAudioService extends ProfileService { return LE_AUDIO_GROUP_ID_INVALID; } - /** - * Creates LeAudio Broadcast instance with BluetoothLeBroadcastSettings. - * - * @param broadcastSettings broadcast settings for this broadcast source - */ - public void createBroadcast(BluetoothLeBroadcastSettings broadcastSettings) { + private int canBroadcastBeCreated(BluetoothLeBroadcastSettings broadcastSettings) { if (mBroadcastDescriptors.size() >= getMaximumNumberOfBroadcasts()) { Log.w( TAG, "createBroadcast reached maximum allowed broadcasts number: " + getMaximumNumberOfBroadcasts()); - mHandler.post( - () -> - notifyBroadcastStartFailed( - BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES)); - return; + return BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES; + } + + byte[] broadcastCode = broadcastSettings.getBroadcastCode(); + if (broadcastCode != null && ((broadcastCode.length > 16) || (broadcastCode.length < 4))) { + Log.e(TAG, "Invalid broadcast code length. Should be from 4 to 16 octets long."); + return BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_CODE; + } + + List settingsList = + broadcastSettings.getSubgroupSettings(); + if (settingsList == null || settingsList.size() < 1) { + Log.d(TAG, "subgroup settings is not valid value"); + return BluetoothStatusCodes.ERROR_BAD_PARAMETERS; } + return BluetoothStatusCodes.SUCCESS; + } + + /** + * Creates LeAudio Broadcast instance with BluetoothLeBroadcastSettings. + * + * @param broadcastSettings broadcast settings for this broadcast source + */ + public void createBroadcast(BluetoothLeBroadcastSettings broadcastSettings) { if (mLeAudioBroadcasterNativeInterface == null) { Log.w(TAG, "Native interface not available."); return; } + int canBroadcastBeCreatedReturnCode = canBroadcastBeCreated(broadcastSettings); + if (canBroadcastBeCreatedReturnCode != BluetoothStatusCodes.SUCCESS) { + mHandler.post(() -> notifyBroadcastStartFailed(canBroadcastBeCreatedReturnCode)); + return; + } + if (mAwaitingBroadcastCreateResponse) { mCreateBroadcastQueue.add(broadcastSettings); Log.i(TAG, "Broadcast creation queued due to waiting for a previous request response."); @@ -1192,21 +1212,6 @@ public class LeAudioService extends ProfileService { } } - byte[] broadcastCode = broadcastSettings.getBroadcastCode(); - boolean isEncrypted = (broadcastCode != null) && (broadcastCode.length != 0); - if (isEncrypted) { - if ((broadcastCode.length > 16) || (broadcastCode.length < 4)) { - Log.e(TAG, "Invalid broadcast code length. Should be from 4 to 16 octets long."); - return; - } - } - - List settingsList = - broadcastSettings.getSubgroupSettings(); - if (settingsList == null || settingsList.size() < 1) { - Log.d(TAG, "subgroup settings is not valid value"); - return; - } mBroadcastSessionStats.put( INVALID_BROADCAST_ID, new LeAudioBroadcastSessionStats(broadcastSettings, SystemClock.elapsedRealtime())); @@ -1214,19 +1219,37 @@ public class LeAudioService extends ProfileService { BluetoothLeAudioContentMetadata publicMetadata = broadcastSettings.getPublicBroadcastMetadata(); - Log.i(TAG, "createBroadcast: isEncrypted=" + (isEncrypted ? "true" : "false")); + byte[] broadcastCode = broadcastSettings.getBroadcastCode(); + Log.i( + TAG, + "createBroadcast: isEncrypted=" + + (((broadcastCode != null) && (broadcastCode.length != 0)) + ? "true" + : "false")); mAwaitingBroadcastCreateResponse = true; if (leaudioBigDependsOnAudioState()) { mCreateBroadcastQueue.add(broadcastSettings); } + + if (leaudioBigDependsOnAudioState()) { + /* Start timeout to recover from stucked/error create Broadcast operation */ + if (mCreateBroadcastTimeoutEvent != null) { + Log.w(TAG, "CreateBroadcastTimeoutEvent already scheduled"); + } else { + mCreateBroadcastTimeoutEvent = new CreateBroadcastTimeoutEvent(); + mHandler.postDelayed(mCreateBroadcastTimeoutEvent, CREATE_BROADCAST_TIMEOUT_MS); + } + } + mLeAudioBroadcasterNativeInterface.createBroadcast( broadcastSettings.isPublicBroadcast(), broadcastSettings.getBroadcastName(), broadcastCode, publicMetadata == null ? null : publicMetadata.getRawMetadata(), - getBroadcastAudioQualityPerSinkCapabilities(settingsList), - settingsList.stream() + getBroadcastAudioQualityPerSinkCapabilities( + broadcastSettings.getSubgroupSettings()), + broadcastSettings.getSubgroupSettings().stream() .map(s -> s.getContentMetadata().getRawMetadata()) .toArray(byte[][]::new)); } @@ -1280,8 +1303,8 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "startBroadcast"); /* Start timeout to recover from stucked/error start Broadcast operation */ - mDialingOutTimeoutEvent = new DialingOutTimeoutEvent(broadcastId); - mHandler.postDelayed(mDialingOutTimeoutEvent, DIALING_OUT_TIMEOUT_MS); + mCreateBroadcastTimeoutEvent = new CreateBroadcastTimeoutEvent(broadcastId); + mHandler.postDelayed(mCreateBroadcastTimeoutEvent, CREATE_BROADCAST_TIMEOUT_MS); mLeAudioBroadcasterNativeInterface.startBroadcast(broadcastId); } @@ -3181,19 +3204,19 @@ public class LeAudioService extends ProfileService { setActiveDevice(unicastDevice); } - void clearBroadcastTimeoutCallback() { + private void clearCreateBroadcastTimeoutCallback() { if (mHandler == null) { Log.e(TAG, "No callback handler"); return; } /* Timeout callback already cleared */ - if (mDialingOutTimeoutEvent == null) { + if (mCreateBroadcastTimeoutEvent == null) { return; } - mHandler.removeCallbacks(mDialingOutTimeoutEvent); - mDialingOutTimeoutEvent = null; + mHandler.removeCallbacks(mCreateBroadcastTimeoutEvent); + mCreateBroadcastTimeoutEvent = null; } void notifyAudioFrameworkForCodecConfigUpdate( @@ -3669,7 +3692,10 @@ public class LeAudioService extends ProfileService { if (!leaudioUseAudioModeListener()) { mQueuedInCallValue = Optional.empty(); } - startBroadcast(mBroadcastIdDeactivatedForUnicastTransition.get()); + if (!leaudioBigDependsOnAudioState()) { + startBroadcast( + mBroadcastIdDeactivatedForUnicastTransition.get()); + } mBroadcastIdDeactivatedForUnicastTransition = Optional.empty(); } @@ -3729,9 +3755,10 @@ public class LeAudioService extends ProfileService { mBroadcastSessionStats.put(broadcastId, sessionStats); } - // Start sending the actual stream - startBroadcast(broadcastId); - + if (!leaudioBigDependsOnAudioState()) { + // Start sending the actual stream + startBroadcast(broadcastId); + } } else { // TODO: Improve reason reporting or extend the native stack event with reason code Log.e( @@ -3744,7 +3771,9 @@ public class LeAudioService extends ProfileService { if ((mUnicastGroupIdDeactivatedForBroadcastTransition != LE_AUDIO_GROUP_ID_INVALID) && mCreateBroadcastQueue.isEmpty() && (!Objects.equals(device, mActiveBroadcastAudioDevice))) { - clearBroadcastTimeoutCallback(); + if (!leaudioBigDependsOnAudioState()) { + clearCreateBroadcastTimeoutCallback(); + } updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); } @@ -3755,6 +3784,9 @@ public class LeAudioService extends ProfileService { .BROADCAST_AUDIO_SESSION_REPORTED__SESSION_SETUP_STATUS__SETUP_STATUS_CREATE_FAILED); } + if (leaudioBigDependsOnAudioState()) { + clearCreateBroadcastTimeoutCallback(); + } mAwaitingBroadcastCreateResponse = false; // In case if there were additional calls to create broadcast @@ -3883,7 +3915,9 @@ public class LeAudioService extends ProfileService { sessionStats.updateSessionStreamingTime(SystemClock.elapsedRealtime()); } - clearBroadcastTimeoutCallback(); + if (!leaudioBigDependsOnAudioState()) { + clearCreateBroadcastTimeoutCallback(); + } if (previousState == LeAudioStackEvent.BROADCAST_STATE_PAUSED) { if (bassClientService != null) { @@ -5279,45 +5313,64 @@ public class LeAudioService extends ProfileService { return audioFrameworkCalls; } - class DialingOutTimeoutEvent implements Runnable { + private class CreateBroadcastTimeoutEvent implements Runnable { Integer mBroadcastId; - DialingOutTimeoutEvent(Integer broadcastId) { + CreateBroadcastTimeoutEvent() {} + + CreateBroadcastTimeoutEvent(Integer broadcastId) { mBroadcastId = broadcastId; } @Override public void run() { - Log.w(TAG, "Failed to start Broadcast in time: " + mBroadcastId); - - mDialingOutTimeoutEvent = null; + if (leaudioBigDependsOnAudioState()) { + Log.w(TAG, "Failed to start Broadcast in time"); - if (getLeAudioService() == null) { - Log.e(TAG, "DialingOutTimeoutEvent: No LE Audio service"); - return; - } + if (getLeAudioService() == null) { + Log.e(TAG, "CreateBroadcastTimeoutEvent: No LE Audio service"); + return; + } - if (Flags.leaudioBroadcastDestroyAfterTimeout()) { - LeAudioBroadcastSessionStats sessionStats = - mBroadcastSessionStats.get(mBroadcastId); - if (sessionStats != null) { - sessionStats.updateSessionStatus( - BluetoothStatsLog - .BROADCAST_AUDIO_SESSION_REPORTED__SESSION_SETUP_STATUS__SETUP_STATUS_STREAMING_FAILED); - // log once destroyed + if (sLeAudioService.mHandler == null) { + Log.w(TAG, "CreateBroadcastTimeoutEvent: No handler"); + return; } - transitionFromBroadcastToUnicast(); - destroyBroadcast(mBroadcastId); + + mHandler.post(() -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT)); } else { - if (mActiveBroadcastAudioDevice != null) { - updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); + Log.w(TAG, "Failed to start Broadcast in time: " + mBroadcastId); + + mCreateBroadcastTimeoutEvent = null; + + if (getLeAudioService() == null) { + Log.e(TAG, "CreateBroadcastTimeoutEvent: No LE Audio service"); + return; } - mHandler.post(() -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT)); - logBroadcastSessionStatsWithStatus( - mBroadcastId, - BluetoothStatsLog - .BROADCAST_AUDIO_SESSION_REPORTED__SESSION_SETUP_STATUS__SETUP_STATUS_STREAMING_FAILED); + if (Flags.leaudioBroadcastDestroyAfterTimeout()) { + LeAudioBroadcastSessionStats sessionStats = + mBroadcastSessionStats.get(mBroadcastId); + if (sessionStats != null) { + sessionStats.updateSessionStatus( + BluetoothStatsLog + .BROADCAST_AUDIO_SESSION_REPORTED__SESSION_SETUP_STATUS__SETUP_STATUS_STREAMING_FAILED); + // log once destroyed + } + transitionFromBroadcastToUnicast(); + destroyBroadcast(mBroadcastId); + } else { + if (mActiveBroadcastAudioDevice != null) { + updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); + } + + mHandler.post( + () -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT)); + logBroadcastSessionStatsWithStatus( + mBroadcastId, + BluetoothStatsLog + .BROADCAST_AUDIO_SESSION_REPORTED__SESSION_SETUP_STATUS__SETUP_STATUS_STREAMING_FAILED); + } } } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 309c7310d2e..7261d369bf4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -31,8 +31,10 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; +import android.os.IBinder; import android.os.Looper; import android.os.ParcelUuid; +import android.os.RemoteException; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.MediumTest; @@ -96,6 +98,9 @@ public class LeAudioBroadcastServiceTest { @Mock private BassClientService mBassClientService; @Mock private TbsService mTbsService; @Mock private MetricsLogger mMetricsLogger; + @Mock private IBluetoothLeBroadcastCallback mCallbacks; + @Mock private IBinder mBinder; + @Spy private LeAudioObjectsFactory mObjectsFactory = LeAudioObjectsFactory.getInstance(); @Spy private ServiceFactory mServiceFactory = new ServiceFactory(); @@ -139,62 +144,13 @@ public class LeAudioBroadcastServiceTest { private static final List OUTPUT_SELECTABLE_CONFIG_HIGH = List.of(LC3_48KHZ_CONFIG); - private boolean mOnBroadcastStartedCalled = false; - private boolean mOnBroadcastStartFailedCalled = false; - private boolean mOnBroadcastStoppedCalled = false; - private boolean mOnBroadcastStopFailedCalled = false; - private boolean mOnBroadcastUpdatedCalled = false; - private boolean mOnBroadcastUpdateFailedCalled = false; - private int mOnBroadcastStartFailedReason = BluetoothStatusCodes.SUCCESS; - - private final IBluetoothLeBroadcastCallback mCallbacks = - new IBluetoothLeBroadcastCallback.Stub() { - @Override - public void onBroadcastStarted(int reason, int broadcastId) { - mOnBroadcastStartedCalled = true; - } - - @Override - public void onBroadcastStartFailed(int reason) { - mOnBroadcastStartFailedCalled = true; - mOnBroadcastStartFailedReason = reason; - } - - @Override - public void onBroadcastStopped(int reason, int broadcastId) { - mOnBroadcastStoppedCalled = true; - } - - @Override - public void onBroadcastStopFailed(int reason) { - mOnBroadcastStopFailedCalled = true; - } - - @Override - public void onPlaybackStarted(int reason, int broadcastId) {} - - @Override - public void onPlaybackStopped(int reason, int broadcastId) {} - - @Override - public void onBroadcastUpdated(int reason, int broadcastId) { - mOnBroadcastUpdatedCalled = true; - } - - @Override - public void onBroadcastUpdateFailed(int reason, int broadcastId) { - mOnBroadcastUpdateFailedCalled = true; - } - - @Override - public void onBroadcastMetadataChanged( - int broadcastId, BluetoothLeBroadcastMetadata metadata) {} - }; - @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + doReturn(mBinder).when(mCallbacks).asBinder(); + doNothing().when(mBinder).linkToDeath(any(), eq(0)); + // Use spied objects factory doNothing().when(mTmapGattServer).start(anyInt()); doNothing().when(mTmapGattServer).stop(); @@ -306,8 +262,10 @@ public class LeAudioBroadcastServiceTest { create_event.valueBool1 = true; mService.messageFromNative(create_event); - // Verify if broadcast is auto-started on start - verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); + if (!Flags.leaudioBigDependsOnAudioState()) { + // Verify if broadcast is auto-started on start + verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); + } // Notify initial paused state LeAudioStackEvent state_event = @@ -326,8 +284,14 @@ public class LeAudioBroadcastServiceTest { verify(mLeAudioBroadcasterNativeInterface).getBroadcastMetadata(eq(broadcastId)); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); - Assert.assertFalse(mOnBroadcastStartFailedCalled); - Assert.assertTrue(mOnBroadcastStartedCalled); + try { + verify(mCallbacks, times(0)).onBroadcastStartFailed(anyInt()); + verify(mCallbacks, times(1)) + .onBroadcastStarted( + eq(BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST), anyInt()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } void verifyBroadcastStopped(int broadcastId) { @@ -361,8 +325,14 @@ public class LeAudioBroadcastServiceTest { anyLong(), anyLong(), eq(0x3)); // STATS_SESSION_SETUP_STATUS_STREAMING - Assert.assertTrue(mOnBroadcastStoppedCalled); - Assert.assertFalse(mOnBroadcastStopFailedCalled); + try { + verify(mCallbacks, times(1)) + .onBroadcastStopped( + eq(BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST), anyInt()); + verify(mCallbacks, times(0)).onBroadcastStopFailed(anyInt()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } @Test @@ -453,15 +423,19 @@ public class LeAudioBroadcastServiceTest { eq(0L), eq(0x4)); // STATS_SESSION_SETUP_STATUS_CREATED_FAILED - Assert.assertFalse(mOnBroadcastStartedCalled); - Assert.assertTrue(mOnBroadcastStartFailedCalled); + try { + verify(mCallbacks, times(0)).onBroadcastStarted(anyInt(), anyInt()); + verify(mCallbacks, times(1)) + .onBroadcastStartFailed(eq(BluetoothStatusCodes.ERROR_UNKNOWN)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } @Test public void testCreateBroadcastTimeout() { mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_DESTROY_AFTER_TIMEOUT); - int broadcastId = 243; byte[] code = {0x00, 0x01, 0x00, 0x02}; synchronized (mService.mBroadcastCallbacks) { @@ -477,59 +451,77 @@ public class LeAudioBroadcastServiceTest { BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1); mService.createBroadcast(settings); - // Test data with only one subgroup - int[] expectedQualityArray = {settings.getSubgroupSettings().get(0).getPreferredQuality()}; - byte[][] expectedDataArray = { - settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata() - }; - - verify(mLeAudioBroadcasterNativeInterface) - .createBroadcast( - eq(true), - eq(TEST_BROADCAST_NAME), - eq(code), - eq(settings.getPublicBroadcastMetadata().getRawMetadata()), - eq(expectedQualityArray), - eq(expectedDataArray)); - - // Check if broadcast is started automatically when created - LeAudioStackEvent create_event = - new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED); - create_event.valueInt1 = broadcastId; - create_event.valueBool1 = true; - mService.messageFromNative(create_event); - - // Verify if broadcast is auto-started on start - verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); - TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); - - Assert.assertTrue(mOnBroadcastStartedCalled); - - // Notify initial paused state - LeAudioStackEvent state_event = - new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); - state_event.valueInt1 = broadcastId; - state_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_PAUSED; - mService.messageFromNative(state_event); + if (Flags.leaudioBigDependsOnAudioState()) { + try { + verify(mCallbacks, timeout(CREATE_BROADCAST_TIMEOUT_MS).times(1)) + .onBroadcastStartFailed(eq(BluetoothStatusCodes.ERROR_TIMEOUT)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } else { + int broadcastId = 243; + // Test data with only one subgroup + int[] expectedQualityArray = { + settings.getSubgroupSettings().get(0).getPreferredQuality() + }; + byte[][] expectedDataArray = { + settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata() + }; - // Check if broadcast is destroyed after timeout - verify(mLeAudioBroadcasterNativeInterface, timeout(CREATE_BROADCAST_TIMEOUT_MS)) - .destroyBroadcast(eq(broadcastId)); + verify(mLeAudioBroadcasterNativeInterface) + .createBroadcast( + eq(true), + eq(TEST_BROADCAST_NAME), + eq(code), + eq(settings.getPublicBroadcastMetadata().getRawMetadata()), + eq(expectedQualityArray), + eq(expectedDataArray)); + + // Check if broadcast is started automatically when created + LeAudioStackEvent create_event = + new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED); + create_event.valueInt1 = broadcastId; + create_event.valueBool1 = true; + mService.messageFromNative(create_event); + + // Verify if broadcast is auto-started on start + verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); - state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED); - state_event.valueInt1 = broadcastId; - mService.messageFromNative(state_event); + try { + verify(mCallbacks, times(1)) + .onBroadcastStarted( + eq(BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST), anyInt()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } - // Verify broadcast audio session is logged when session failed to stream - verify(mMetricsLogger) - .logLeAudioBroadcastAudioSession( - eq(broadcastId), - eq(new int[] {0x2}), // STATS_SESSION_AUDIO_QUALITY_HIGH - eq(0), - anyLong(), - anyLong(), - eq(0L), - eq(0x5)); // STATS_SESSION_SETUP_STATUS_STREAMING_FAILED + // Notify initial paused state + LeAudioStackEvent state_event = + new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); + state_event.valueInt1 = broadcastId; + state_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_PAUSED; + mService.messageFromNative(state_event); + + // Check if broadcast is destroyed after timeout + verify(mLeAudioBroadcasterNativeInterface, timeout(CREATE_BROADCAST_TIMEOUT_MS)) + .destroyBroadcast(eq(broadcastId)); + + state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED); + state_event.valueInt1 = broadcastId; + mService.messageFromNative(state_event); + + // Verify broadcast audio session is logged when session failed to stream + verify(mMetricsLogger) + .logLeAudioBroadcastAudioSession( + eq(broadcastId), + eq(new int[] {0x2}), // STATS_SESSION_AUDIO_QUALITY_HIGH + eq(0), + anyLong(), + anyLong(), + eq(0L), + eq(0x5)); // STATS_SESSION_SETUP_STATUS_STREAMING_FAILED + } } @Test @@ -649,8 +641,14 @@ public class LeAudioBroadcastServiceTest { TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); - Assert.assertFalse(mOnBroadcastStoppedCalled); - Assert.assertTrue(mOnBroadcastStopFailedCalled); + try { + verify(mCallbacks, times(0)).onBroadcastStopped(anyInt(), anyInt()); + verify(mCallbacks, times(1)) + .onBroadcastStopFailed( + eq(BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_BROADCAST_ID)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } // Update metadata for non-existing broadcast BluetoothLeAudioContentMetadata.Builder meta_builder = @@ -662,8 +660,12 @@ public class LeAudioBroadcastServiceTest { TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); - Assert.assertFalse(mOnBroadcastUpdatedCalled); - Assert.assertTrue(mOnBroadcastUpdateFailedCalled); + try { + verify(mCallbacks, times(0)).onBroadcastUpdated(anyInt(), anyInt()); + verify(mCallbacks, times(1)).onBroadcastUpdateFailed(anyInt(), anyInt()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } private BluetoothLeBroadcastSubgroup createBroadcastSubgroup() { @@ -977,19 +979,21 @@ public class LeAudioBroadcastServiceTest { TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); verifyBroadcastStarted(broadcastId, settings); - mOnBroadcastStartedCalled = false; - mOnBroadcastStartFailedCalled = false; + Mockito.clearInvocations(mCallbacks); // verify creating another broadcast will fail mService.createBroadcast(settings); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); - Assert.assertFalse(mOnBroadcastStartedCalled); - Assert.assertTrue(mOnBroadcastStartFailedCalled); - Assert.assertEquals( - BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES, - mOnBroadcastStartFailedReason); + try { + verify(mCallbacks, times(0)).onBroadcastStarted(anyInt(), anyInt()); + verify(mCallbacks, times(1)) + .onBroadcastStartFailed( + eq(BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } private void prepareHandoverStreamingBroadcast(int groupId, int broadcastId, byte[] code) { @@ -1083,9 +1087,6 @@ public class LeAudioBroadcastServiceTest { create_event.valueBool1 = true; mService.messageFromNative(create_event); - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); - /* Switch to active streaming */ create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); create_event.device = mBroadcastDevice; @@ -1108,6 +1109,8 @@ public class LeAudioBroadcastServiceTest { /* Imitate setting device in call */ mService.setInCall(true); + Assert.assertTrue(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + /* Check if broadcast is paused by InCall handling */ verify(mLeAudioBroadcasterNativeInterface).pauseBroadcast(eq(broadcastId)); @@ -1155,8 +1158,8 @@ public class LeAudioBroadcastServiceTest { .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + /* Verify if broadcast triggers transition */ + Assert.assertFalse(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); } @Test @@ -1172,6 +1175,8 @@ public class LeAudioBroadcastServiceTest { /* Imitate setting device in call */ mService.handleAudioModeChange(AudioManager.MODE_IN_CALL); + Assert.assertTrue(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + /* Check if broadcast is paused by AudioMode handling */ verify(mLeAudioBroadcasterNativeInterface).pauseBroadcast(eq(broadcastId)); @@ -1227,8 +1232,13 @@ public class LeAudioBroadcastServiceTest { .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + if (Flags.leaudioBigDependsOnAudioState()) { + /* Verify if broadcast triggers transition */ + Assert.assertFalse(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + } else { + /* Verify if broadcast is auto-started on start */ + verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + } } @Test @@ -1239,8 +1249,10 @@ public class LeAudioBroadcastServiceTest { prepareHandoverStreamingBroadcast(groupId, broadcastId, code); - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); + if (!Flags.leaudioBigDependsOnAudioState()) { + /* Verify if broadcast is auto-started on start */ + verify(mLeAudioBroadcasterNativeInterface).startBroadcast(eq(broadcastId)); + } /* Imitate group change request by Bluetooth Sink HAL resume request */ LeAudioStackEvent create_event = @@ -1249,6 +1261,8 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.STATUS_LOCAL_STREAM_REQUESTED; mService.messageFromNative(create_event); + Assert.assertTrue(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + /* Check if broadcast is paused triggered by group change request */ verify(mLeAudioBroadcasterNativeInterface).pauseBroadcast(eq(broadcastId)); @@ -1297,8 +1311,13 @@ public class LeAudioBroadcastServiceTest { .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + if (Flags.leaudioBigDependsOnAudioState()) { + /* Verify if broadcast triggers transition */ + Assert.assertFalse(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + } else { + /* Verify if broadcast is auto-started on start */ + verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + } } @Test @@ -1321,6 +1340,8 @@ public class LeAudioBroadcastServiceTest { /* Imitate setting device in call */ mService.setInCall(true); + Assert.assertTrue(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + /* Broadcast already paused, not call pause again by InCall handling */ verify(mLeAudioBroadcasterNativeInterface, never()).pauseBroadcast(eq(broadcastId)); @@ -1362,8 +1383,8 @@ public class LeAudioBroadcastServiceTest { .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + /* Verify if broadcast triggers transition */ + Assert.assertFalse(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); } @Test @@ -1386,6 +1407,8 @@ public class LeAudioBroadcastServiceTest { /* Imitate setting device in call */ mService.handleAudioModeChange(AudioManager.MODE_IN_CALL); + Assert.assertTrue(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + /* Broadcast already paused, not call pause again by AudioMode handling */ verify(mLeAudioBroadcasterNativeInterface, never()).pauseBroadcast(eq(broadcastId)); @@ -1435,8 +1458,8 @@ public class LeAudioBroadcastServiceTest { .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + /* Verify if broadcast triggers transition */ + Assert.assertFalse(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); } @Test @@ -1462,6 +1485,8 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.STATUS_LOCAL_STREAM_REQUESTED; mService.messageFromNative(create_event); + Assert.assertTrue(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); + /* Broadcast already paused, not call pause again by group change request */ verify(mLeAudioBroadcasterNativeInterface, never()).pauseBroadcast(eq(broadcastId)); @@ -1503,9 +1528,8 @@ public class LeAudioBroadcastServiceTest { verify(mAudioManager) .handleBluetoothActiveDeviceChanged( eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); - - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); + /* Verify if broadcast triggers transition */ + Assert.assertFalse(mService.mBroadcastIdDeactivatedForUnicastTransition.isPresent()); } @Test diff --git a/system/bta/le_audio/broadcaster/broadcaster.cc b/system/bta/le_audio/broadcaster/broadcaster.cc index a7b05339b1d..251091a8b48 100644 --- a/system/bta/le_audio/broadcaster/broadcaster.cc +++ b/system/bta/le_audio/broadcaster/broadcaster.cc @@ -913,13 +913,16 @@ public: is_iso_running_ = is_active; log::info("is_iso_running: {}", is_iso_running_); if (!is_iso_running_) { - if (queued_start_broadcast_request_) { - auto broadcast_id = *queued_start_broadcast_request_; - queued_start_broadcast_request_ = std::nullopt; + if (!com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { + if (queued_start_broadcast_request_) { + auto broadcast_id = *queued_start_broadcast_request_; + queued_start_broadcast_request_ = std::nullopt; - log::info("Start queued broadcast."); - StartAudioBroadcast(broadcast_id); + log::info("Start queued broadcast."); + StartAudioBroadcast(broadcast_id); + } } + if (queued_create_broadcast_request_) { auto broadcast_msg = std::move(*queued_create_broadcast_request_); queued_create_broadcast_request_ = std::nullopt; diff --git a/system/bta/le_audio/broadcaster/broadcaster_test.cc b/system/bta/le_audio/broadcaster/broadcaster_test.cc index 1145b93a4a5..63b708039ed 100644 --- a/system/bta/le_audio/broadcaster/broadcaster_test.cc +++ b/system/bta/le_audio/broadcaster/broadcaster_test.cc @@ -533,8 +533,19 @@ TEST_F(BroadcasterTest, CreateAudioBroadcastMultiGroups) { TEST_F(BroadcasterTest, SuspendAudioBroadcast) { EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) .Times(1); + LeAudioSourceAudioHalClient::Callbacks* audio_receiver; + EXPECT_CALL(*mock_audio_source_, Start) + .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))) + .WillRepeatedly(Return(false)); auto broadcast_id = InstantiateBroadcast(); - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); + + if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { + ASSERT_NE(audio_receiver, nullptr); + audio_receiver->OnAudioResume(); + } else { + LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); + } + Mock::VerifyAndClearExpectations(mock_codec_manager_); EXPECT_CALL(mock_broadcaster_callbacks_, @@ -559,7 +570,9 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) { EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) .Times(1); + auto broadcast_id = InstantiateBroadcast(); + ASSERT_NE(audio_receiver, nullptr); Mock::VerifyAndClearExpectations(mock_codec_manager_); EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) @@ -575,8 +588,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) { ASSERT_TRUE(big_terminate_timer_->cb == nullptr); ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); - ASSERT_NE(audio_receiver, nullptr); + audio_receiver->OnAudioResume(); // NOTICE: This is really an implementation specific part, we fake the BIG // config as the mocked state machine does not even call the @@ -609,6 +621,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) { .Times(1); auto broadcast_id = InstantiateBroadcast(media_metadata, default_code, {bluetooth::le_audio::QUALITY_HIGH}); + ASSERT_NE(audio_receiver, nullptr); Mock::VerifyAndClearExpectations(mock_codec_manager_); LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id); @@ -626,8 +639,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) { EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, false)) .Times(0); - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); - ASSERT_NE(audio_receiver, nullptr); + audio_receiver->OnAudioResume(); // NOTICE: This is really an implementation specific part, we fake the BIG // config as the mocked state machine does not even call the @@ -651,8 +663,18 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) { TEST_F(BroadcasterTest, StopAudioBroadcast) { EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) .Times(1); + LeAudioSourceAudioHalClient::Callbacks* audio_receiver; + EXPECT_CALL(*mock_audio_source_, Start) + .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))) + .WillRepeatedly(Return(false)); auto broadcast_id = InstantiateBroadcast(); - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); + + if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) { + ASSERT_NE(audio_receiver, nullptr); + audio_receiver->OnAudioResume(); + } else { + LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); + } // NOTICE: This is really an implementation specific part, we fake the BIG // config as the mocked state machine does not even call the @@ -712,7 +734,6 @@ TEST_F(BroadcasterTest, DestroyAudioBroadcast) { LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id); EXPECT_CALL(*mock_audio_source_, Start).Times(0); - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); EXPECT_CALL(*mock_audio_source_, Stop).Times(0); LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id); @@ -846,8 +867,8 @@ TEST_F(BroadcasterTest, UpdateMetadataFromAudioTrackMetadata) { ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA, media_ccid); auto broadcast_id = InstantiateBroadcast(); - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); ASSERT_NE(audio_receiver, nullptr); + audio_receiver->OnAudioResume(); auto sm = MockBroadcastStateMachine::GetLastInstance(); std::vector ccid_list; @@ -1204,6 +1225,7 @@ TEST_F(BroadcasterTest, AudioActiveState) { .WillRepeatedly(Return(false)); auto broadcast_id = InstantiateBroadcast(); + ASSERT_NE(audio_receiver, nullptr); auto sm = MockBroadcastStateMachine::GetLastInstance(); pb_announcement = sm->GetPublicBroadcastAnnouncement(); auto created_public_meta = types::LeAudioLtvMap(pb_announcement.metadata).RawPacket(); @@ -1218,9 +1240,6 @@ TEST_F(BroadcasterTest, AudioActiveState) { }); ON_CALL(*sm, GetPublicBroadcastAnnouncement()).WillByDefault(ReturnRef(pb_announcement)); - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); - ASSERT_NE(audio_receiver, nullptr); - // Update to true Audio Active State while audio resumed EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement); audio_receiver->OnAudioResume(); @@ -1278,32 +1297,12 @@ TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundFromTheBeginnin auto broadcast_id = InstantiateBroadcast(); EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING)) - .Times(1); + .Times(0); // Timers not started ASSERT_TRUE(big_terminate_timer_->cb == nullptr); ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); - - // Start Broadcast - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); - // Timers started - ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); - ASSERT_TRUE(big_terminate_timer_->cb != nullptr); - ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); + ASSERT_EQ(0, get_func_call_count("alarm_set_on_mloop")); ASSERT_NE(audio_receiver, nullptr); - - // BIG termination timer execution, state machine go to CONFIGURED state so BIG terminated - EXPECT_CALL(mock_broadcaster_callbacks_, - OnBroadcastStateChanged(broadcast_id, BroadcastState::CONFIGURED)) - .Times(1); - // Imitate execution of BIG termination timer - big_terminate_timer_->cb(big_terminate_timer_->data); - - // Broadcast stop timer execution, state machine go to STOPPED state - EXPECT_CALL(mock_broadcaster_callbacks_, - OnBroadcastStateChanged(broadcast_id, BroadcastState::STOPPED)) - .Times(1); - // Imitate execution of BIG termination timer - broadcast_stop_timer_->cb(broadcast_stop_timer_->data); } TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundAfterSuspend) { @@ -1326,24 +1325,11 @@ TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundAfterSuspend) { ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); // Start Broadcast - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); - // Timers started - ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); - ASSERT_TRUE(big_terminate_timer_->cb != nullptr); - ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); - ASSERT_NE(audio_receiver, nullptr); - - // First onAudioResume when BIG already created, not cause any state change - EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastStateChanged(broadcast_id, _)).Times(0); audio_receiver->OnAudioResume(); - // Timers cancelled - ASSERT_EQ(2, get_func_call_count("alarm_cancel")); - ASSERT_TRUE(big_terminate_timer_->cb == nullptr); - ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); // OnAudioSuspend cause starting the BIG termination timer audio_receiver->OnAudioSuspend(); - ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop")); + ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); ASSERT_TRUE(big_terminate_timer_->cb != nullptr); ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); @@ -1357,7 +1343,7 @@ TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundAfterSuspend) { // OnAudioSuspend cause starting the BIG termination timer audio_receiver->OnAudioSuspend(); - ASSERT_EQ(6, get_func_call_count("alarm_set_on_mloop")); + ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop")); ASSERT_TRUE(big_terminate_timer_->cb != nullptr); ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); @@ -1396,24 +1382,11 @@ TEST_F(BroadcasterTest, BigCreationTerminationDependsOnAudioResumeSuspend) { ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); // Start Broadcast - LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id); - // Timers started - ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); - ASSERT_TRUE(big_terminate_timer_->cb != nullptr); - ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); - ASSERT_NE(audio_receiver, nullptr); - - // First onAudioResume when BIG already created, not cause any state change - EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastStateChanged(broadcast_id, _)).Times(0); audio_receiver->OnAudioResume(); - // Timers cancelled - ASSERT_EQ(2, get_func_call_count("alarm_cancel")); - ASSERT_TRUE(big_terminate_timer_->cb == nullptr); - ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr); // OnAudioSuspend cause starting the BIG termination timer audio_receiver->OnAudioSuspend(); - ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop")); + ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); ASSERT_TRUE(big_terminate_timer_->cb != nullptr); ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); @@ -1427,7 +1400,7 @@ TEST_F(BroadcasterTest, BigCreationTerminationDependsOnAudioResumeSuspend) { // OnAudioSuspend cause starting the BIG termination timer audio_receiver->OnAudioSuspend(); - ASSERT_EQ(6, get_func_call_count("alarm_set_on_mloop")); + ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop")); ASSERT_TRUE(big_terminate_timer_->cb != nullptr); ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); diff --git a/system/bta/le_audio/broadcaster/mock_state_machine.h b/system/bta/le_audio/broadcaster/mock_state_machine.h index ebafbed3985..6b35b11532e 100644 --- a/system/bta/le_audio/broadcaster/mock_state_machine.h +++ b/system/bta/le_audio/broadcaster/mock_state_machine.h @@ -30,6 +30,7 @@ public: advertising_sid_ = ++instance_counter_; ON_CALL(*this, Initialize).WillByDefault([this]() { + SetState(State::CONFIGURED); this->cb->OnStateMachineCreateStatus(this->cfg.broadcast_id, result_); return result_; }); -- GitLab From 6ee1a2f85b3bd6ae65e1b46c1f08f1641477f8ba Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Wed, 23 Oct 2024 16:53:23 +0000 Subject: [PATCH 420/875] CS: Retry when config creation fails Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 374212678 Test: m com.android.btservice Change-Id: I3bd7aabe41f87aed2f57bfabe18370a57a61c1c3 --- system/gd/hci/distance_measurement_manager.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index ec56490d420..e0039153484 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -70,6 +70,7 @@ static constexpr uint16_t kRangingCounterMask = 0x0FFF; static constexpr uint8_t kInvalidConfigId = 0xFF; static constexpr uint16_t kDefaultIntervalMs = 1000; // 1s static constexpr uint8_t kPreferredPeerAntennaValue = 0x01; // Use first ordered antenna element +static constexpr uint8_t kMaxRetryCounterForCreateConfig = 0x03; struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { struct CsProcedureData { @@ -166,6 +167,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { bool ras_connected = false; bool setup_complete = false; bool config_set = false; + uint8_t retry_counter_for_create_config = 0; uint16_t n_procedure_count = 0; CsMainModeType main_mode_type = CsMainModeType::MODE_2; CsSubModeType sub_mode_type = CsSubModeType::UNUSED; @@ -759,6 +761,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { req_it->second.setup_complete = true; log::info("Setup phase complete, connection_handle: {}, address: {}", connection_handle, cs_requester_trackers_[connection_handle].address); + req_it->second.retry_counter_for_create_config = 0; send_le_cs_create_config(connection_handle, cs_requester_trackers_[connection_handle].config_id); } @@ -820,7 +823,20 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (event_view.GetStatus() != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(event_view.GetStatus()); log::warn("Received LeCsConfigCompleteView with error code {}", error_code); - handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); + // The Create Config LL packet may arrive before the remote side has finished setting default + // settings, which will result in create config failure. Retry to ensure the remote side has + // completed its setup. + if (cs_requester_trackers_.find(connection_handle) != cs_requester_trackers_.end() && + cs_requester_trackers_[connection_handle].retry_counter_for_create_config < + kMaxRetryCounterForCreateConfig) { + cs_requester_trackers_[connection_handle].retry_counter_for_create_config++; + log::info("send_le_cs_create_config, retry counter {}", + cs_requester_trackers_[connection_handle].retry_counter_for_create_config); + send_le_cs_create_config(connection_handle, + cs_requester_trackers_[connection_handle].config_id); + } else { + handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); + } return; } uint8_t config_id = event_view.GetConfigId(); -- GitLab From 2b3c47056b7a605d29225388674f35d0a2ab11d2 Mon Sep 17 00:00:00 2001 From: "Pechetty Sravani (xWF)" Date: Thu, 24 Oct 2024 04:54:27 +0000 Subject: [PATCH 421/875] Revert "Make connection_manager dumpsys more concise" Revert submission 3315276 Reason for revert: Reverted changes: /q/submissionid:3315276 Change-Id: I256bddcca63658c78f24ba1b057ef20b26a76e63 --- .../stack/connection_manager/connection_manager.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/system/stack/connection_manager/connection_manager.cc b/system/stack/connection_manager/connection_manager.cc index c29ac5d4031..96278a91064 100644 --- a/system/stack/connection_manager/connection_manager.cc +++ b/system/stack/connection_manager/connection_manager.cc @@ -581,10 +581,7 @@ void dump(int fd) { dprintf(fd, "\tdevices attempting connection: %d", (int)bgconn_dev.size()); for (const auto& entry : bgconn_dev) { // TODO: confirm whether we need to replace this - dprintf(fd, "\n\t * %s:\t\tin_accept_list: %s\t cap_targeted_announcements: %s", - ADDRESS_TO_LOGGABLE_CSTR(entry.first), - entry.second.is_in_accept_list ? "true" : "false", - entry.second.doing_targeted_announcements_conn.empty() ? "false" : "true"); + dprintf(fd, "\n\t * %s: ", ADDRESS_TO_LOGGABLE_CSTR(entry.first)); if (!entry.second.doing_direct_conn.empty()) { dprintf(fd, "\n\t\tapps doing direct connect: "); @@ -599,6 +596,14 @@ void dump(int fd) { dprintf(fd, "%d, ", id); } } + if (!entry.second.doing_targeted_announcements_conn.empty()) { + dprintf(fd, "\n\t\tapps doing cap announcement connect: "); + for (const auto& id : entry.second.doing_targeted_announcements_conn) { + dprintf(fd, "%d, ", id); + } + } + dprintf(fd, "\n\t\t is in the allow list: %s", + entry.second.is_in_accept_list ? "true" : "false"); } dprintf(fd, "\n"); } -- GitLab From 68dd1469673cea50378c089f99b3cca21ab62d71 Mon Sep 17 00:00:00 2001 From: "Pechetty Sravani (xWF)" Date: Thu, 24 Oct 2024 04:54:27 +0000 Subject: [PATCH 422/875] Revert "Make it obvious that connection_manager is separate from..." Revert submission 3315276 Reason for revert: Reverted changes: /q/submissionid:3315276 Change-Id: I45ab232a73179ec379aa658ec0b2d2466b0a8d20 --- system/bta/Android.bp | 1 - system/bta/dm/bta_dm_act.cc | 2 +- system/btif/src/bluetooth.cc | 2 +- system/stack/Android.bp | 15 ++++++--------- system/stack/BUILD.gn | 2 +- system/stack/acl/ble_acl.cc | 2 +- system/stack/btm/btm_devctl.cc | 2 +- .../connection_manager.cc | 0 .../connection_manager.h | 0 system/stack/gatt/gatt_api.cc | 2 +- system/stack/gatt/gatt_main.cc | 2 +- system/stack/gatt/gatt_utils.cc | 2 +- system/stack/l2cap/l2c_ble.cc | 2 +- system/stack/test/gatt/mock_gatt_utils_ref.cc | 2 +- ...er_test.cc => gatt_connection_manager_test.cc} | 3 +-- system/test/Android.bp | 7 ------- system/test/headless/bt_stack_info.cc | 2 +- ...r.cc => mock_stack_gatt_connection_manager.cc} | 8 +------- 18 files changed, 19 insertions(+), 37 deletions(-) rename system/stack/{connection_manager => gatt}/connection_manager.cc (100%) rename system/stack/{connection_manager => gatt}/connection_manager.h (100%) rename system/stack/test/{connection_manager_test.cc => gatt_connection_manager_test.cc} (99%) rename system/test/mock/{mock_stack_connection_manager.cc => mock_stack_gatt_connection_manager.cc} (92%) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 64c44d250cf..235246605f2 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -260,7 +260,6 @@ cc_test { ":TestMockStackAvdt", ":TestMockStackAvrc", ":TestMockStackBtm", - ":TestMockStackConnMgr", ":TestMockStackGap", ":TestMockStackGatt", ":TestMockStackHid", diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 792aa44b6e3..1d1d5c589de 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -52,7 +52,7 @@ #include "main/shim/entry.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index a5a2e54f203..f246ca1be87 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -100,7 +100,7 @@ #include "osi/include/wakelock.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sco_hfp_hal.h" -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "stack/include/a2dp_api.h" #include "stack/include/avdt_api.h" #include "stack/include/btm_client_interface.h" diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 1161cae7ca5..5fec9d2cee2 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -275,11 +275,11 @@ cc_library_static { "btm/security_event_parser.cc", "btu/btu_event.cc", "btu/btu_hcif.cc", - "connection_manager/connection_manager.cc", "eatt/eatt.cc", "gap/gap_ble.cc", "gap/gap_conn.cc", "gatt/att_protocol.cc", + "gatt/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", @@ -540,7 +540,6 @@ cc_fuzz { ":TestMockStackAcl", ":TestMockStackArbiter", ":TestMockStackBtm", - ":TestMockStackConnMgr", ":TestMockStackHcic", ":TestMockStackL2cap", ":TestMockStackMetrics", @@ -1068,7 +1067,7 @@ cc_test { // Bluetooth stack connection multiplexing cc_test { - name: "net_test_conn_multiplexing", + name: "net_test_gatt_conn_multiplexing", defaults: [ "fluoride_defaults", "mts_defaults", @@ -1087,9 +1086,9 @@ cc_test { srcs: [ ":TestCommonMainHandler", ":TestMockStackBtmInterface", - "connection_manager/connection_manager.cc", + "gatt/connection_manager.cc", "test/common/mock_btm_api_layer.cc", - "test/connection_manager_test.cc", + "test/gatt_connection_manager_test.cc", ], shared_libs: [ "libcutils", @@ -1653,7 +1652,6 @@ cc_test { ":TestMockMainShimEntry", ":TestMockRustFfi", ":TestMockStackBtu", - ":TestMockStackConnMgr", ":TestMockStackGap", ":TestMockStackGatt", ":TestMockStackHcic", @@ -1974,9 +1972,9 @@ cc_test { ":TestMockStackSmp", "ais/ais_ble.cc", "arbiter/acl_arbiter.cc", - "connection_manager/connection_manager.cc", "eatt/eatt.cc", "gatt/att_protocol.cc", + "gatt/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", @@ -2069,7 +2067,7 @@ cc_test { ":TestMockMainShimEntry", ":TestMockStackAcl", ":TestMockStackBtm", - ":TestMockStackConnMgr", + ":TestMockStackGatt", ":TestMockStackHcic", ":TestMockStackSdp", ":TestMockStackSmp", @@ -2166,7 +2164,6 @@ cc_test { ":TestMockRustFfi", ":TestMockStackBtm", ":TestMockStackBtu", - ":TestMockStackConnMgr", ":TestMockStackGatt", ":TestMockStackHcic", ":TestMockStackL2cap", diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn index 559aa1f366c..c2b87b44a55 100644 --- a/system/stack/BUILD.gn +++ b/system/stack/BUILD.gn @@ -125,7 +125,7 @@ source_set("stack") { "gap/gap_ble.cc", "gap/gap_conn.cc", "gatt/att_protocol.cc", - "connection_manager/connection_manager.cc", + "gatt/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index 0606716f757..1f5d5b580c3 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -25,7 +25,7 @@ #include "stack/btm/btm_dev.h" #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/btm_ble_addr.h" #include "stack/include/btm_ble_privacy.h" diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc index d22fba73c77..86f4af00e4b 100644 --- a/system/stack/btm/btm_devctl.cc +++ b/system/stack/btm/btm_devctl.cc @@ -38,7 +38,7 @@ #include "main/shim/entry.h" #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/acl_api_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/connection_manager/connection_manager.cc b/system/stack/gatt/connection_manager.cc similarity index 100% rename from system/stack/connection_manager/connection_manager.cc rename to system/stack/gatt/connection_manager.cc diff --git a/system/stack/connection_manager/connection_manager.h b/system/stack/gatt/connection_manager.h similarity index 100% rename from system/stack/connection_manager/connection_manager.h rename to system/stack/gatt/connection_manager.h diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index 7ed0fe05160..d9d7f051d95 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -37,7 +37,7 @@ #include "osi/include/allocator.h" #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "stack/gatt/gatt_int.h" #include "stack/include/ais_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index f5591d21948..bc559a5715c 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -28,6 +28,7 @@ #include "btif/include/btif_dm.h" #include "btif/include/btif_storage.h" #include "btif/include/stack_manager_t.h" +#include "connection_manager.h" #include "device/include/interop.h" #include "internal_include/bt_target.h" #include "internal_include/stack_config.h" @@ -37,7 +38,6 @@ #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" -#include "stack/connection_manager/connection_manager.h" #include "stack/eatt/eatt.h" #include "stack/gatt/gatt_int.h" #include "stack/include/acl_api.h" diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index d159bbd794a..72083acb500 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -38,8 +38,8 @@ #include "osi/include/properties.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" -#include "stack/connection_manager/connection_manager.h" #include "stack/eatt/eatt.h" +#include "stack/gatt/connection_manager.h" #include "stack/gatt/gatt_int.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_psm_types.h" diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index fe22262b89a..a00e0d17f46 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -44,7 +44,7 @@ #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" #include "stack/btm/btm_sec_int_types.h" -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc index 2f392b3e90a..f79db0ac3d8 100644 --- a/system/stack/test/gatt/mock_gatt_utils_ref.cc +++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc @@ -22,7 +22,7 @@ #pragma GCC diagnostic ignored "-Wmissing-prototypes" #pragma GCC diagnostic ignored "-Wunused-parameter" -/** stack/connection_manager/connection_manager.cc */ +/** stack/gatt/connection_manager.cc */ namespace connection_manager { bool background_connect_remove(uint8_t app_id, const RawAddress& address) { return false; } bool direct_connect_remove(uint8_t app_id, const RawAddress& address, bool connection_timeout) { diff --git a/system/stack/test/connection_manager_test.cc b/system/stack/test/gatt_connection_manager_test.cc similarity index 99% rename from system/stack/test/connection_manager_test.cc rename to system/stack/test/gatt_connection_manager_test.cc index cbb7b3ff35d..afe3fcba4e8 100644 --- a/system/stack/test/connection_manager_test.cc +++ b/system/stack/test/gatt_connection_manager_test.cc @@ -1,5 +1,3 @@ -#include "stack/connection_manager/connection_manager.h" - #include #include #include @@ -13,6 +11,7 @@ #include "osi/test/alarm_mock.h" #include "security_device_record.h" #include "stack/btm/neighbor_inquiry.h" +#include "stack/gatt/connection_manager.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/test/Android.bp b/system/test/Android.bp index d4a1a767eb8..a78ed4e8ef8 100644 --- a/system/test/Android.bp +++ b/system/test/Android.bp @@ -483,13 +483,6 @@ filegroup { ], } -filegroup { - name: "TestMockStackConnMgr", - srcs: [ - "mock/mock_stack_connection_manager.cc", - ], -} - filegroup { name: "TestMockStackEatt", srcs: [ diff --git a/system/test/headless/bt_stack_info.cc b/system/test/headless/bt_stack_info.cc index 300dbf62b78..ad00ba5c6b5 100644 --- a/system/test/headless/bt_stack_info.cc +++ b/system/test/headless/bt_stack_info.cc @@ -21,7 +21,7 @@ #include "btif/include/btif_common.h" // do_in_jni_thread #include "btif/include/btif_hh.h" // DumpsysHid #include "main/shim/dumpsys.h" -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "stack/include/main_thread.h" #include "stack/include/pan_api.h" // PAN_Dumpsys #include "test/headless/log.h" diff --git a/system/test/mock/mock_stack_connection_manager.cc b/system/test/mock/mock_stack_gatt_connection_manager.cc similarity index 92% rename from system/test/mock/mock_stack_connection_manager.cc rename to system/test/mock/mock_stack_gatt_connection_manager.cc index 97cd1608548..f0f33dddb5e 100644 --- a/system/test/mock/mock_stack_connection_manager.cc +++ b/system/test/mock/mock_stack_gatt_connection_manager.cc @@ -21,18 +21,12 @@ #include -#include "stack/connection_manager/connection_manager.h" +#include "stack/gatt/connection_manager.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" using namespace connection_manager; -bool connection_manager::background_connect_targeted_announcement_add( - tAPP_ID /* app_id */, const RawAddress& /* address */) { - inc_func_call_count(__func__); - return false; -} - bool connection_manager::background_connect_add(uint8_t /* app_id */, const RawAddress& /* address */) { inc_func_call_count(__func__); -- GitLab From a0fbb0ea65f4cbad19dcb5b6c6cb4406867f8efd Mon Sep 17 00:00:00 2001 From: Bao Do Date: Thu, 24 Oct 2024 14:07:08 +0800 Subject: [PATCH 423/875] Remove lock from FetchAudioProvider. When binderDiedCallbackAidl is called, it create a new clients and do the fetching works. This new client is completly independent from the old client, request still can be sent to the old client. By removing lock, we prevent BT crash when binderDiedCallbackAidl is called multiple times, resulting in the lock being destroyed. Bug: 375051151 Test: mmm packages/modules/Bluetooth Flag: EXEMPT trivial change Change-Id: Ie7cc2ba6c2fd9a4c94933677acd5e518b4ec5892 --- system/audio_hal_interface/aidl/client_interface_aidl.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.cc b/system/audio_hal_interface/aidl/client_interface_aidl.cc index 87e29cdab99..e8b143fb5d7 100644 --- a/system/audio_hal_interface/aidl/client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/client_interface_aidl.cc @@ -135,8 +135,6 @@ void BluetoothAudioClientInterface::FetchAudioProvider() { if (provider_ != nullptr) { log::warn("refetch"); } - // Prevent other access to the AIDL if currently fetching new service - std::lock_guard guard(internal_mutex_); // Retry if audioserver restarts in the middle of fetching. // When audioserver restarts, IBluetoothAudioProviderFactory service is also // re-registered, so we need to re-fetch the service. -- GitLab From 028c2458f8263fdcc95d35f570a39057979efe29 Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Mon, 21 Oct 2024 13:11:16 +0000 Subject: [PATCH 424/875] Bass: Handle sync info request in all cases While sink ask for sync info request when BASS is not synchronized to the broadcaster, first synchronized it and then send PAST. Remove paused sink when receiver is active or requesting for sync info. StopBigMonitoring when all receivers are active and no pending paused sinks. Do not monitor BIG if sink is active or requesting for sync info. While resume receivers source synchronization, do not modify source, if PA is synced or requested. Bug: 372522289 Bug: 366294688 Bug: 363168099 Test: atest BassClientServiceTest BassClientStateMachineTest Change-Id: If728689e8b7d1ce3e571a14df7c0893bc00950e2 --- .../bass_client/BassClientService.java | 168 ++++++++++++---- .../bass_client/BassClientStateMachine.java | 137 +++++++------ .../bass_client/BassClientServiceTest.java | 181 +++++++++++++++++- .../BassClientStateMachineTest.java | 39 +++- 4 files changed, 422 insertions(+), 103 deletions(-) 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 8135014cbfe..7a0389ad2c5 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -169,6 +169,8 @@ public class BassClientService extends ProfileService { private final Map mBroadcastMetadataMap = new ConcurrentHashMap<>(); private final HashSet mPausedBroadcastSinks = new HashSet<>(); + private final Map> mSinksWaitingForPast = + new HashMap<>(); private final Map mPausedBroadcastIds = new HashMap<>(); private final Deque mPendingAddSources = new ArrayDeque<>(); private final Map> mLocalBroadcastReceivers = @@ -276,13 +278,6 @@ public class BassClientService extends ProfileService { { log("MESSAGE_BIG_MONITOR_TIMEOUT"); stopSourceReceivers(broadcastId); - synchronized (mSearchScanCallbackLock) { - // when searching is stopped then clear all sync - // data - if (mSearchScanCallback == null) { - clearAllSyncData(); - } - } break; } default: @@ -1107,6 +1102,24 @@ public class BassClientService extends ProfileService { } } + void syncRequestForPast(BluetoothDevice sink, int broadcastId, int sourceId) { + log( + "syncRequestForPast sink: " + + sink + + ", broadcastId: " + + broadcastId + + ", sourceId: " + + sourceId); + + if (!leaudioBroadcastResyncHelper()) { + return; + } + synchronized (mSinksWaitingForPast) { + mSinksWaitingForPast.put(sink, new Pair(broadcastId, sourceId)); + } + addSelectSourceRequest(broadcastId, true); + } + private void localNotifyReceiveStateChanged( BluetoothDevice sink, BluetoothLeBroadcastReceiveState receiveState) { int broadcastId = receiveState.getBroadcastId(); @@ -1114,24 +1127,14 @@ public class BassClientService extends ProfileService { && !isLocalBroadcast(receiveState) && !isEmptyBluetoothDevice(receiveState.getSourceDevice()) && !isHostPauseType(broadcastId)) { - boolean isReadyToAutoResync = false; - if (receiveState.getPaSyncState() - == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED) { - isReadyToAutoResync = true; - } else { - for (int i = 0; i < receiveState.getNumSubgroups(); i++) { - Long syncState = receiveState.getBisSyncState().get(i); - /* Synced to BIS */ - if (syncState != BassConstants.BIS_SYNC_NOT_SYNC_TO_BIS - && syncState != BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG) { - isReadyToAutoResync = true; - break; - } - } - } - if (isReadyToAutoResync) { - stopBigMonitoring(broadcastId, false); + if (isReceiverActive(receiveState) + || receiveState.getPaSyncState() + == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCINFO_REQUEST) { + mPausedBroadcastSinks.remove(sink); + if (isAllReceiversActive(broadcastId) && mPausedBroadcastSinks.isEmpty()) { + stopBigMonitoring(broadcastId, false); + } } else if (!mPausedBroadcastIds.containsKey(broadcastId)) { if (mCachedBroadcasts.containsKey(broadcastId)) { addSelectSourceRequest(broadcastId, true); @@ -1144,6 +1147,9 @@ public class BassClientService extends ProfileService { } } } else if (isEmptyBluetoothDevice(receiveState.getSourceDevice())) { + synchronized (mSinksWaitingForPast) { + mSinksWaitingForPast.remove(sink); + } checkAndStopBigMonitoring(); } @@ -1584,8 +1590,9 @@ public class BassClientService extends ProfileService { if (toState == BluetoothProfile.STATE_DISCONNECTED) { mPendingGroupOp.remove(device); mPausedBroadcastSinks.remove(device); - - checkAndStopBigMonitoring(); + synchronized (mSinksWaitingForPast) { + mSinksWaitingForPast.remove(device); + } int bondState = mAdapterService.getBondState(device); if (bondState == BluetoothDevice.BOND_NONE) { @@ -1593,6 +1600,20 @@ public class BassClientService extends ProfileService { removeStateMachine(device); } + checkAndStopBigMonitoring(); + + if (getConnectedDevices().isEmpty() + || (mPausedBroadcastSinks.isEmpty() + && mSinksWaitingForPast.isEmpty() + && !isAnyConnectedDeviceSwitchingSource())) { + synchronized (mSearchScanCallbackLock) { + // when searching is stopped then clear all sync data + if (mSearchScanCallback == null) { + clearAllSyncData(); + } + } + } + /* Restore allowed context mask for unicast in case if last connected broadcast * delegator device which has external source disconnectes. */ @@ -2167,6 +2188,41 @@ public class BassClientService extends ProfileService { } mBisDiscoveryCounterMap.put(syncHandle, MAX_BIS_DISCOVERY_TRIES_NUM); + synchronized (mSinksWaitingForPast) { + Iterator>> iterator = + mSinksWaitingForPast.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry> entry = iterator.next(); + BluetoothDevice sinkDevice = entry.getKey(); + int broadcastIdForPast = entry.getValue().first; + if (broadcastId == broadcastIdForPast) { + int sourceId = entry.getValue().second; + synchronized (mStateMachines) { + BassClientStateMachine sm = getOrCreateStateMachine(sinkDevice); + Message message = + sm.obtainMessage( + BassClientStateMachine.INITIATE_PA_SYNC_TRANSFER); + message.arg1 = syncHandle; + message.arg2 = sourceId; + sm.sendMessage(message); + } + synchronized (mPendingSourcesToAdd) { + Iterator addIterator = + mPendingSourcesToAdd.iterator(); + while (addIterator.hasNext()) { + AddSourceData pendingSourcesToAdd = addIterator.next(); + if (pendingSourcesToAdd.mSourceMetadata.getBroadcastId() + == broadcastId + && pendingSourcesToAdd.mSink.equals(sinkDevice)) { + addIterator.remove(); + } + } + } + iterator.remove(); + } + } + } + synchronized (mPendingSourcesToAdd) { Iterator iterator = mPendingSourcesToAdd.iterator(); while (iterator.hasNext()) { @@ -3698,14 +3754,23 @@ public class BassClientService extends ProfileService { .filter(e -> e.getBroadcastId() == metadata.getBroadcastId()) .findAny(); + if (leaudioBroadcastResyncHelper() + && receiveState.isPresent() + && (receiveState.get().getPaSyncState() + == BluetoothLeBroadcastReceiveState + .PA_SYNC_STATE_SYNCINFO_REQUEST + || receiveState.get().getPaSyncState() + == BluetoothLeBroadcastReceiveState + .PA_SYNC_STATE_SYNCHRONIZED)) { + iterator.remove(); + continue; + } + List activeSyncedSrc = getActiveSyncedSources(); if (receiveState.isPresent() && (!leaudioBroadcastResyncHelper() || isLocalBroadcast(metadata) - || receiveState.get().getPaSyncState() - == BluetoothLeBroadcastReceiveState - .PA_SYNC_STATE_SYNCHRONIZED || activeSyncedSrc.contains( getSyncHandleForBroadcastId(metadata.getBroadcastId())))) { int sourceId = receiveState.get().getSourceId(); @@ -3862,26 +3927,51 @@ public class BassClientService extends ProfileService { return false; } + private boolean isReceiverActive(BluetoothLeBroadcastReceiveState receiveState) { + if (receiveState.getPaSyncState() + == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED) { + return true; + } else { + for (int i = 0; i < receiveState.getNumSubgroups(); i++) { + Long syncState = receiveState.getBisSyncState().get(i); + /* Synced to BIS */ + if (syncState != BassConstants.BIS_SYNC_NOT_SYNC_TO_BIS + && syncState != BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG) { + return true; + } + } + } + return false; + } + private Set getExternalBroadcastsActiveOnSinks() { HashSet syncedBroadcasts = new HashSet<>(); for (BluetoothDevice device : getConnectedDevices()) { for (BluetoothLeBroadcastReceiveState receiveState : getAllSources(device)) { - if (!isLocalBroadcast(receiveState)) { - for (int i = 0; i < receiveState.getNumSubgroups(); i++) { - Long syncState = receiveState.getBisSyncState().get(i); - /* Synced to BIS */ - if (syncState != BassConstants.BIS_SYNC_NOT_SYNC_TO_BIS - && syncState != BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG) { - syncedBroadcasts.add(receiveState.getBroadcastId()); - log("getExternalBroadcastsActiveOnSinks: " + receiveState); - } - } + if (isLocalBroadcast(receiveState)) { + continue; + } + if (isReceiverActive(receiveState)) { + syncedBroadcasts.add(receiveState.getBroadcastId()); + log("getExternalBroadcastsActiveOnSinks: " + receiveState); } } } return syncedBroadcasts; } + private boolean isAllReceiversActive(int broadcastId) { + for (BluetoothDevice device : getConnectedDevices()) { + for (BluetoothLeBroadcastReceiveState receiveState : getAllSources(device)) { + if (receiveState.getBroadcastId() == broadcastId + && !isReceiverActive(receiveState)) { + return false; + } + } + } + return true; + } + /** Get sink devices synced to the broadcasts */ public List getSyncedBroadcastSinks() { List activeSinks = new ArrayList<>(); diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index adca0a07b6a..b59ff2fcd27 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -84,8 +84,7 @@ import java.util.Scanner; import java.util.UUID; import java.util.stream.IntStream; -@VisibleForTesting -public class BassClientStateMachine extends StateMachine { +class BassClientStateMachine extends StateMachine { private static final String TAG = "BassClientStateMachine"; @VisibleForTesting static final byte[] REMOTE_SCAN_STOP = {00}; @VisibleForTesting static final byte[] REMOTE_SCAN_START = {01}; @@ -113,6 +112,7 @@ public class BassClientStateMachine extends StateMachine { static final int REACHED_MAX_SOURCE_LIMIT = 16; static final int SWITCH_BCAST_SOURCE = 17; static final int CANCEL_PENDING_SOURCE_OPERATION = 18; + static final int INITIATE_PA_SYNC_TRANSFER = 19; // NOTE: the value is not "final" - it is modified in the unit tests @VisibleForTesting private int mConnectTimeoutMs; @@ -816,69 +816,80 @@ public class BassClientStateMachine extends StateMachine { int state = recvState.getPaSyncState(); if (state == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCINFO_REQUEST) { log("Initiate PAST procedure"); - PeriodicAdvertisementResult result = - mService.getPeriodicAdvertisementResult( - recvState.getSourceDevice(), recvState.getBroadcastId()); - if (result != null) { - int syncHandle = result.getSyncHandle(); - log("processPASyncState: syncHandle " + result.getSyncHandle()); - if (syncHandle != BassConstants.INVALID_SYNC_HANDLE) { - serviceData = 0x000000FF & recvState.getSourceId(); - serviceData = serviceData << 8; - // advA matches EXT_ADV_ADDRESS - // also matches source address (as we would have written) - serviceData = - serviceData & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_EXT_ADV_ADDRESS); - serviceData = - serviceData - & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS); - log( - "Initiate PAST for: " - + mDevice - + ", syncHandle: " - + syncHandle - + "serviceData" - + serviceData); - BluetoothMethodProxy.getInstance() - .periodicAdvertisingManagerTransferSync( - BassClientPeriodicAdvertisingManager - .getPeriodicAdvertisingManager(), - mDevice, - serviceData, - syncHandle); - } + int sourceId = recvState.getSourceId(); + BluetoothLeBroadcastMetadata currentMetadata = getCurrentBroadcastMetadata(sourceId); + if (mService.isLocalBroadcast(currentMetadata)) { + int advHandle = currentMetadata.getSourceAdvertisingSid(); + serviceData = 0x000000FF & sourceId; + serviceData = serviceData << 8; + // Address we set in the Source Address can differ from the address in the air + serviceData = + serviceData | BassConstants.ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS; + log( + "Initiate local broadcast PAST for: " + + mDevice + + ", advSID/Handle: " + + advHandle + + ", serviceData: " + + serviceData); + BluetoothMethodProxy.getInstance() + .periodicAdvertisingManagerTransferSetInfo( + BassClientPeriodicAdvertisingManager + .getPeriodicAdvertisingManager(), + mDevice, + serviceData, + advHandle, + mLocalPeriodicAdvCallback); } else { - BluetoothLeBroadcastMetadata currentMetadata = - getCurrentBroadcastMetadata(recvState.getSourceId()); - if (mService.isLocalBroadcast(currentMetadata)) { - int advHandle = currentMetadata.getSourceAdvertisingSid(); - serviceData = 0x000000FF & recvState.getSourceId(); - serviceData = serviceData << 8; - // Address we set in the Source Address can differ from the address in the air - serviceData = - serviceData | BassConstants.ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS; - log( - "Initiate local broadcast PAST for: " - + mDevice - + ", advSID/Handle: " - + advHandle - + ", serviceData: " - + serviceData); - BluetoothMethodProxy.getInstance() - .periodicAdvertisingManagerTransferSetInfo( - BassClientPeriodicAdvertisingManager - .getPeriodicAdvertisingManager(), - mDevice, - serviceData, - advHandle, - mLocalPeriodicAdvCallback); - } else { - Log.e(TAG, "There is no valid sync handle for this Source"); + int broadcastId = recvState.getBroadcastId(); + PeriodicAdvertisementResult result = + mService.getPeriodicAdvertisementResult( + recvState.getSourceDevice(), broadcastId); + if (result != null) { + int syncHandle = result.getSyncHandle(); + if (syncHandle != BassConstants.INVALID_SYNC_HANDLE) { + initiatePaSyncTransfer(syncHandle, sourceId); + return; + } } + mService.syncRequestForPast(mDevice, broadcastId, sourceId); } } } + private void initiatePaSyncTransfer(int syncHandle, int sourceId) { + if (syncHandle != BassConstants.INVALID_SYNC_HANDLE + && sourceId != BassConstants.INVALID_SOURCE_ID) { + int serviceData = 0x000000FF & sourceId; + serviceData = serviceData << 8; + // advA matches EXT_ADV_ADDRESS + // also matches source address (as we would have written) + serviceData = serviceData & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_EXT_ADV_ADDRESS); + serviceData = + serviceData & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS); + log( + "Initiate PAST for: " + + mDevice + + ", syncHandle: " + + syncHandle + + ", serviceData: " + + serviceData); + BluetoothMethodProxy.getInstance() + .periodicAdvertisingManagerTransferSync( + BassClientPeriodicAdvertisingManager.getPeriodicAdvertisingManager(), + mDevice, + serviceData, + syncHandle); + } else { + Log.e( + TAG, + "Invalid syncHandle or sourceId for PAST, syncHandle: " + + syncHandle + + ", sourceId: " + + sourceId); + } + } + private void processSyncStateChangeStats(BluetoothLeBroadcastReceiveState recvState) { int sourceId = recvState.getSourceId(); BluetoothLeBroadcastMetadata metaData = getCurrentBroadcastMetadata(sourceId); @@ -2350,6 +2361,11 @@ public class BassClientStateMachine extends StateMachine { int broadcastId = message.arg1; cancelPendingSourceOperation(broadcastId); break; + case INITIATE_PA_SYNC_TRANSFER: + int syncHandle = message.arg1; + int sourceIdForPast = message.arg2; + initiatePaSyncTransfer(syncHandle, sourceIdForPast); + break; default: log("CONNECTED: not handled message:" + message.what); return NOT_HANDLED; @@ -2539,6 +2555,7 @@ public class BassClientStateMachine extends StateMachine { case REACHED_MAX_SOURCE_LIMIT: case SWITCH_BCAST_SOURCE: case PSYNC_ACTIVE_TIMEOUT: + case INITIATE_PA_SYNC_TRANSFER: log( "defer the message: " + messageWhatToString(message.what) @@ -2646,6 +2663,8 @@ public class BassClientStateMachine extends StateMachine { return "CONNECT_TIMEOUT"; case CANCEL_PENDING_SOURCE_OPERATION: return "CANCEL_PENDING_SOURCE_OPERATION"; + case INITIATE_PA_SYNC_TRANSFER: + return "INITIATE_PA_SYNC_TRANSFER"; default: break; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 89fe1daa5bf..12a0f7d9efe 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -1637,6 +1637,38 @@ public class BassClientServiceTest { } } + private void injectRemoteSourceStateChanged( + BluetoothLeBroadcastMetadata meta, int paSynState, boolean isBisSynced) { + for (BassClientStateMachine sm : mStateMachines.values()) { + // Update receiver state + if (sm.getDevice().equals(mCurrentDevice)) { + injectRemoteSourceStateChanged( + sm, + meta, + TEST_SOURCE_ID, + paSynState, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState + .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null, + isBisSynced ? (long) 0x00000001 : (long) 0x00000000); + } else if (sm.getDevice().equals(mCurrentDevice1)) { + injectRemoteSourceStateChanged( + sm, + meta, + TEST_SOURCE_ID + 1, + paSynState, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState + .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null, + isBisSynced ? (long) 0x00000002 : (long) 0x00000000); + } + } + } + private void injectRemoteSourceStateRemoval(BassClientStateMachine sm, int sourceId) { List stateList = sm.getAllSources(); if (stateList == null) { @@ -4215,8 +4247,8 @@ public class BassClientServiceTest { verify(mLeAudioService).activeBroadcastAssistantNotification(eq(true)); Mockito.clearInvocations(mLeAudioService); - /* Imitate broadcast source stop, sink notify about loosing BIS sync */ - injectRemoteSourceStateChanged(meta, true, false); + /* Imitate broadcast source stop, sink notify about loosing PA and BIS sync */ + injectRemoteSourceStateChanged(meta, false, false); /* Unicast would like to stream */ mBassClientService.cacheSuspendingSources(TEST_BROADCAST_ID); @@ -4253,8 +4285,8 @@ public class BassClientServiceTest { 0 /* STATUS_LOCAL_STREAM_REQUESTED */); if (Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { - /* Imitate broadcast source stop, sink notify about loosing BIS sync */ - injectRemoteSourceStateChanged(meta, true, false); + /* Imitate broadcast source stop, sink notify about loosing PA and BIS sync */ + injectRemoteSourceStateChanged(meta, false, false); } else { verifyRemoveMessageAndInjectSourceRemoval(); } @@ -6757,4 +6789,145 @@ public class BassClientServiceTest { assertThat(mBassClientService.isLocalBroadcast(metadata)).isTrue(); assertThat(mBassClientService.isLocalBroadcast(receiveState)).isTrue(); } + + private void verifyInitiatePaSyncTransferAndNoOthers() { + expect.that(mStateMachines.size()).isEqualTo(2); + for (BassClientStateMachine sm : mStateMachines.values()) { + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(sm, atLeast(1)).sendMessage(messageCaptor.capture()); + long count; + if (sm.getDevice().equals(mCurrentDevice)) { + count = + messageCaptor.getAllValues().stream() + .filter( + m -> + (m.what + == BassClientStateMachine + .INITIATE_PA_SYNC_TRANSFER) + && (m.arg1 == TEST_SYNC_HANDLE) + && (m.arg2 == TEST_SOURCE_ID)) + .count(); + assertThat(count).isEqualTo(1); + count = + messageCaptor.getAllValues().stream() + .filter( + m -> + m.what + != BassClientStateMachine + .INITIATE_PA_SYNC_TRANSFER) + .count(); + assertThat(count).isEqualTo(0); + } else if (sm.getDevice().equals(mCurrentDevice1)) { + count = + messageCaptor.getAllValues().stream() + .filter( + m -> + (m.what + == BassClientStateMachine + .INITIATE_PA_SYNC_TRANSFER) + && (m.arg1 == TEST_SYNC_HANDLE) + && (m.arg2 == TEST_SOURCE_ID + 1)) + .count(); + assertThat(count).isEqualTo(1); + count = + messageCaptor.getAllValues().stream() + .filter( + m -> + m.what + != BassClientStateMachine + .INITIATE_PA_SYNC_TRANSFER) + .count(); + assertThat(count).isEqualTo(0); + } else { + throw new AssertionError("Unexpected device"); + } + } + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void initiatePaSyncTransfer() { + prepareSynchronizedPairAndStopSearching(); + + // Sync info request force syncing to broadcaster and add sinks pending for PAST + mBassClientService.syncRequestForPast(mCurrentDevice, TEST_BROADCAST_ID, TEST_SOURCE_ID); + mBassClientService.syncRequestForPast( + mCurrentDevice1, TEST_BROADCAST_ID, TEST_SOURCE_ID + 1); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + // Sync will INITIATE_PA_SYNC_TRANSFER + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + verifyInitiatePaSyncTransferAndNoOthers(); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void InitiatePaSyncTransfer_concurrentWithResume() { + prepareSynchronizedPairAndStopSearching(); + + BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); + + // Cache sinks for resume and set HOST_INTENTIONAL pause + mBassClientService.handleUnicastSourceStreamStatusChange( + 0 /* STATUS_LOCAL_STREAM_REQUESTED */); + injectRemoteSourceStateChanged(meta, false, false); + + // Resume source will force syncing to broadcaser and put pending source to add + mBassClientService.resumeReceiversSourceSynchronization(); + mInOrderMethodProxy + .verify(mMethodProxy) + .periodicAdvertisingManagerRegisterSync( + any(), any(), anyInt(), anyInt(), any(), any()); + + // Sync info request add sinks pending for PAST + mBassClientService.syncRequestForPast(mCurrentDevice, TEST_BROADCAST_ID, TEST_SOURCE_ID); + mBassClientService.syncRequestForPast( + mCurrentDevice1, TEST_BROADCAST_ID, TEST_SOURCE_ID + 1); + + // Sync will send INITIATE_PA_SYNC_TRANSFER and remove pending soure to add + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + verifyInitiatePaSyncTransferAndNoOthers(); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void resumeSourceSynchronization_omitWhenPaSyncedOrRequested() { + prepareSynchronizedPair(); + + BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); + + // Cache sinks for resume and set HOST_INTENTIONAL pause + // Try resume while sync info requested + mBassClientService.handleUnicastSourceStreamStatusChange( + 0 /* STATUS_LOCAL_STREAM_REQUESTED */); + injectRemoteSourceStateChanged( + meta, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCINFO_REQUEST, false); + checkNoResumeSynchronizationByHost(); + + // Cache sinks for resume and set HOST_INTENTIONAL pause + // Try resume while pa synced + mBassClientService.handleUnicastSourceStreamStatusChange( + 0 /* STATUS_LOCAL_STREAM_REQUESTED */); + injectRemoteSourceStateChanged(meta, true, false); + checkNoResumeSynchronizationByHost(); + + // Cache sinks for resume and set HOST_INTENTIONAL pause + // Try resume while pa unsynced + mBassClientService.handleUnicastSourceStreamStatusChange( + 0 /* STATUS_LOCAL_STREAM_REQUESTED */); + injectRemoteSourceStateChanged(meta, false, false); + checkResumeSynchronizationByHost(); + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index e4ae0e4dd8f..696526bb262 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -32,6 +32,7 @@ import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT_T import static com.android.bluetooth.bass_client.BassClientStateMachine.DISCONNECT; import static com.android.bluetooth.bass_client.BassClientStateMachine.GATT_TXN_PROCESSED; import static com.android.bluetooth.bass_client.BassClientStateMachine.GATT_TXN_TIMEOUT; +import static com.android.bluetooth.bass_client.BassClientStateMachine.INITIATE_PA_SYNC_TRANSFER; import static com.android.bluetooth.bass_client.BassClientStateMachine.PSYNC_ACTIVE_TIMEOUT; import static com.android.bluetooth.bass_client.BassClientStateMachine.REACHED_MAX_SOURCE_LIMIT; import static com.android.bluetooth.bass_client.BassClientStateMachine.READ_BASS_CHARACTERISTICS; @@ -894,12 +895,23 @@ public class BassClientStateMachineTest { when(characteristic.getValue()).thenReturn(value); when(mBassClientService.getPeriodicAdvertisementResult(any(), anyInt())) .thenReturn(paResult); - when(paResult.getSyncHandle()).thenReturn(100); + int syncHandle = 100; + when(paResult.getSyncHandle()).thenReturn(syncHandle); Mockito.clearInvocations(callbacks); cb.onCharacteristicRead(null, characteristic, GATT_SUCCESS); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + int serviceData = 0x000000FF & sourceId; + serviceData = serviceData << 8; + // advA matches EXT_ADV_ADDRESS + // also matches source address (as we would have written) + serviceData = serviceData & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_EXT_ADV_ADDRESS); + serviceData = serviceData & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS); + verify(mMethodProxy) + .periodicAdvertisingManagerTransferSync( + any(), any(), eq(serviceData), eq(syncHandle)); + verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); @@ -1706,6 +1718,26 @@ public class BassClientStateMachineTest { assertThat(mBassClientStateMachine.mPendingSourceId).isEqualTo(sid); } + @Test + public void sendInitiatePaSyncTransferMessage_inConnectedState() { + initToConnectedState(); + int syncHandle = 1234; + int sourceId = 4321; + + mBassClientStateMachine.sendMessage(INITIATE_PA_SYNC_TRANSFER, syncHandle, sourceId); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + + int serviceData = 0x000000FF & sourceId; + serviceData = serviceData << 8; + // advA matches EXT_ADV_ADDRESS + // also matches source address (as we would have written) + serviceData = serviceData & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_EXT_ADV_ADDRESS); + serviceData = serviceData & (~BassConstants.ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS); + verify(mMethodProxy) + .periodicAdvertisingManagerTransferSync( + any(), any(), eq(serviceData), eq(syncHandle)); + } + @Test public void sendConnectMessage_inConnectedProcessingState_doesNotChangeState() { initToConnectedProcessingState(); @@ -1906,6 +1938,11 @@ public class BassClientStateMachineTest { mBassClientStateMachine.sendMessage(SWITCH_BCAST_SOURCE); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); assertThat(mBassClientStateMachine.hasDeferredMessagesSuper(SWITCH_BCAST_SOURCE)).isTrue(); + + mBassClientStateMachine.sendMessage(INITIATE_PA_SYNC_TRANSFER); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + assertThat(mBassClientStateMachine.hasDeferredMessagesSuper(INITIATE_PA_SYNC_TRANSFER)) + .isTrue(); } @Test -- GitLab From 882559bd4a68f7761f0c12f28468612723bcce09 Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Tue, 1 Oct 2024 13:41:19 +0000 Subject: [PATCH 425/875] LeAudio: Fix redundant AIDL call with software encoding When using software encoding the AIDL call for the audio set configuration fails and we fall back to local configurations source. On software path we should use local configuration and not call the AIDL interface at all. Bug: 374933885 Bug: 313054645 Test: atest bluetooth_le_audio_codec_manager_test Flag: EXEMPT; bug fix covered with unit tests Change-Id: I5f26a4326594a54228ee9a33835c12934101afc7 --- system/bta/le_audio/codec_manager.cc | 80 +++++++++++------------ system/bta/le_audio/codec_manager_test.cc | 34 ++++++++++ 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index d4b0fe0efc7..117c3a2cec8 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -280,23 +280,47 @@ public: return true; } - AudioSetConfigurations GetSupportedCodecConfigurations( - const CodecManager::UnicastConfigurationRequirements& requirements) const { + std::unique_ptr GetLocalCodecConfigurations( + const CodecManager::UnicastConfigurationRequirements& requirements, + CodecManager::UnicastConfigurationProvider provider) const { + AudioSetConfigurations configs; if (GetCodecLocation() == le_audio::types::CodecLocation::ADSP) { log::verbose("Get offload config for the context type: {}", (int)requirements.audio_context_type); - // TODO: Need to have a mechanism to switch to software session if offload // doesn't support. - return context_type_offload_config_map_.count(requirements.audio_context_type) - ? context_type_offload_config_map_.at(requirements.audio_context_type) - : AudioSetConfigurations(); + configs = context_type_offload_config_map_.count(requirements.audio_context_type) + ? context_type_offload_config_map_.at(requirements.audio_context_type) + : AudioSetConfigurations(); + } else { + log::verbose("Get software config for the context type: {}", + (int)requirements.audio_context_type); + configs = *AudioSetConfigurationProvider::Get()->GetConfigurations( + requirements.audio_context_type); } - log::verbose("Get software config for the context type: {}", - (int)requirements.audio_context_type); - return *AudioSetConfigurationProvider::Get()->GetConfigurations( - requirements.audio_context_type); + if (configs.empty()) { + log::error("No valid configuration matching the requirements: {}", requirements); + PrintDebugState(); + return nullptr; + } + + // Remove the dual bidir SWB config if not supported + if (!IsDualBiDirSwbSupported()) { + configs.erase(std::remove_if(configs.begin(), configs.end(), + [](auto const& el) { + if (el->confs.source.empty()) { + return false; + } + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb(*el); + }), + configs.end()); + } + + // Note: For the software configuration provider, we use the provider matcher + // logic to match the proper configuration with group capabilities. + return provider(requirements, &configs); } void PrintDebugState() const { @@ -317,6 +341,10 @@ public: } bool IsUsingCodecExtensibility() const { + if (GetCodecLocation() == types::CodecLocation::HOST) { + return false; + } + auto codec_ext_status = osi_property_get_bool("bluetooth.core.le_audio.codec_extension_aidl.enabled", false) && com::android::bluetooth::flags::leaudio_multicodec_aidl_support(); @@ -333,37 +361,9 @@ public: if (hal_config) { return std::make_unique(*hal_config); } - log::debug( - "No configuration received from AIDL, fall back to static " - "configuration."); + log::debug("No configuration received from AIDL, fall back to static configuration."); } - - auto configs = GetSupportedCodecConfigurations(requirements); - if (configs.empty()) { - log::error("No valid configuration matching the requirements: {}", requirements); - PrintDebugState(); - return nullptr; - } - - // Remove the dual bidir SWB config if not supported - if (!IsDualBiDirSwbSupported()) { - configs.erase(std::remove_if(configs.begin(), configs.end(), - [](auto const& el) { - if (el->confs.source.empty()) { - return false; - } - return AudioSetConfigurationProvider::Get() - ->CheckConfigurationIsDualBiDirSwb(*el); - }), - configs.end()); - } - - // Note: For the only supported right now legacy software configuration - // provider, we use the device group logic to match the proper - // configuration with group capabilities. Note that this path only - // supports the LC3 codec format. For the multicodec support we should - // rely on the configuration matcher behind the AIDL interface. - return provider(requirements, &configs); + return GetLocalCodecConfigurations(requirements, provider); } bool CheckCodecConfigIsBiDirSwb(const AudioSetConfiguration& config) { diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc index d72d5878802..5770fdbea42 100644 --- a/system/bta/le_audio/codec_manager_test.cc +++ b/system/bta/le_audio/codec_manager_test.cc @@ -265,6 +265,8 @@ void set_mock_offload_capabilities(const std::vector& cap } static constexpr char kPropLeAudioOffloadSupported[] = "ro.bluetooth.leaudio_offload.supported"; +static constexpr char kPropLeAudioCodecExtensibility[] = + "bluetooth.core.le_audio.codec_extension_aidl.enabled"; static constexpr char kPropLeAudioOffloadDisabled[] = "persist.bluetooth.leaudio_offload.disabled"; static constexpr char kPropLeAudioBidirSwbSupported[] = "bluetooth.leaudio.dual_bidirection_swb.supported"; @@ -823,6 +825,10 @@ public: // Allow for bidir SWB configurations osi_property_set_bool(kPropLeAudioBidirSwbSupported, true); + // Codec extensibility disabled by default + com::android::bluetooth::flags::provider_->leaudio_multicodec_aidl_support(false); + osi_property_set_bool(kPropLeAudioCodecExtensibility, false); + CodecManagerTestBase::SetUp(); } }; @@ -837,6 +843,10 @@ public: // Do not allow for bidir SWB configurations osi_property_set_bool(kPropLeAudioBidirSwbSupported, false); + // Codec extensibility disabled by default + com::android::bluetooth::flags::provider_->leaudio_multicodec_aidl_support(false); + osi_property_set_bool(kPropLeAudioCodecExtensibility, false); + CodecManagerTestBase::SetUp(); } }; @@ -1295,4 +1305,28 @@ TEST_F(CodecManagerTestHost, test_dont_update_broadcast_offloader) { ASSERT_FALSE(was_called); } +TEST_F(CodecManagerTestHost, test_dont_call_hal_for_config) { + com::android::bluetooth::flags::provider_->leaudio_multicodec_aidl_support(true); + osi_property_set_bool(kPropLeAudioCodecExtensibility, true); + + // Set the offloader capabilities + std::vector offload_capabilities; + set_mock_offload_capabilities(offload_capabilities); + + const std::vector offloading_preference = {}; + codec_manager->Start(offloading_preference); + codec_manager->UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_, + mock_le_audio_sink_hal_client_, true); + + EXPECT_CALL(*mock_le_audio_source_hal_client_, GetUnicastConfig(_)).Times(0); + codec_manager->GetCodecConfig( + {.audio_context_type = types::LeAudioContextType::MEDIA}, + [&](const CodecManager::UnicastConfigurationRequirements& /*requirements*/, + const set_configurations::AudioSetConfigurations* /*confs*/) + -> std::unique_ptr { + // In this case the chosen configuration doesn't matter - select none + return nullptr; + }); +} + } // namespace bluetooth::le_audio -- GitLab From 55b05336b553109c4e11af59cd8a1d887c054eb5 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Wed, 23 Oct 2024 18:52:13 +0800 Subject: [PATCH 426/875] Hcidoc: Support multiple concurrent connections with the same address Devices which uses the same address for BREDR and LE connections will mess up with the internal processing of hcidoc because it assumed only one connection at any given time per address. Bug: 375370824 Test: m -j Test: manually with pixel buds Flag: EXEMPT, floss only change Change-Id: I7e4d3ed24d15b74da70e44a480c67180b4233162 --- floss/hcidoc/src/groups/informational.rs | 183 +++++++++++++++++------ 1 file changed, 136 insertions(+), 47 deletions(-) diff --git a/floss/hcidoc/src/groups/informational.rs b/floss/hcidoc/src/groups/informational.rs index dbaa6c8ae37..1827b642822 100644 --- a/floss/hcidoc/src/groups/informational.rs +++ b/floss/hcidoc/src/groups/informational.rs @@ -83,6 +83,24 @@ impl AddressType { } } +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +enum Transport { + Unknown, + BREDR, + LE, +} + +impl fmt::Display for Transport { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let str = match self { + Transport::Unknown => "??", + Transport::BREDR => "BR", + Transport::LE => "LE", + }; + write!(f, "{}", str) + } +} + #[derive(Clone, Copy, PartialEq)] enum InitiatorType { Unknown, @@ -124,8 +142,8 @@ struct DeviceInformation { names: HashSet, address: Address, address_type: AddressType, - acls: Vec, - acl_state: AclState, + acls: HashMap>, + acl_state: HashMap, } impl DeviceInformation { @@ -134,30 +152,52 @@ impl DeviceInformation { names: HashSet::new(), address: address, address_type: AddressType::None, - acls: vec![], - acl_state: AclState::None, + acls: HashMap::from([(Transport::BREDR, vec![]), (Transport::LE, vec![])]), + acl_state: HashMap::from([ + (Transport::BREDR, AclState::None), + (Transport::LE, AclState::None), + ]), } } - fn is_connection_active(&self) -> bool { + fn is_connection_active(&self, transport: Transport) -> bool { + if transport == Transport::Unknown { + return false; + } + // not empty and last connection's end time is not set. - return !self.acls.is_empty() && self.acls.last().unwrap().end_time == INVALID_TS; + return !self.acls[&transport].is_empty() + && self.acls[&transport].last().unwrap().end_time == INVALID_TS; } - fn get_or_allocate_connection(&mut self, handle: &ConnectionHandle) -> &mut AclInformation { - if !self.is_connection_active() { - let acl = AclInformation::new(*handle); - self.acls.push(acl); + fn get_or_allocate_connection( + &mut self, + handle: ConnectionHandle, + transport: Transport, + ) -> &mut AclInformation { + assert_ne!(transport, Transport::Unknown, "device allocating unknown transport"); + if !self.is_connection_active(transport) { + let acl = AclInformation::new(handle, transport); + self.acls.get_mut(&transport).unwrap().push(acl); } - return self.acls.last_mut().unwrap(); + return self.acls.get_mut(&transport).unwrap().last_mut().unwrap(); } - fn report_connection_start(&mut self, handle: ConnectionHandle, ts: NaiveDateTime) { - let mut acl = AclInformation::new(handle); - let initiator = self.acl_state.get_connection_initiator(); + fn report_connection_start( + &mut self, + handle: ConnectionHandle, + transport: Transport, + ts: NaiveDateTime, + ) { + if transport == Transport::Unknown { + return; + } + + let mut acl = AclInformation::new(handle, transport); + let initiator = self.acl_state[&transport].get_connection_initiator(); acl.report_start(initiator, ts); - self.acls.push(acl); - self.acl_state = AclState::Connected; + self.acls.get_mut(&transport).unwrap().push(acl); + self.acl_state.insert(transport, AclState::Connected); } fn report_connection_end( @@ -166,9 +206,25 @@ impl DeviceInformation { initiator: InitiatorType, ts: NaiveDateTime, ) { - let acl = self.get_or_allocate_connection(&handle); - acl.report_end(initiator, ts); - self.acl_state = AclState::None; + for transport in [Transport::BREDR, Transport::LE] { + if self.is_connection_active(transport) { + if self.acls[&transport].last().unwrap().handle == handle { + self.acls + .get_mut(&transport) + .unwrap() + .last_mut() + .unwrap() + .report_end(initiator, ts); + self.acl_state.insert(transport, AclState::None); + return; + } + } + } + + eprintln!( + "device {} receive disconnection of handle {} without corresponding connection at {}", + self.address, handle, ts + ); } fn print_names(names: &HashSet) -> String { @@ -190,7 +246,10 @@ impl fmt::Display for DeviceInformation { device_names = DeviceInformation::print_names(&self.names), num_connections = self.acls.len() ); - for acl in &self.acls { + for acl in &self.acls[&Transport::BREDR] { + let _ = write!(f, "{}", acl); + } + for acl in &self.acls[&Transport::LE] { let _ = write!(f, "{}", acl); } @@ -209,6 +268,7 @@ struct AclInformation { start_time: NaiveDateTime, end_time: NaiveDateTime, handle: ConnectionHandle, + transport: Transport, start_initiator: InitiatorType, end_initiator: InitiatorType, active_profiles: HashMap, @@ -218,11 +278,12 @@ struct AclInformation { } impl AclInformation { - pub fn new(handle: ConnectionHandle) -> Self { + pub fn new(handle: ConnectionHandle, transport: Transport) -> Self { AclInformation { start_time: INVALID_TS, end_time: INVALID_TS, - handle: handle, + handle, + transport, start_initiator: InitiatorType::Unknown, end_initiator: InitiatorType::Unknown, active_profiles: HashMap::new(), @@ -387,7 +448,8 @@ impl fmt::Display for AclInformation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let _ = writeln!( f, - " Handle: {handle}, {timestamp_initiator_info}", + " Handle: {handle} ({transport}), {timestamp_initiator_info}", + transport = self.transport, handle = self.handle, timestamp_initiator_info = print_timestamps_and_initiator( self.start_time, @@ -566,23 +628,28 @@ impl InformationalRule { fn get_or_allocate_unknown_connection( &mut self, - handle: &ConnectionHandle, + handle: ConnectionHandle, + transport: Transport, ) -> &mut AclInformation { - if !self.unknown_connections.contains_key(handle) { - self.unknown_connections.insert(*handle, AclInformation::new(*handle)); + if !self.unknown_connections.contains_key(&handle) { + self.unknown_connections.insert(handle, AclInformation::new(handle, transport)); } - return self.unknown_connections.get_mut(handle).unwrap(); + return self.unknown_connections.get_mut(&handle).unwrap(); } - fn get_or_allocate_connection(&mut self, handle: &ConnectionHandle) -> &mut AclInformation { - if !self.handles.contains_key(&handle) { - let conn = self.get_or_allocate_unknown_connection(&handle); + fn get_or_allocate_connection( + &mut self, + handle: ConnectionHandle, + transport: Transport, + ) -> &mut AclInformation { + if !self.handles.contains_key(&handle) || transport == Transport::Unknown { + let conn = self.get_or_allocate_unknown_connection(handle, transport); return conn; } - let address = &self.handles.get(handle).unwrap().clone(); + let address = &self.handles.get(&handle).unwrap().clone(); let device = self.get_or_allocate_device(address); - return device.get_or_allocate_connection(handle); + return device.get_or_allocate_connection(handle, transport); } fn report_address_type(&mut self, address: &Address, address_type: AddressType) { @@ -595,19 +662,20 @@ impl InformationalRule { device.names.insert(name.into()); } - fn report_acl_state(&mut self, address: &Address, state: AclState) { + fn report_acl_state(&mut self, address: &Address, transport: Transport, state: AclState) { let device = self.get_or_allocate_device(address); - device.acl_state = state; + device.acl_state.insert(transport, state); } fn report_connection_start( &mut self, address: &Address, handle: ConnectionHandle, + transport: Transport, ts: NaiveDateTime, ) { let device = self.get_or_allocate_device(address); - device.report_connection_start(handle, ts); + device.report_connection_start(handle, transport, ts); self.handles.insert(handle, *address); self.pending_disconnections.remove(&handle); } @@ -624,14 +692,14 @@ impl InformationalRule { } let device = self.devices.get_mut(address).unwrap(); - if !device.is_connection_active() { + if !device.is_connection_active(Transport::BREDR) { // SCO is connected, but ACL is not. This is weird, but let's ignore for simplicity. eprintln!("[{}] SCO is connected, but ACL is not.", address); return; } // Whatever handle value works here - we aren't allocating a new one. - let acl = device.get_or_allocate_connection(&0); + let acl = device.get_or_allocate_connection(0, Transport::BREDR); let acl_handle = acl.handle; // We need to listen the HCI commands to determine the correct initiator. // Here we just assume host for simplicity. @@ -654,7 +722,7 @@ impl InformationalRule { // This might be a SCO disconnection event, so check that first if self.sco_handles.contains_key(&handle) { let acl_handle = self.sco_handles[&handle]; - let conn = self.get_or_allocate_connection(&acl_handle); + let conn = self.get_or_allocate_connection(acl_handle, Transport::BREDR); // in case of HFP failure, the initiator here would be set to peer, which is incorrect, // but when printing we detect by the timestamp that it was a failure anyway. conn.report_profile_end( @@ -677,7 +745,7 @@ impl InformationalRule { self.sco_handles.retain(|_sco_handle, acl_handle| *acl_handle != handle); } else { // Unknown device. - let conn = self.get_or_allocate_unknown_connection(&handle); + let conn = self.get_or_allocate_unknown_connection(handle, Transport::Unknown); conn.report_end(initiator, ts); } } @@ -731,7 +799,7 @@ impl InformationalRule { initiator: InitiatorType, ts: NaiveDateTime, ) { - let conn = self.get_or_allocate_connection(&handle); + let conn = self.get_or_allocate_connection(handle, Transport::BREDR); conn.report_l2cap_conn_req(psm, cid, initiator, ts); } @@ -747,7 +815,7 @@ impl InformationalRule { if status == ConnectionResponseResult::Pending { return; } - let conn = self.get_or_allocate_connection(&handle); + let conn = self.get_or_allocate_connection(handle, Transport::BREDR); let cid_info = CidInformation { host_cid, peer_cid }; conn.report_l2cap_conn_rsp(status, cid_info, initiator, ts); } @@ -760,7 +828,7 @@ impl InformationalRule { initiator: InitiatorType, ts: NaiveDateTime, ) { - let conn = self.get_or_allocate_connection(&handle); + let conn = self.get_or_allocate_connection(handle, Transport::BREDR); let cid_info = CidInformation { host_cid, peer_cid }; conn.report_l2cap_disconn_rsp(cid_info, initiator, ts); } @@ -774,6 +842,7 @@ impl Rule for InformationalRule { self.report_connection_start( &ev.get_bd_addr(), ev.get_connection_handle(), + Transport::BREDR, packet.ts, ); @@ -830,10 +899,15 @@ impl Rule for InformationalRule { } // Determining LE initiator is complex, for simplicity assume host inits. - self.report_acl_state(&ev.get_peer_address(), AclState::Initiating); + self.report_acl_state( + &ev.get_peer_address(), + Transport::LE, + AclState::Initiating, + ); self.report_connection_start( &ev.get_peer_address(), ev.get_connection_handle(), + Transport::LE, packet.ts, ); self.report_address_type(&ev.get_peer_address(), AddressType::LE); @@ -845,10 +919,15 @@ impl Rule for InformationalRule { } // Determining LE initiator is complex, for simplicity assume host inits. - self.report_acl_state(&ev.get_peer_address(), AclState::Initiating); + self.report_acl_state( + &ev.get_peer_address(), + Transport::LE, + AclState::Initiating, + ); self.report_connection_start( &ev.get_peer_address(), ev.get_connection_handle(), + Transport::LE, packet.ts, ); self.report_address_type(&ev.get_peer_address(), AddressType::LE); @@ -881,11 +960,19 @@ impl Rule for InformationalRule { self.report_reset(packet.ts); } CommandChild::CreateConnection(cmd) => { - self.report_acl_state(&cmd.get_bd_addr(), AclState::Initiating); + self.report_acl_state( + &cmd.get_bd_addr(), + Transport::BREDR, + AclState::Initiating, + ); self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR); } CommandChild::AcceptConnectionRequest(cmd) => { - self.report_acl_state(&cmd.get_bd_addr(), AclState::Accepting); + self.report_acl_state( + &cmd.get_bd_addr(), + Transport::BREDR, + AclState::Accepting, + ); self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR); } CommandChild::Disconnect(cmd) => { @@ -1001,7 +1088,9 @@ impl Rule for InformationalRule { * (5) Address, alphabetically */ fn sort_addresses(a: &DeviceInformation, b: &DeviceInformation) -> Ordering { - let connection_order = a.acls.is_empty().cmp(&b.acls.is_empty()); + let a_empty = a.acls[&Transport::BREDR].is_empty() && a.acls[&Transport::LE].is_empty(); + let b_empty = b.acls[&Transport::BREDR].is_empty() && b.acls[&Transport::LE].is_empty(); + let connection_order = a_empty.cmp(&b_empty); if connection_order != Ordering::Equal { return connection_order; } -- GitLab From a5468e2c028c6629a8f98e724fd3fb3fba81d754 Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Tue, 22 Oct 2024 11:18:10 -0700 Subject: [PATCH 427/875] stack::avct: Add dumpsys Bug: 375001524 Test: m . Flag: EXEMPT, Dumpsys logging change Change-Id: I83dbac8a28123cc549a651c3b7cfe5282576ad97 --- system/btif/src/bluetooth.cc | 2 ++ system/stack/avct/avct_api.cc | 35 +++++++++++++++++++++++++ system/stack/include/avct_api.h | 14 ++++++++++ system/test/mock/mock_stack_avct_api.cc | 1 + 4 files changed, 52 insertions(+) diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index a5a2e54f203..c4bb371e80a 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -102,6 +102,7 @@ #include "stack/btm/btm_sco_hfp_hal.h" #include "stack/connection_manager/connection_manager.h" #include "stack/include/a2dp_api.h" +#include "stack/include/avct_api.h" #include "stack/include/avdt_api.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_status.h" @@ -886,6 +887,7 @@ static void dump(int fd, const char** arguments) { VolumeControl::DebugDump(fd); connection_manager::dump(fd); bluetooth::bqr::DebugDump(fd); + AVCT_Dumpsys(fd); PAN_Dumpsys(fd); DumpsysHid(fd); DumpsysBtaDm(fd); diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index 2c4426f1a5d..70efdee0c22 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -31,6 +31,7 @@ #include "avct_int.h" #include "bta/include/bta_sec_api.h" #include "internal_include/bt_target.h" +#include "main/shim/dumpsys.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_psm_types.h" @@ -434,3 +435,37 @@ uint16_t AVCT_MsgReq(uint8_t handle, uint8_t label, uint8_t cr, BT_HDR* p_msg) { } return result; } + +#define DUMPSYS_TAG "stack::avct" + +void AVCT_Dumpsys(int fd) { + LOG_DUMPSYS_TITLE(fd, DUMPSYS_TAG); + for (int i = 0; i < AVCT_NUM_CONN; i++) { + const tAVCT_CCB& ccb = avct_cb.ccb[i]; + if (!ccb.allocated) { + continue; + } + LOG_DUMPSYS(fd, " Id:%2u profile_uuid:0x%04x role:%s control:0x%2x", i, ccb.cc.pid, + avct_role_text(ccb.cc.role).c_str(), ccb.cc.control); + if (ccb.p_lcb) { // tAVCT_LCB + LOG_DUMPSYS(fd, + " Link : peer:%s lcid:0x%04x sm_state:%-24s ch_state:%s conflict_lcid:0x%04x", + fmt::format("{}", ccb.p_lcb->peer_addr).c_str(), ccb.p_lcb->ch_lcid, + avct_sm_state_text(ccb.p_lcb->state).c_str(), + avct_ch_state_text(ccb.p_lcb->ch_state).c_str(), ccb.p_lcb->conflict_lcid); + } else { + LOG_DUMPSYS(fd, " Link : No link channel"); + } + + if (ccb.p_bcb) { // tAVCT_BCB + LOG_DUMPSYS(fd, + " Browse: peer:%s lcid:0x%04x sm_state:%-24s ch_state:%s conflict_lcid:0x%04x", + fmt::format("{}", ccb.p_bcb->peer_addr).c_str(), ccb.p_bcb->ch_lcid, + avct_sm_state_text(ccb.p_bcb->state).c_str(), + avct_ch_state_text(ccb.p_bcb->ch_state).c_str(), ccb.p_bcb->conflict_lcid); + } else { + LOG_DUMPSYS(fd, " Browse: No browse channel"); + } + } +} +#undef DUMPSYS_TAG diff --git a/system/stack/include/avct_api.h b/system/stack/include/avct_api.h index 0cf58171baa..3693cdcd0fe 100644 --- a/system/stack/include/avct_api.h +++ b/system/stack/include/avct_api.h @@ -280,4 +280,18 @@ uint16_t AVCT_GetPeerMtu(uint8_t handle); ******************************************************************************/ uint16_t AVCT_MsgReq(uint8_t handle, uint8_t label, uint8_t cr, BT_HDR* p_msg); +/******************************************************************************* +** +** Function AVCT_Dumpsys +** +** Description This function provides dumpsys data during the dumpsys +** procedure. +** +** Parameters: fd: Descriptor used to write the AVCT internals +** +** Returns void +** +*******************************************************************************/ +void AVCT_Dumpsys(int fd); + #endif /* AVCT_API_H */ diff --git a/system/test/mock/mock_stack_avct_api.cc b/system/test/mock/mock_stack_avct_api.cc index a63348f30c3..2e88b66e841 100644 --- a/system/test/mock/mock_stack_avct_api.cc +++ b/system/test/mock/mock_stack_avct_api.cc @@ -56,3 +56,4 @@ uint16_t AVCT_RemoveConn(uint8_t /* handle */) { } void AVCT_Deregister(void) { inc_func_call_count(__func__); } void AVCT_Register() { inc_func_call_count(__func__); } +void AVCT_Dumpsys(int /* fd */) { inc_func_call_count(__func__); } -- GitLab From 55d15d0065658e64a161ab9b99733536da8fd482 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Thu, 24 Oct 2024 17:41:27 +0000 Subject: [PATCH 428/875] CS: Set tone_antenna_config_selection based on property Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 375165953 Test: m com.android.btservice Change-Id: I79886a8cddaa2c7e8b9e080b436ae1168bc9b1e4 --- system/gd/hci/distance_measurement_manager.cc | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index e0039153484..ab39d5970bf 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -62,14 +62,12 @@ static constexpr uint16_t kMaxProcedureInterval = 0xFF; static constexpr uint16_t kMaxProcedureCount = 0x01; static constexpr uint32_t kMinSubeventLen = 0x0004E2; // 1250us static constexpr uint32_t kMaxSubeventLen = 0x3d0900; // 4s -static constexpr uint8_t kToneAntennaConfigSelection = 0x00; // 1x1 static constexpr uint8_t kTxPwrDelta = 0x00; static constexpr uint8_t kProcedureDataBufferSize = 0x10; // Buffer size of Procedure data static constexpr uint16_t kMtuForRasData = 507; // 512 - 5 static constexpr uint16_t kRangingCounterMask = 0x0FFF; static constexpr uint8_t kInvalidConfigId = 0xFF; static constexpr uint16_t kDefaultIntervalMs = 1000; // 1s -static constexpr uint8_t kPreferredPeerAntennaValue = 0x01; // Use first ordered antenna element static constexpr uint8_t kMaxRetryCounterForCreateConfig = 0x03; struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { @@ -173,6 +171,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { CsSubModeType sub_mode_type = CsSubModeType::UNUSED; CsRttType rtt_type = CsRttType::RTT_AA_ONLY; bool remote_support_phase_based_ranging = false; + uint8_t remote_num_antennas_supported_ = 0x01; uint8_t config_id = kInvalidConfigId; uint8_t selected_tx_power = 0; std::vector procedure_data_list = {}; @@ -624,20 +623,31 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle)); } - void send_le_cs_set_procedure_parameters(uint16_t connection_handle, uint8_t config_id) { + void send_le_cs_set_procedure_parameters(uint16_t connection_handle, uint8_t config_id, + uint8_t remote_num_antennas_supported) { + uint8_t tone_antenna_config_selection = + cs_tone_antenna_config_mapping_table_[num_antennas_supported_] + [remote_num_antennas_supported]; + uint8_t preferred_peer_antenna_value = + cs_preferred_peer_antenna_mapping_table_[tone_antenna_config_selection]; + log::info( + "num_antennas_supported:{}, remote_num_antennas_supported:{}, " + "tone_antenna_config_selection:{}, preferred_peer_antenna:{}", + num_antennas_supported_, remote_num_antennas_supported, tone_antenna_config_selection, + preferred_peer_antenna_value); CsPreferredPeerAntenna preferred_peer_antenna; - preferred_peer_antenna.use_first_ordered_antenna_element_ = kPreferredPeerAntennaValue & 0x01; + preferred_peer_antenna.use_first_ordered_antenna_element_ = preferred_peer_antenna_value & 0x01; preferred_peer_antenna.use_second_ordered_antenna_element_ = - (kPreferredPeerAntennaValue >> 1) & 0x01; + (preferred_peer_antenna_value >> 1) & 0x01; preferred_peer_antenna.use_third_ordered_antenna_element_ = - (kPreferredPeerAntennaValue >> 2) & 0x01; + (preferred_peer_antenna_value >> 2) & 0x01; preferred_peer_antenna.use_fourth_ordered_antenna_element_ = - (kPreferredPeerAntennaValue >> 3) & 0x01; + (preferred_peer_antenna_value >> 3) & 0x01; hci_layer_->EnqueueCommand( LeCsSetProcedureParametersBuilder::Create( connection_handle, config_id, kMaxProcedureLen, kMinProcedureInterval, kMaxProcedureInterval, kMaxProcedureCount, kMinSubeventLen, kMaxSubeventLen, - kToneAntennaConfigSelection, CsPhy::LE_1M_PHY, kTxPwrDelta, + tone_antenna_config_selection, CsPhy::LE_1M_PHY, kTxPwrDelta, preferred_peer_antenna, CsSnrControl::NOT_APPLIED, CsSnrControl::NOT_APPLIED), handler_->BindOnceOn(this, &impl::on_cs_set_procedure_parameters)); } @@ -731,6 +741,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } cs_subfeature_supported_ = complete_view.GetOptionalSubfeaturesSupported(); + num_antennas_supported_ = complete_view.GetNumAntennasSupported(); } void on_cs_read_remote_supported_capabilities_complete( @@ -758,6 +769,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (req_it != cs_requester_trackers_.end() && req_it->second.measurement_ongoing) { req_it->second.remote_support_phase_based_ranging = event_view.GetOptionalSubfeaturesSupported().phase_based_ranging_ == 0x01; + req_it->second.remote_num_antennas_supported_ = event_view.GetNumAntennasSupported(); req_it->second.setup_complete = true; log::info("Setup phase complete, connection_handle: {}, address: {}", connection_handle, cs_requester_trackers_[connection_handle].address); @@ -805,7 +817,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { !req_it->second.config_set) { req_it->second.config_set = true; send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), - req_it->second.config_id); + req_it->second.config_id, + req_it->second.remote_num_antennas_supported_); } auto res_it = cs_responder_trackers_.find(connection_handle); if (res_it != cs_responder_trackers_.end() && @@ -1774,6 +1787,13 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { std::unordered_map cs_responder_trackers_; DistanceMeasurementCallbacks* distance_measurement_callbacks_; CsOptionalSubfeaturesSupported cs_subfeature_supported_; + uint8_t num_antennas_supported_ = 0x01; + // A table that maps num_antennas_supported and remote_num_antennas_supported to Antenna + // Configuration Index. + uint8_t cs_tone_antenna_config_mapping_table_[4][4] = { + {0, 4, 5, 6}, {1, 7, 7, 7}, {2, 7, 7, 7}, {3, 7, 7, 7}}; + // A table that maps Antenna Configuration Index to Preferred Peer Antenna. + uint8_t cs_preferred_peer_antenna_mapping_table_[8] = {1, 1, 1, 1, 3, 7, 15, 3}; // Antenna path permutations. See Channel Sounding CR_PR for the details. uint8_t cs_antenna_permutation_array_[24][4] = { {1, 2, 3, 4}, {2, 1, 3, 4}, {1, 3, 2, 4}, {3, 1, 2, 4}, {3, 2, 1, 4}, {2, 3, 1, 4}, -- GitLab From 39fbe60367e7a7d3e3dcc59267bb21bad3a3d16a Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Thu, 24 Oct 2024 17:59:44 +0000 Subject: [PATCH 429/875] flags: leaudio_broadcast_primary_group_selection Fix race condition in primary group selection Bug: 375422795 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: Ic87fb3d40b72da6e275346ee02edd2db8ee8da94 --- flags/leaudio.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 02361f1b6bd..2d94566cfbe 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -391,3 +391,13 @@ flag { description: "API to get and set microphone for call enable status" bug: "372395197" } + +flag { + name: "leaudio_broadcast_primary_group_selection" + namespace: "bluetooth" + description: "Fix race condition in primary group selection" + bug: "375422795" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From d418570b60cdfc0a8646d3a20b548ad7aecd2365 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Thu, 24 Oct 2024 18:07:31 +0000 Subject: [PATCH 430/875] flags: leaudio_broadcast_api_get_local_metadata API to get broadcast assistant local metadata Bug: 375423982 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: Ib7c8d889be64af77eb2dcdc1cb7a18aa2ea59e3a --- flags/leaudio.aconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 2d94566cfbe..8f70fa4fff5 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -401,3 +401,11 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "leaudio_broadcast_api_get_local_metadata" + is_exported: true + namespace: "bluetooth" + description: "API to get broadcast assistant local metadata" + bug: "375423982" +} -- GitLab From 90fec2b308687daddf6f75d023b11b41673d5656 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Thu, 24 Oct 2024 18:10:12 +0000 Subject: [PATCH 431/875] flags: leaudio_broadcast_api_manage_primary_group API to manage broadcast primary group Bug: 375422410 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: I722b44c3818d174d86300b72321fb2c57a1280e1 --- flags/leaudio.aconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 8f70fa4fff5..346c3ba1548 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -409,3 +409,11 @@ flag { description: "API to get broadcast assistant local metadata" bug: "375423982" } + +flag { + name: "leaudio_broadcast_api_manage_primary_group" + is_exported: true + namespace: "bluetooth" + description: "API to manage broadcast primary group" + bug: "375422410" +} -- GitLab From fc46160cd91d20d5eb71160d40850052cb1faf71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Paw=C5=82owski?= Date: Thu, 24 Oct 2024 20:22:34 +0000 Subject: [PATCH 432/875] Revert "Revert "Make it obvious that connection_manager is separ..." Revert submission 3316623-revert-3315276-VNGBAEHITV Reason for revert: TEST_MAPPING file was not updated Reverted changes: /q/submissionid:3316623-revert-3315276-VNGBAEHITV Change-Id: Ie44ca77a1a9316dd0692335b22cc06bef8d76fb9 --- system/bta/Android.bp | 1 + system/bta/dm/bta_dm_act.cc | 2 +- system/btif/src/bluetooth.cc | 2 +- system/stack/Android.bp | 15 +++++++++------ system/stack/BUILD.gn | 2 +- system/stack/acl/ble_acl.cc | 2 +- system/stack/btm/btm_devctl.cc | 2 +- .../connection_manager.cc | 0 .../connection_manager.h | 0 system/stack/gatt/gatt_api.cc | 2 +- system/stack/gatt/gatt_main.cc | 2 +- system/stack/gatt/gatt_utils.cc | 2 +- system/stack/l2cap/l2c_ble.cc | 2 +- ...manager_test.cc => connection_manager_test.cc} | 3 ++- system/stack/test/gatt/mock_gatt_utils_ref.cc | 2 +- system/test/Android.bp | 7 +++++++ system/test/headless/bt_stack_info.cc | 2 +- ...anager.cc => mock_stack_connection_manager.cc} | 8 +++++++- 18 files changed, 37 insertions(+), 19 deletions(-) rename system/stack/{gatt => connection_manager}/connection_manager.cc (100%) rename system/stack/{gatt => connection_manager}/connection_manager.h (100%) rename system/stack/test/{gatt_connection_manager_test.cc => connection_manager_test.cc} (99%) rename system/test/mock/{mock_stack_gatt_connection_manager.cc => mock_stack_connection_manager.cc} (92%) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 9bfe5f6d7e0..4ffce6907d6 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -260,6 +260,7 @@ cc_test { ":TestMockStackAvdt", ":TestMockStackAvrc", ":TestMockStackBtm", + ":TestMockStackConnMgr", ":TestMockStackGap", ":TestMockStackGatt", ":TestMockStackHid", diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 1d1d5c589de..792aa44b6e3 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -52,7 +52,7 @@ #include "main/shim/entry.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index d47c29978e3..c4bb371e80a 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -100,7 +100,7 @@ #include "osi/include/wakelock.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sco_hfp_hal.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/a2dp_api.h" #include "stack/include/avct_api.h" #include "stack/include/avdt_api.h" diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 5fec9d2cee2..1161cae7ca5 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -275,11 +275,11 @@ cc_library_static { "btm/security_event_parser.cc", "btu/btu_event.cc", "btu/btu_hcif.cc", + "connection_manager/connection_manager.cc", "eatt/eatt.cc", "gap/gap_ble.cc", "gap/gap_conn.cc", "gatt/att_protocol.cc", - "gatt/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", @@ -540,6 +540,7 @@ cc_fuzz { ":TestMockStackAcl", ":TestMockStackArbiter", ":TestMockStackBtm", + ":TestMockStackConnMgr", ":TestMockStackHcic", ":TestMockStackL2cap", ":TestMockStackMetrics", @@ -1067,7 +1068,7 @@ cc_test { // Bluetooth stack connection multiplexing cc_test { - name: "net_test_gatt_conn_multiplexing", + name: "net_test_conn_multiplexing", defaults: [ "fluoride_defaults", "mts_defaults", @@ -1086,9 +1087,9 @@ cc_test { srcs: [ ":TestCommonMainHandler", ":TestMockStackBtmInterface", - "gatt/connection_manager.cc", + "connection_manager/connection_manager.cc", "test/common/mock_btm_api_layer.cc", - "test/gatt_connection_manager_test.cc", + "test/connection_manager_test.cc", ], shared_libs: [ "libcutils", @@ -1652,6 +1653,7 @@ cc_test { ":TestMockMainShimEntry", ":TestMockRustFfi", ":TestMockStackBtu", + ":TestMockStackConnMgr", ":TestMockStackGap", ":TestMockStackGatt", ":TestMockStackHcic", @@ -1972,9 +1974,9 @@ cc_test { ":TestMockStackSmp", "ais/ais_ble.cc", "arbiter/acl_arbiter.cc", + "connection_manager/connection_manager.cc", "eatt/eatt.cc", "gatt/att_protocol.cc", - "gatt/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", @@ -2067,7 +2069,7 @@ cc_test { ":TestMockMainShimEntry", ":TestMockStackAcl", ":TestMockStackBtm", - ":TestMockStackGatt", + ":TestMockStackConnMgr", ":TestMockStackHcic", ":TestMockStackSdp", ":TestMockStackSmp", @@ -2164,6 +2166,7 @@ cc_test { ":TestMockRustFfi", ":TestMockStackBtm", ":TestMockStackBtu", + ":TestMockStackConnMgr", ":TestMockStackGatt", ":TestMockStackHcic", ":TestMockStackL2cap", diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn index c2b87b44a55..559aa1f366c 100644 --- a/system/stack/BUILD.gn +++ b/system/stack/BUILD.gn @@ -125,7 +125,7 @@ source_set("stack") { "gap/gap_ble.cc", "gap/gap_conn.cc", "gatt/att_protocol.cc", - "gatt/connection_manager.cc", + "connection_manager/connection_manager.cc", "gatt/gatt_api.cc", "gatt/gatt_attr.cc", "gatt/gatt_auth.cc", diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index 1f5d5b580c3..0606716f757 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -25,7 +25,7 @@ #include "stack/btm/btm_dev.h" #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/btm_ble_addr.h" #include "stack/include/btm_ble_privacy.h" diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc index 86f4af00e4b..d22fba73c77 100644 --- a/system/stack/btm/btm_devctl.cc +++ b/system/stack/btm/btm_devctl.cc @@ -38,7 +38,7 @@ #include "main/shim/entry.h" #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/acl_api_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/gatt/connection_manager.cc b/system/stack/connection_manager/connection_manager.cc similarity index 100% rename from system/stack/gatt/connection_manager.cc rename to system/stack/connection_manager/connection_manager.cc diff --git a/system/stack/gatt/connection_manager.h b/system/stack/connection_manager/connection_manager.h similarity index 100% rename from system/stack/gatt/connection_manager.h rename to system/stack/connection_manager/connection_manager.h diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index d9d7f051d95..7ed0fe05160 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -37,7 +37,7 @@ #include "osi/include/allocator.h" #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/gatt/gatt_int.h" #include "stack/include/ais_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index bc559a5715c..f5591d21948 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -28,7 +28,6 @@ #include "btif/include/btif_dm.h" #include "btif/include/btif_storage.h" #include "btif/include/stack_manager_t.h" -#include "connection_manager.h" #include "device/include/interop.h" #include "internal_include/bt_target.h" #include "internal_include/stack_config.h" @@ -38,6 +37,7 @@ #include "stack/arbiter/acl_arbiter.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/eatt/eatt.h" #include "stack/gatt/gatt_int.h" #include "stack/include/acl_api.h" diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index 72083acb500..d159bbd794a 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -38,8 +38,8 @@ #include "osi/include/properties.h" #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/eatt/eatt.h" -#include "stack/gatt/connection_manager.h" #include "stack/gatt/gatt_int.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_psm_types.h" diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index a00e0d17f46..fe22262b89a 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -44,7 +44,7 @@ #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sec.h" #include "stack/btm/btm_sec_int_types.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" diff --git a/system/stack/test/gatt_connection_manager_test.cc b/system/stack/test/connection_manager_test.cc similarity index 99% rename from system/stack/test/gatt_connection_manager_test.cc rename to system/stack/test/connection_manager_test.cc index afe3fcba4e8..cbb7b3ff35d 100644 --- a/system/stack/test/gatt_connection_manager_test.cc +++ b/system/stack/test/connection_manager_test.cc @@ -1,3 +1,5 @@ +#include "stack/connection_manager/connection_manager.h" + #include #include #include @@ -11,7 +13,6 @@ #include "osi/test/alarm_mock.h" #include "security_device_record.h" #include "stack/btm/neighbor_inquiry.h" -#include "stack/gatt/connection_manager.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc index f79db0ac3d8..2f392b3e90a 100644 --- a/system/stack/test/gatt/mock_gatt_utils_ref.cc +++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc @@ -22,7 +22,7 @@ #pragma GCC diagnostic ignored "-Wmissing-prototypes" #pragma GCC diagnostic ignored "-Wunused-parameter" -/** stack/gatt/connection_manager.cc */ +/** stack/connection_manager/connection_manager.cc */ namespace connection_manager { bool background_connect_remove(uint8_t app_id, const RawAddress& address) { return false; } bool direct_connect_remove(uint8_t app_id, const RawAddress& address, bool connection_timeout) { diff --git a/system/test/Android.bp b/system/test/Android.bp index a78ed4e8ef8..d4a1a767eb8 100644 --- a/system/test/Android.bp +++ b/system/test/Android.bp @@ -483,6 +483,13 @@ filegroup { ], } +filegroup { + name: "TestMockStackConnMgr", + srcs: [ + "mock/mock_stack_connection_manager.cc", + ], +} + filegroup { name: "TestMockStackEatt", srcs: [ diff --git a/system/test/headless/bt_stack_info.cc b/system/test/headless/bt_stack_info.cc index ad00ba5c6b5..300dbf62b78 100644 --- a/system/test/headless/bt_stack_info.cc +++ b/system/test/headless/bt_stack_info.cc @@ -21,7 +21,7 @@ #include "btif/include/btif_common.h" // do_in_jni_thread #include "btif/include/btif_hh.h" // DumpsysHid #include "main/shim/dumpsys.h" -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "stack/include/main_thread.h" #include "stack/include/pan_api.h" // PAN_Dumpsys #include "test/headless/log.h" diff --git a/system/test/mock/mock_stack_gatt_connection_manager.cc b/system/test/mock/mock_stack_connection_manager.cc similarity index 92% rename from system/test/mock/mock_stack_gatt_connection_manager.cc rename to system/test/mock/mock_stack_connection_manager.cc index f0f33dddb5e..97cd1608548 100644 --- a/system/test/mock/mock_stack_gatt_connection_manager.cc +++ b/system/test/mock/mock_stack_connection_manager.cc @@ -21,12 +21,18 @@ #include -#include "stack/gatt/connection_manager.h" +#include "stack/connection_manager/connection_manager.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" using namespace connection_manager; +bool connection_manager::background_connect_targeted_announcement_add( + tAPP_ID /* app_id */, const RawAddress& /* address */) { + inc_func_call_count(__func__); + return false; +} + bool connection_manager::background_connect_add(uint8_t /* app_id */, const RawAddress& /* address */) { inc_func_call_count(__func__); -- GitLab From 3210dbfcbb56828bc4bd0ad51e5223221d249781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Paw=C5=82owski?= Date: Thu, 24 Oct 2024 20:22:34 +0000 Subject: [PATCH 433/875] Revert^2 "Make connection_manager dumpsys more concise" 2b3c47056b7a605d29225388674f35d0a2ab11d2 Change-Id: I9b5c08162709f583b0304b2fde66d16e25a09013 --- .../stack/connection_manager/connection_manager.cc | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/system/stack/connection_manager/connection_manager.cc b/system/stack/connection_manager/connection_manager.cc index 96278a91064..c29ac5d4031 100644 --- a/system/stack/connection_manager/connection_manager.cc +++ b/system/stack/connection_manager/connection_manager.cc @@ -581,7 +581,10 @@ void dump(int fd) { dprintf(fd, "\tdevices attempting connection: %d", (int)bgconn_dev.size()); for (const auto& entry : bgconn_dev) { // TODO: confirm whether we need to replace this - dprintf(fd, "\n\t * %s: ", ADDRESS_TO_LOGGABLE_CSTR(entry.first)); + dprintf(fd, "\n\t * %s:\t\tin_accept_list: %s\t cap_targeted_announcements: %s", + ADDRESS_TO_LOGGABLE_CSTR(entry.first), + entry.second.is_in_accept_list ? "true" : "false", + entry.second.doing_targeted_announcements_conn.empty() ? "false" : "true"); if (!entry.second.doing_direct_conn.empty()) { dprintf(fd, "\n\t\tapps doing direct connect: "); @@ -596,14 +599,6 @@ void dump(int fd) { dprintf(fd, "%d, ", id); } } - if (!entry.second.doing_targeted_announcements_conn.empty()) { - dprintf(fd, "\n\t\tapps doing cap announcement connect: "); - for (const auto& id : entry.second.doing_targeted_announcements_conn) { - dprintf(fd, "%d, ", id); - } - } - dprintf(fd, "\n\t\t is in the allow list: %s", - entry.second.is_in_accept_list ? "true" : "false"); } dprintf(fd, "\n"); } -- GitLab From a9e06b35ba40e952ae86185b71d16a176f4abc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Paw=C5=82owski?= Date: Thu, 24 Oct 2024 20:29:25 +0000 Subject: [PATCH 434/875] Fix test mapping for net_test_conn_multiplexing Test: mma -j32 Bug: 372202918 Flag: EXEMPT, fixing tests Change-Id: If0ea276dca4a0bc7b560aa33c7fcd6b2e77f45b8 --- TEST_MAPPING | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index 5f21a9b8008..82cbc974ab1 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -56,7 +56,7 @@ "name": "net_test_device_iot_config" }, { - "name": "net_test_gatt_conn_multiplexing" + "name": "net_test_conn_multiplexing" }, { "name": "net_test_hci" @@ -251,7 +251,7 @@ "name": "net_test_device_iot_config" }, { - "name": "net_test_gatt_conn_multiplexing" + "name": "net_test_conn_multiplexing" }, { "name": "net_test_stack" -- GitLab From c2d0aa2c33f54da0faf24f1677542d5a900c9a92 Mon Sep 17 00:00:00 2001 From: Palash Ahuja Date: Thu, 24 Oct 2024 11:04:11 -0700 Subject: [PATCH 435/875] Adding the state transition for BOND_NONE state in the native layer Test: m statsd_testdrive && pair/unpair with remote device Bug: 375437118 Flag: EXEMPT, metrics related changes Change-Id: Ied58dc70c4cb3716767eafd267d3df1bc6eaa199 --- system/btif/src/btif_dm.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index be251acca8e..118aa5eba60 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -564,6 +564,12 @@ static void bond_state_changed(bt_status_t status, const RawAddress& bd_addr, if (pairing_cb.bond_type == BOND_TYPE_TEMPORARY) { state = BT_BOND_STATE_NONE; + } else { + if (state == BT_BOND_STATE_NONE) { + bluetooth::os::LogMetricBluetoothEvent(ToGdAddress(bd_addr), + android::bluetooth::EventType::BOND, + android::bluetooth::State::STATE_NONE); + } } log::info( -- GitLab From 0f5ceefd872176bfea6418a9d1f6be57926eba6f Mon Sep 17 00:00:00 2001 From: Billy Huang Date: Thu, 24 Oct 2024 13:33:35 -0700 Subject: [PATCH 436/875] Declare opp_check_content_uri_permissions flag Flag: com.android.bluetooth.flags.opp_check_content_uri_permissions Ignore-AOSP-First: Security fix Test: m com.google.android.btservices Bug: 375466974 Bug: 315241296 Change-Id: I22711856821004ca737f6b3b5b00bcb2d155db6f --- flags/security.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/security.aconfig b/flags/security.aconfig index 5a8b5791f19..26a7fefeb06 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -75,3 +75,13 @@ flag { } } + +flag { + name: "opp_check_content_uri_permissions" + namespace: "bluetooth" + description: "Check that the launching application for OPP has read access to the given content URI, on Android V+" + bug: "375466974" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From d491e96522b7e1445b73a015d571b4799acabef4 Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Thu, 24 Oct 2024 08:39:51 -0700 Subject: [PATCH 437/875] stack::avct::avct_l2c_connect_ind_cback Fix warning log Bug: 375407443 Test: m . Flag: EXEMPT, Null pointer dereference Change-Id: I675bb944a6105088bba5bfd0954ae2139c4662fc --- system/stack/avct/avct_l2c.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/system/stack/avct/avct_l2c.cc b/system/stack/avct/avct_l2c.cc index ffb3a64d3a9..e3001eeaa28 100644 --- a/system/stack/avct/avct_l2c.cc +++ b/system/stack/avct/avct_l2c.cc @@ -148,19 +148,18 @@ void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16 /* transition to configuration state */ p_lcb->ch_state = AVCT_CH_CFG; + + log::debug("Received remote connection request peer:{} lcid:0x{:04x} ch_state:{}", bd_addr, + lcid, avct_ch_state_text(p_lcb->ch_state)); } else { /* If we reject the connection, send DisconnectReq */ if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { log::warn("Unable to send L2CAP disconnect request peer:{} lcid:0x{:04x}", bd_addr, lcid); } - } - - if (p_lcb) { - log::debug("Received remote connection request peer:{} lcid:0x{:04x} res:{} ch_state:{}", - bd_addr, lcid, l2cap_result_code_text(result), avct_ch_state_text(p_lcb->ch_state)); - } else { - log::info("Ignoring remote connection request peer:{} lcid:0x{:04x} res:{} ch_state:{}", - bd_addr, lcid, l2cap_result_code_text(result), avct_ch_state_text(p_lcb->ch_state)); + log::info( + "Ignoring remote connection request no link or no resources peer:{} lcid:0x{:04x} " + "lcb_exists:{}", + bd_addr, lcid, p_lcb != nullptr); } } -- GitLab From e13ca783ee3c77a120be6976cac4eb3c31af875e Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Tue, 22 Oct 2024 11:19:13 -0700 Subject: [PATCH 438/875] stack::avct: Add net_test_stack_avctp Bug: 375001501 Test: atest net_test_stack_avctp Flag: EXEMPT, Testing Infrastructure Change-Id: I1b140cb61e86b15d345a3a1c548db316d5ff32bf --- TEST_MAPPING | 3 + system/btif/Android.bp | 2 - system/stack/Android.bp | 70 ++++++++++++++ system/stack/avct/avct_api.cc | 10 +- system/stack/test/stack_avctp_test.cc | 128 ++++++++++++++++++++++++++ 5 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 system/stack/test/stack_avctp_test.cc diff --git a/TEST_MAPPING b/TEST_MAPPING index 5f21a9b8008..425f18826a8 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -319,6 +319,9 @@ { "name": "net_test_bta_jv" }, + { + "name": "net_test_stack_avctp" + }, { "name": "asrc_resampler_test" } diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 9b22ee4784e..2d3d40e3fd2 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -597,8 +597,6 @@ cc_test { "libbt-platform-protos-lite", "libbt-sbc-decoder", "libbt-sbc-encoder", - "libbt-stack", - "libbt-stack-core", "libbtdevice", "libbtif", "libbtif-core", diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 5fec9d2cee2..b739ce27328 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -1179,6 +1179,76 @@ cc_test { header_libs: ["libbluetooth_headers"], } +cc_test { + name: "net_test_stack_avctp", + defaults: [ + "fluoride_defaults", + "mts_defaults", + ], + test_suites: ["general-tests"], + host_supported: true, + test_options: { + unit_test: true, + }, + include_dirs: [ + "external/libldac/inc", + "packages/modules/Bluetooth/system", + "packages/modules/Bluetooth/system/gd", + "packages/modules/Bluetooth/system/stack/include", + ], + srcs: [ + ":TestCommonMockFunctions", + ":TestFakeOsi", + ":TestMockBta", + ":TestMockBtif", + ":TestMockDevice", + ":TestMockStackA2dp", + ":TestMockStackAcl", + ":TestMockStackL2cap", + "avct/avct_api.cc", + "avct/avct_bcb_act.cc", + "avct/avct_ccb.cc", + "avct/avct_l2c.cc", + "avct/avct_l2c_br.cc", + "avct/avct_lcb.cc", + "avct/avct_lcb_act.cc", + "test/stack_avctp_test.cc", + ], + shared_libs: [ + "libcrypto", + "libcutils", + "server_configurable_flags", + ], + static_libs: [ + "bluetooth_flags_c_lib_for_test", + "libaconfig_storage_read_api_cc", + "libbase", + "libbluetooth-types", + "libbluetooth_crypto_toolbox", + "libbluetooth_gd", + "libbluetooth_log", + "libbt-common", + "libchrome", + "libevent", + "libgmock", + "liblog", + "libosi", + "libprotobuf-cpp-lite", + "libstatslog_bt", + ], + target: { + android: { + shared_libs: ["libstatssocket"], + }, + }, + sanitize: { + address: true, + cfi: true, + misc_undefined: ["bounds"], + }, + header_libs: ["libbluetooth_headers"], +} + cc_test { name: "net_test_stack_avdtp", defaults: [ diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index 70efdee0c22..d4a6aab45eb 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -28,11 +28,12 @@ #include #include -#include "avct_int.h" #include "bta/include/bta_sec_api.h" #include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" #include "osi/include/allocator.h" +#include "stack/avct/avct_int.h" +#include "stack/include/avct_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_psm_types.h" #include "stack/include/l2cap_interface.h" @@ -109,6 +110,13 @@ void AVCT_Deregister(void) { /* deregister AVCT_BR_PSM with L2CAP */ stack::l2cap::get_interface().L2CA_Deregister(BT_PSM_AVCTP_BROWSE); + + // Clean up AVCTP data structures + for (int i = 0; i < AVCT_NUM_LINKS; i++) { + osi_free(avct_cb.lcb[i].p_rx_msg); + fixed_queue_free(avct_cb.lcb[i].tx_q, nullptr); + osi_free_and_reset((void**)&(avct_cb.bcb[i].p_tx_msg)); + } } /******************************************************************************* diff --git a/system/stack/test/stack_avctp_test.cc b/system/stack/test/stack_avctp_test.cc new file mode 100644 index 00000000000..17abac13c6d --- /dev/null +++ b/system/stack/test/stack_avctp_test.cc @@ -0,0 +1,128 @@ +/* + * 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. + */ + +#include +#include +#include + +#include "stack/include/avct_api.h" +#include "stack/include/bt_psm_types.h" +#include "test/fake/fake_osi.h" +#include "test/mock/mock_stack_l2cap_interface.h" + +using ::testing::_; +using ::testing::Args; +using ::testing::DoAll; +using ::testing::SaveArg; + +namespace { +constexpr uint16_t kRemoteCid = 0x0123; +const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); +} // namespace + +class StackAvctpTest : public ::testing::Test { +protected: + void SetUp() override { + fake_osi_ = std::make_unique<::test::fake::FakeOsi>(); + bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_); + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _)) + .WillRepeatedly([this](unsigned short psm, const tL2CAP_APPL_INFO& cb, bool /* c */, + tL2CAP_ERTM_INFO* /*d*/, unsigned short /* e */, + unsigned short /* f */, unsigned short /* g */) { + this->callback_map_.insert(std::make_tuple(psm, cb)); + return psm; + }); + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(_)).WillRepeatedly([]() { + return true; + }); + AVCT_Register(); + // Make sure we have a callback for both PSMs + ASSERT_EQ(2U, callback_map_.size()); + } + + void TearDown() override { + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP)); + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE)); + AVCT_Deregister(); + } + + std::map callback_map_; + bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_; + std::unique_ptr fake_osi_; + int fd_{STDOUT_FILENO}; +}; + +TEST_F(StackAvctpTest, AVCT_Dumpsys) { AVCT_Dumpsys(fd_); } + +TEST_F(StackAvctpTest, AVCT_CreateConn) { + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _)) + .WillRepeatedly([](unsigned short /* psm */, const RawAddress /* bd_addr */, + uint16_t /* sec_level */) { return 0x1234; }); + + uint8_t handle; + tAVCT_CC cc = { + .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */, + const RawAddress* /* peer_addr */) {}, + .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */, + BT_HDR* /* p_pkt */) {}, + .pid = 0x1234, + .role = AVCT_ROLE_INITIATOR, + .control = 1, + }; + ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress)); + ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle)); +} + +TEST_F(StackAvctpTest, AVCT_CreateBrowse) { + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _)) + .WillRepeatedly([](unsigned short /* psm */, const RawAddress /* bd_addr */, + uint16_t /* sec_level */) { return 0x1234; }); + + uint8_t handle; + tAVCT_CC cc = { + .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */, + const RawAddress* /* peer_addr */) {}, + .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */, + BT_HDR* /* p_pkt */) {}, + .pid = 0x1234, + .role = AVCT_ROLE_INITIATOR, + .control = 1, + }; + ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress)); + ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateBrowse(handle, AVCT_ROLE_INITIATOR)); + + ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveBrowse(handle)); + ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle)); +} + +TEST_F(StackAvctpTest, AVCT_RemoteInitiatesControl) { + // AVCT Control + callback_map_[BT_PSM_AVCTP].pL2CA_ConnectInd_Cb(kRawAddress, kRemoteCid, BT_PSM_AVCTP, 0); + callback_map_[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK); +} + +TEST_F(StackAvctpTest, AVCT_RemoteInitiatesBrowse) { + // AVCT Control + callback_map_[BT_PSM_AVCTP].pL2CA_ConnectInd_Cb(kRawAddress, kRemoteCid, BT_PSM_AVCTP, 0); + callback_map_[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK); + + // AVCT Browse + callback_map_[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectInd_Cb(kRawAddress, kRemoteCid, + BT_PSM_AVCTP_BROWSE, 0); + callback_map_[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK); + + AVCT_Dumpsys(fd_); +} -- GitLab From 188a23d1906abc9df3a3dc7276b2edd694be8645 Mon Sep 17 00:00:00 2001 From: Suqun Peng Date: Wed, 16 Oct 2024 14:05:47 +0800 Subject: [PATCH 439/875] ACL: Switch to GD thread to prevent race condition of accessing map ACL_ReadConnectionAddress(), ACL_ReadPeerConnectionAddress() and ACL_GetAdvertisingSetConnectedTo() are invoked in bt_main_thread/ bt_jni_thread, they iterate le_connection_map, but gd_stack_thread will modify the map when LE link connects or disconnects. Post tasks to GD thread to prevent race condition of accessing map Bug: 373764860 Test: m com.android.btservices Change-Id: Idfd05af0d01725e56ec53ab9525d370fbd5c644d --- system/main/shim/acl.cc | 112 ++++++++++++++++--------- system/main/shim/acl.h | 9 +- system/main/shim/acl_api.cc | 18 ++-- system/test/mock/mock_main_shim_acl.cc | 17 ++-- 4 files changed, 100 insertions(+), 56 deletions(-) diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc index 7f33da446fa..1c6ee6ded95 100644 --- a/system/main/shim/acl.cc +++ b/system/main/shim/acl.cc @@ -1050,6 +1050,63 @@ struct shim::Acl::impl { "Le"); } + void get_connection_local_address(uint16_t handle, bool ota_address, + std::promise promise) { + log::debug("get_connection_local_address handle:{} ota_address:{}", handle, ota_address); + bluetooth::hci::AddressWithType address_with_type; + for (auto& [acl_handle, connection] : handle_to_le_connection_map_) { + if (acl_handle != handle) { + continue; + } + + if (ota_address) { + promise.set_value(connection->GetLocalOtaAddressWithType()); + return; + } + promise.set_value(connection->GetLocalAddressWithType()); + return; + } + log::warn("address not found!"); + promise.set_value(address_with_type); + return; + } + + void get_connection_peer_address(uint16_t handle, bool ota_address, + std::promise promise) { + log::debug("get_connection_peer_address handle:{} ota_address:{}", handle, ota_address); + bluetooth::hci::AddressWithType address_with_type; + for (auto& [acl_handle, connection] : handle_to_le_connection_map_) { + if (acl_handle != handle) { + continue; + } + + if (ota_address) { + promise.set_value(connection->GetPeerOtaAddressWithType()); + return; + } + promise.set_value(connection->GetPeerAddressWithType()); + return; + } + log::warn("address not found!"); + promise.set_value(address_with_type); + return; + } + + void get_advertising_set_connected_to(const RawAddress& remote_bda, + std::promise> promise) { + log::debug("get_advertising_set_connected_to {}", remote_bda); + auto remote_address = ToGdAddress(remote_bda); + for (auto& [handle, connection] : handle_to_le_connection_map_) { + if (connection->GetRemoteAddressWithType().GetAddress() == remote_address) { + promise.set_value(connection->GetAdvertisingSetConnectedTo()); + return; + } + } + log::warn("address not found!"); + promise.set_value({}); + return; + } + void ignore_le_connection_from(const hci::AddressWithType& address_with_type) { shadow_acceptlist_.Remove(address_with_type); GetAclManager()->CancelLeConnect(address_with_type); @@ -1367,50 +1424,25 @@ void shim::Acl::OnClassicLinkDisconnected(HciHandle handle, hci::ErrorCode reaso remote_address, creation_time, teardown_time, handle, is_locally_initiated, reason)); } -bluetooth::hci::AddressWithType shim::Acl::GetConnectionLocalAddress(uint16_t handle, - bool ota_address) { - bluetooth::hci::AddressWithType address_with_type; - - for (auto& [acl_handle, connection] : pimpl_->handle_to_le_connection_map_) { - if (acl_handle != handle) { - continue; - } - - if (ota_address) { - return connection->GetLocalOtaAddressWithType(); - } - return connection->GetLocalAddressWithType(); - } - log::warn("address not found!"); - return address_with_type; +void shim::Acl::GetConnectionLocalAddress( + uint16_t handle, bool ota_address, std::promise promise) { + log::debug("GetConnectionLocalAddress handle:{} ota_address:{}", handle, ota_address); + handler_->CallOn(pimpl_.get(), &Acl::impl::get_connection_local_address, handle, ota_address, + std::move(promise)); } -bluetooth::hci::AddressWithType shim::Acl::GetConnectionPeerAddress(uint16_t handle, - bool ota_address) { - bluetooth::hci::AddressWithType address_with_type; - for (auto& [acl_handle, connection] : pimpl_->handle_to_le_connection_map_) { - if (acl_handle != handle) { - continue; - } - - if (ota_address) { - return connection->GetPeerOtaAddressWithType(); - } - return connection->GetPeerAddressWithType(); - } - log::warn("address not found!"); - return address_with_type; +void shim::Acl::GetConnectionPeerAddress( + uint16_t handle, bool ota_address, std::promise promise) { + log::debug("GetConnectionPeerAddress handle:{} ota_address:{}", handle, ota_address); + handler_->CallOn(pimpl_.get(), &Acl::impl::get_connection_peer_address, handle, ota_address, + std::move(promise)); } -std::optional shim::Acl::GetAdvertisingSetConnectedTo(const RawAddress& remote_bda) { - auto remote_address = ToGdAddress(remote_bda); - for (auto& [handle, connection] : pimpl_->handle_to_le_connection_map_) { - if (connection->GetRemoteAddressWithType().GetAddress() == remote_address) { - return connection->GetAdvertisingSetConnectedTo(); - } - } - log::warn("address not found!"); - return {}; +void shim::Acl::GetAdvertisingSetConnectedTo(const RawAddress& remote_bda, + std::promise> promise) { + log::debug("GetAdvertisingSetConnectedTo {}", remote_bda); + handler_->CallOn(pimpl_.get(), &Acl::impl::get_advertising_set_connected_to, remote_bda, + std::move(promise)); } void shim::Acl::OnLeLinkDisconnected(HciHandle handle, hci::ErrorCode reason) { diff --git a/system/main/shim/acl.h b/system/main/shim/acl.h index ebac868f461..013660d7f42 100644 --- a/system/main/shim/acl.h +++ b/system/main/shim/acl.h @@ -57,9 +57,12 @@ public: std::unique_ptr) override; void OnLeConnectFail(hci::AddressWithType, hci::ErrorCode reason) override; void OnLeLinkDisconnected(uint16_t handle, hci::ErrorCode reason); - bluetooth::hci::AddressWithType GetConnectionLocalAddress(uint16_t handle, bool ota_address); - bluetooth::hci::AddressWithType GetConnectionPeerAddress(uint16_t handle, bool ota_address); - std::optional GetAdvertisingSetConnectedTo(const RawAddress& remote_bda); + void GetConnectionLocalAddress(uint16_t handle, bool ota_address, + std::promise promise); + void GetConnectionPeerAddress(uint16_t handle, bool ota_address, + std::promise promise); + void GetAdvertisingSetConnectedTo(const RawAddress& remote_bda, + std::promise> promise); // LinkConnectionInterface void CreateClassicConnection(const hci::Address& address) override; diff --git a/system/main/shim/acl_api.cc b/system/main/shim/acl_api.cc index d00a6619b41..90d9c7b9f5b 100644 --- a/system/main/shim/acl_api.cc +++ b/system/main/shim/acl_api.cc @@ -131,8 +131,11 @@ void bluetooth::shim::ACL_IgnoreAllLeConnections() { void bluetooth::shim::ACL_ReadConnectionAddress(uint16_t handle, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, bool ota_address) { - auto local_address = - Stack::GetInstance()->GetAcl()->GetConnectionLocalAddress(handle, ota_address); + std::promise promise; + auto future = promise.get_future(); + Stack::GetInstance()->GetAcl()->GetConnectionLocalAddress(handle, ota_address, + std::move(promise)); + auto local_address = future.get(); conn_addr = ToRawAddress(local_address.GetAddress()); *p_addr_type = static_cast(local_address.GetAddressType()); @@ -140,15 +143,20 @@ void bluetooth::shim::ACL_ReadConnectionAddress(uint16_t handle, RawAddress& con void bluetooth::shim::ACL_ReadPeerConnectionAddress(uint16_t handle, RawAddress& conn_addr, tBLE_ADDR_TYPE* p_addr_type, bool ota_address) { - auto remote_ota_address = - Stack::GetInstance()->GetAcl()->GetConnectionPeerAddress(handle, ota_address); + std::promise promise; + auto future = promise.get_future(); + Stack::GetInstance()->GetAcl()->GetConnectionPeerAddress(handle, ota_address, std::move(promise)); + auto remote_ota_address = future.get(); conn_addr = ToRawAddress(remote_ota_address.GetAddress()); *p_addr_type = static_cast(remote_ota_address.GetAddressType()); } std::optional bluetooth::shim::ACL_GetAdvertisingSetConnectedTo(const RawAddress& addr) { - return Stack::GetInstance()->GetAcl()->GetAdvertisingSetConnectedTo(addr); + std::promise> promise; + auto future = promise.get_future(); + Stack::GetInstance()->GetAcl()->GetAdvertisingSetConnectedTo(addr, std::move(promise)); + return future.get(); } void bluetooth::shim::ACL_AddToAddressResolution(const tBLE_BD_ADDR& legacy_address_with_type, diff --git a/system/test/mock/mock_main_shim_acl.cc b/system/test/mock/mock_main_shim_acl.cc index 2c11004ba26..831be689d63 100644 --- a/system/test/mock/mock_main_shim_acl.cc +++ b/system/test/mock/mock_main_shim_acl.cc @@ -88,20 +88,21 @@ void bluetooth::shim::Acl::OnClassicLinkDisconnected(HciHandle /* handle */, inc_func_call_count(__func__); } -bluetooth::hci::AddressWithType shim::Acl::GetConnectionLocalAddress(uint16_t /* handle */, - bool /* ota_address */) { +void shim::Acl::GetConnectionLocalAddress( + uint16_t /* handle */, bool /* ota_address */, + std::promise /* promise */) { inc_func_call_count(__func__); - return hci::AddressWithType(); } -bluetooth::hci::AddressWithType shim::Acl::GetConnectionPeerAddress(uint16_t /* handle */, - bool /* ota_address */) { + +void shim::Acl::GetConnectionPeerAddress( + uint16_t /* handle */, bool /* ota_address */, + std::promise /* promise */) { inc_func_call_count(__func__); - return hci::AddressWithType(); } -std::optional shim::Acl::GetAdvertisingSetConnectedTo(const RawAddress& /* remote_bda */) { +void shim::Acl::GetAdvertisingSetConnectedTo( + const RawAddress& /* remote_bda */, std::promise> /* promise */) { inc_func_call_count(__func__); - return std::nullopt; } void shim::Acl::OnLeLinkDisconnected(HciHandle /* handle */, hci::ErrorCode /* reason */) { -- GitLab From 708e9b1661e17658c6dcf5433a212879c17fe354 Mon Sep 17 00:00:00 2001 From: "eric_kuang.rs" Date: Tue, 15 Oct 2024 10:24:46 +0800 Subject: [PATCH 440/875] Add a condition to check if curr_song_id is "Not provided" when there is no media selected for playing. Test: atest AvrcpDeviceTest BQB test: AVRCPTGNFYBV-04-C Bug: 373470150 Change-Id: I0ecb99eb5240779e0a9a606f2c62c411200e8705 --- system/profile/avrcp/device.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index f334ab659de..7810625f745 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -603,7 +603,8 @@ void Device::TrackChangedNotificationResponse(uint8_t label, bool interim, std:: // PTS BV-04-C and BV-5-C assume browsing not supported if (stack_config_get_interface()->get_pts_avrcp_test()) { log::warn("{}: pts test mode", address_); - uint64_t uid = curr_song_id.empty() ? 0xffffffffffffffff : 0; + uint64_t uid = + (curr_song_id.empty() || curr_song_id == "Not Provided") ? 0xffffffffffffffff : 0; auto response = RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(interim, uid); send_message_cb_.Run(label, false, std::move(response)); return; -- GitLab From f65692fc66ff53b8f2d9d1dd46a4e9a405dba02a Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Thu, 24 Oct 2024 13:56:54 +0000 Subject: [PATCH 441/875] Removed startAutoDispatch and stopAutoDispatch Bug: 373713756 Test: atest HeadsetServiceAndStateMachineTest --rerun-until-failure Flag: TEST_ONLY Change-Id: Ia2e96189e016090063bc006af760381e42caae27 --- .../bluetooth/hfp/HeadsetServiceAndStateMachineTest.java | 2 -- 1 file changed, 2 deletions(-) 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 eb0e166a778..4195b965365 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 @@ -1770,7 +1770,6 @@ public class HeadsetServiceAndStateMachineTest { HeadsetCallState headsetCallState = new HeadsetCallState( 0, 0, HeadsetHalConstants.CALL_STATE_INCOMING, TEST_PHONE_NUMBER, 128, ""); - mTestLooper.startAutoDispatch(); // Require as this is waiting unconditionally mHeadsetService.phoneStateChanged( headsetCallState.mNumActive, headsetCallState.mNumHeld, @@ -1779,7 +1778,6 @@ public class HeadsetServiceAndStateMachineTest { headsetCallState.mType, headsetCallState.mName, false); - mTestLooper.stopAutoDispatch(); mTestLooper.dispatchAll(); // HeadsetStateMachine completes processing CALL_STATE_CHANGED message verify(mNativeInterface).phoneStateChange(device, headsetCallState); -- GitLab From 3b9b4bf0c6fbe94480926962f5ae63c95c9531b2 Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Fri, 25 Oct 2024 08:30:46 +0000 Subject: [PATCH 442/875] Add flag le_scan_remove_non_oneway_binder_calls Bug: 375558872 Bug: 354349140 Bug: 315241296 Test: m -j; Change-Id: I29b5baa2209062552836df1193e62a415a547215 --- flags/gap.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/gap.aconfig b/flags/gap.aconfig index c28f1b67298..2b2b5cdd557 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -247,3 +247,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "le_scan_remove_non_oneway_binder_calls" + namespace: "bluetooth" + description: "Remove non-oneway binder calls from BluetoothLeScanner.startScan" + bug: "375558872" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From d9e44ae2e76ca9927acc9432452d8679a43b04c5 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Fri, 25 Oct 2024 08:48:56 +0000 Subject: [PATCH 443/875] CS: Get the Antenna Configuration Index correctly Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 375165953 Test: m com.android.btservice Change-Id: I1617507a2fbd9b36cf3f4a6a649a65f423fabe7d --- system/gd/hci/distance_measurement_manager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index ab39d5970bf..6e21fcb683a 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -626,8 +626,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { void send_le_cs_set_procedure_parameters(uint16_t connection_handle, uint8_t config_id, uint8_t remote_num_antennas_supported) { uint8_t tone_antenna_config_selection = - cs_tone_antenna_config_mapping_table_[num_antennas_supported_] - [remote_num_antennas_supported]; + cs_tone_antenna_config_mapping_table_[num_antennas_supported_ - 1] + [remote_num_antennas_supported - 1]; uint8_t preferred_peer_antenna_value = cs_preferred_peer_antenna_mapping_table_[tone_antenna_config_selection]; log::info( -- GitLab From 751675a122b463b7d6735881029cfba495177584 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 21 Oct 2024 13:34:42 +0000 Subject: [PATCH 444/875] remove redundent conflict checking Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 368617974 Test: m com.android.btservices Change-Id: I1fc29c3e01ae6b39ea02bb5ff9ffddfd931ef654 --- system/gd/hci/distance_measurement_manager.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index ec56490d420..35e5b3bba51 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -974,14 +974,6 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { distance_measurement_callbacks_->OnDistanceMeasurementStarted(live_tracker->address, METHOD_CS); } - // cs role switch from requester to responder, may reset the config if conflict. - if (!live_tracker->local_start && - cs_requester_trackers_.find(connection_handle) != cs_requester_trackers_.end() && - cs_requester_trackers_[connection_handle].config_id == live_tracker->config_id) { - log::debug("config id {} from remote is the same as the cached local, reset config_set.", - cs_requester_trackers_[connection_handle].config_id); - cs_requester_trackers_[connection_handle].config_set = false; - } } else if (event_view.GetState() == Enable::DISABLED) { uint8_t valid_requester_states = static_cast(CsTrackerState::STARTED); uint8_t valid_responder_states = static_cast(CsTrackerState::STARTED); -- GitLab From 41e77e909c22ec3395be0010e6ce5c304b3d23af Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 24 Oct 2024 18:18:38 -0700 Subject: [PATCH 445/875] Untangled RESTORE_USER_SETTING message Using a different message for OFF and ON is way much clearer, especially with incoming test Bug: 328842491 Flag: Exempt, no-op Test: atest ServiceBluetoothTests Change-Id: I2ac8526c0395762748fb22a17613b6bbe2f61e17 --- .../bluetooth/BluetoothManagerService.java | 68 +++++++++---------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index b59ab9de452..6a9e905310c 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -157,10 +157,8 @@ class BluetoothManagerService { @VisibleForTesting static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; @VisibleForTesting static final int MESSAGE_USER_SWITCHED = 300; @VisibleForTesting static final int MESSAGE_USER_UNLOCKED = 301; - @VisibleForTesting static final int MESSAGE_RESTORE_USER_SETTING = 500; - - private static final int RESTORE_SETTING_TO_ON = 1; - private static final int RESTORE_SETTING_TO_OFF = 0; + @VisibleForTesting static final int MESSAGE_RESTORE_USER_SETTING_OFF = 501; + @VisibleForTesting static final int MESSAGE_RESTORE_USER_SETTING_ON = 502; private static final int MAX_ERROR_RESTART_RETRIES = 6; private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10; @@ -557,17 +555,15 @@ class BluetoothManagerService { + (" prevValue=" + prevValue) + (" newValue=" + newValue)); - if ((newValue != null) - && (prevValue != null) - && !prevValue.equals(newValue)) { - mHandler.obtainMessage( - MESSAGE_RESTORE_USER_SETTING, - newValue.equals("0") - ? RESTORE_SETTING_TO_OFF - : RESTORE_SETTING_TO_ON, - 0) - .sendToTarget(); + if ((newValue == null) + || (prevValue == null) + || prevValue.equals(newValue)) { + return; } + mHandler.sendEmptyMessage( + newValue.equals("0") + ? MESSAGE_RESTORE_USER_SETTING_OFF + : MESSAGE_RESTORE_USER_SETTING_ON); } } else if (action.equals(Intent.ACTION_SHUTDOWN)) { Log.i(TAG, "Device is shutting down."); @@ -1539,24 +1535,26 @@ class BluetoothManagerService { } break; - case MESSAGE_RESTORE_USER_SETTING: - if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { - Log.d(TAG, "MESSAGE_RESTORE_USER_SETTING: set Bluetooth state to disabled"); - setBluetoothPersistedState(BLUETOOTH_OFF); - mEnableExternal = false; - sendDisableMsg(ENABLE_DISABLE_REASON_RESTORE_USER_SETTING); - } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) { - Log.d(TAG, "MESSAGE_RESTORE_USER_SETTING: set Bluetooth state to enabled"); - mQuietEnableExternal = false; - mEnableExternal = true; - sendEnableMsg(false, ENABLE_DISABLE_REASON_RESTORE_USER_SETTING); - } else { - Log.w( - TAG, - "MESSAGE_RESTORE_USER_SETTING: Unhandled." - + (" mEnable=" + mEnable) - + (" msg.arg1=" + msg.arg1)); + case MESSAGE_RESTORE_USER_SETTING_OFF: + if (!mEnable) { + Log.w(TAG, "RESTORE_USER_SETTING_OFF: Unhandled: already disabled"); + break; + } + Log.d(TAG, "RESTORE_USER_SETTING_OFF: set Bluetooth state to disabled"); + setBluetoothPersistedState(BLUETOOTH_OFF); + mEnableExternal = false; + sendDisableMsg(ENABLE_DISABLE_REASON_RESTORE_USER_SETTING); + break; + + case MESSAGE_RESTORE_USER_SETTING_ON: + if (mEnable) { + Log.w(TAG, "RESTORE_USER_SETTING_ON: Unhandled: already enabled"); + break; } + Log.d(TAG, "RESTORE_USER_SETTING_ON: set Bluetooth state to enabled"); + mQuietEnableExternal = false; + mEnableExternal = true; + sendEnableMsg(false, ENABLE_DISABLE_REASON_RESTORE_USER_SETTING); break; case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: @@ -1618,14 +1616,10 @@ class BluetoothManagerService { bluetoothStateChangeHandler(prevState, newState); // handle error state transition case from TURNING_ON to OFF // unbind and rebind bluetooth service and enable bluetooth - if ((prevState == STATE_BLE_TURNING_ON) - && (newState == STATE_OFF) - && mEnable) { + if ((prevState == STATE_BLE_TURNING_ON) && (newState == STATE_OFF) && mEnable) { recoverBluetoothServiceFromError(false); } - if ((prevState == STATE_TURNING_ON) - && (newState == STATE_BLE_ON) - && mEnable) { + if ((prevState == STATE_TURNING_ON) && (newState == STATE_BLE_ON) && mEnable) { recoverBluetoothServiceFromError(true); } // If we tried to enable BT while BT was in the process of shutting down, -- GitLab From 1a279f979f171071caec64f597ab634b0b1d8d85 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 24 Oct 2024 18:21:47 -0700 Subject: [PATCH 446/875] Remove un-necessary post Airplane and satellite handler are running on the correct looper. post is not necessary For userSwitch posting delayed with a 0 delay isn't giving value. finally, remove the synchronized in the airplane handler as this is not called by multiples thread Bug: 328842491 Flag: Exempt, no-op Test: atest ServiceBluetoothTests Change-Id: I4d2e8d7bf6e25ca36157aa2d9ac9dc4ee8fd36f0 --- .../bluetooth/BluetoothManagerService.java | 68 ++++++++----------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 6a9e905310c..32a017cc899 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -399,39 +399,30 @@ class BluetoothManagerService { private static final Object ON_SWITCH_USER_TOKEN = new Object(); Unit onAirplaneModeChanged(boolean isAirplaneModeOn) { - mHandler.postDelayed( - () -> - delayModeChangedIfNeeded( - ON_AIRPLANE_MODE_CHANGED_TOKEN, - () -> handleAirplaneModeChanged(isAirplaneModeOn), - "onAirplaneModeChanged"), + delayModeChangedIfNeeded( ON_AIRPLANE_MODE_CHANGED_TOKEN, - 0); + () -> handleAirplaneModeChanged(isAirplaneModeOn), + "onAirplaneModeChanged"); return Unit.INSTANCE; } // TODO(b/289584302): Update to private once use_new_satellite_mode is enabled Unit onSatelliteModeChanged(boolean isSatelliteModeOn) { - mHandler.postDelayed( - () -> - delayModeChangedIfNeeded( - ON_SATELLITE_MODE_CHANGED_TOKEN, - () -> handleSatelliteModeChanged(isSatelliteModeOn), - "onSatelliteModeChanged"), + delayModeChangedIfNeeded( ON_SATELLITE_MODE_CHANGED_TOKEN, - 0); + () -> handleSatelliteModeChanged(isSatelliteModeOn), + "onSatelliteModeChanged"); return Unit.INSTANCE; } + // Call is coming from the systemServer main thread and need to be post to avoid race void onSwitchUser(UserHandle userHandle) { - mHandler.postDelayed( + mHandler.post( () -> delayModeChangedIfNeeded( ON_SWITCH_USER_TOKEN, () -> handleSwitchUser(userHandle), - "onSwitchUser"), - ON_SWITCH_USER_TOKEN, - 0); + "onSwitchUser")); } private void forceToOffFromModeChange(int currentState, int reason) { @@ -458,29 +449,30 @@ class BluetoothManagerService { } private void handleAirplaneModeChanged(boolean isAirplaneModeOn) { - synchronized (this) { - if (isBluetoothPersistedStateOn()) { - if (isAirplaneModeOn) { - setBluetoothPersistedState(BLUETOOTH_ON_AIRPLANE); - } else { - setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH); - } + boolean isPersistStateOn = isBluetoothPersistedStateOn(); + if (isPersistStateOn) { + if (isAirplaneModeOn) { + setBluetoothPersistedState(BLUETOOTH_ON_AIRPLANE); + } else { + setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH); } + } - int currentState = mState.get(); - - Log.d( - TAG, - ("handleAirplaneModeChanged(" + isAirplaneModeOn + "):") - + (" currentState=" + nameForState(currentState))); + int currentState = mState.get(); - if (isAirplaneModeOn) { - forceToOffFromModeChange(currentState, ENABLE_DISABLE_REASON_AIRPLANE_MODE); - } else if (mEnableExternal) { - sendEnableMsg(mQuietEnableExternal, ENABLE_DISABLE_REASON_AIRPLANE_MODE); - } else if (currentState != STATE_ON) { - autoOnSetupTimer(); - } + Log.d( + TAG, + ("handleAirplaneModeChanged(" + isAirplaneModeOn + "):") + + (" mEnableExternal=" + mEnableExternal) + + (" isPersistStateOn=" + isPersistStateOn) + + (" currentState=" + nameForState(currentState))); + + if (isAirplaneModeOn) { + forceToOffFromModeChange(currentState, ENABLE_DISABLE_REASON_AIRPLANE_MODE); + } else if (mEnableExternal) { + sendEnableMsg(mQuietEnableExternal, ENABLE_DISABLE_REASON_AIRPLANE_MODE); + } else if (currentState != STATE_ON) { + autoOnSetupTimer(); } } -- GitLab From 36c8630f55517761dce3f832626ea41af2efa6c2 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 24 Oct 2024 18:24:36 -0700 Subject: [PATCH 447/875] SystemServer: Airplane change when FactoryReset When receiving ACTION_SETTING_RESTORED we temporarily set the persisted state to off. If we leave airplane mode before the restore is executed we will have a race condition on the start of the bluetooth. This CL adds a check on the persistedState, to make sure we do not wrongly interact with it Bug: 328842491 Fix: 328842491 Test: atest ServiceBluetoothTests Test: atest disableAirplane_whenFactoryReset_doesNotStartBluetooth Test: atest disableAirplane_whenNothing_startBluetooth Flag: Exempt, Adding a flag here does not add DF value as it is a very edge case (you need to stress test factory reset & airplane mode) Change-Id: I969e156c9f289aa0088887d8c7fafca15a4bc843 --- .../bluetooth/BluetoothManagerService.java | 7 +- .../BluetoothManagerServiceTest.java | 78 ++++++++++++++++++- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 32a017cc899..8bd003641d9 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -142,7 +142,7 @@ class BluetoothManagerService { // Delay for the addProxy function in msec private static final int ADD_PROXY_DELAY_MS = 100 * HW_MULTIPLIER; // Delay for retrying enable and disable in msec - private static final int ENABLE_DISABLE_DELAY_MS = 300 * HW_MULTIPLIER; + @VisibleForTesting static final int ENABLE_DISABLE_DELAY_MS = 300 * HW_MULTIPLIER; @VisibleForTesting static final int MESSAGE_ENABLE = 1; @VisibleForTesting static final int MESSAGE_DISABLE = 2; @@ -182,7 +182,7 @@ class BluetoothManagerService { private final RemoteCallbackList mCallbacks = new RemoteCallbackList<>(); private final BluetoothServiceBinder mBinder; - private final BluetoothHandler mHandler; + @VisibleForTesting final BluetoothHandler mHandler; private final ContentResolver mContentResolver; private final Context mContext; private final Looper mLooper; @@ -469,7 +469,8 @@ class BluetoothManagerService { if (isAirplaneModeOn) { forceToOffFromModeChange(currentState, ENABLE_DISABLE_REASON_AIRPLANE_MODE); - } else if (mEnableExternal) { + } else if (mEnableExternal && currentState != STATE_ON && isPersistStateOn) { + // isPersistStateOn is checked to prevent race with RESTORE_USER_SETTING sendEnableMsg(mQuietEnableExternal, ENABLE_DISABLE_REASON_AIRPLANE_MODE); } else if (currentState != STATE_ON) { autoOnSetupTimer(); diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java index 4be1786c362..8c4a2c9fa83 100644 --- a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java +++ b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java @@ -19,6 +19,7 @@ package com.android.server.bluetooth; import static android.bluetooth.BluetoothAdapter.STATE_BLE_ON; import static android.bluetooth.BluetoothAdapter.STATE_OFF; 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 com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_SERVICE_CONNECTED; @@ -26,7 +27,9 @@ import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUET import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_STATE_CHANGE; import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_DISABLE; import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_ENABLE; +import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_HANDLE_DISABLE_DELAYED; import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_RESTART_BLUETOOTH_SERVICE; +import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_RESTORE_USER_SETTING_OFF; import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_TIMEOUT_BIND; import static com.google.common.truth.Truth.assertThat; @@ -101,6 +104,7 @@ 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; @@ -185,6 +189,7 @@ public class BluetoothManagerServiceTest { doReturn(mAdapterBinder).when(mBluetoothServerProxy).createAdapterBinder(any()); doReturn(mAdapterService).when(mAdapterBinder).getAdapterBinder(); + doReturn(mBinder).when(mAdapterService).asBinder(); doReturn(mock(Intent.class)) .when(mContext) @@ -238,6 +243,17 @@ public class BluetoothManagerServiceTest { }); } + private void discardMessage(int... what) { + IntStream.of(what) + .forEach( + w -> { + Message msg = mLooper.nextMessage(); + assertThat(msg).isNotNull(); + assertThat(msg.what).isEqualTo(w); + // Drop the message + }); + } + @Test public void onUserRestrictionsChanged_disallowBluetooth_onlySendDisableMessageOnSystemUser() throws InterruptedException { @@ -358,6 +374,22 @@ public class BluetoothManagerServiceTest { return btCallback; } + private void transition_onToBleOn(IBluetoothCallback btCallback) throws Exception { + verify(mAdapterBinder).onToBleOn(any()); + + btCallback.onBluetoothStateChange(STATE_TURNING_OFF, STATE_BLE_ON); + syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE); + } + + private void transition_onToOff(IBluetoothCallback btCallback) throws Exception { + transition_onToBleOn(btCallback); + verify(mAdapterBinder).bleOnToOff(any()); + + // When all the profile are started, adapterService consider it is ON + btCallback.onBluetoothStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); + syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE); + } + @Test public void enable_whileTurningToBleOn_shouldEnable() throws Exception { mManagerService.enableBle("enable_whileTurningToBleOn_shouldEnable", mBinder); @@ -450,9 +482,47 @@ public class BluetoothManagerServiceTest { assertThat(mManagerService.getState()).isEqualTo(STATE_OFF); mLooper.moveTimeForward(120_000); - Message msg = mLooper.nextMessage(); - assertThat(msg).isNotNull(); - assertThat(msg.what).isEqualTo(MESSAGE_RESTART_BLUETOOTH_SERVICE); - // Discard the msg without executing it + discardMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + } + + @Test + public void disableAirplane_whenNothing_startBluetooth() throws Exception { + doReturn(BluetoothManagerService.BLUETOOTH_ON_BLUETOOTH) + .when(mBluetoothServerProxy) + .getBluetoothPersistedState(any(), anyInt()); + mManagerService.enable("disableAirplane_whenNothing_startBluetooth"); + discardMessage(MESSAGE_ENABLE); + + mManagerService.onAirplaneModeChanged(false); + 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()); + + mManagerService.enable("test_offToOn"); + 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); + transition_onToOff(btCallback); + + mManagerService.onAirplaneModeChanged(false); + assertThat(mLooper.nextMessage()).isNull(); // Must not create a MESSAGE_ENABLE } } -- GitLab From 8fb0b987966c917d14f9b2d21374747f8330049a Mon Sep 17 00:00:00 2001 From: Charlie Boutier Date: Thu, 24 Oct 2024 21:38:13 +0000 Subject: [PATCH 448/875] BumbleBluetoothTests: Add custom annotations to skip physical tests Bug: 375478591 Test: atest BumbleBluetoothTests Change-Id: If866025caea4ef5c129f2aa9a128d277dd9b8b6e --- .../src/android/bluetooth/DckL2capTest.kt | 2 ++ .../src/android/bluetooth/LeScanningTest.java | 1 + .../src/android/bluetooth/VirtualOnly.java | 28 +++++++++++++++++++ .../bluetooth/hid/HidHostDualModeTest.java | 2 ++ .../android/bluetooth/hid/HidHostTest.java | 2 ++ .../LeAudioServiceDiscoveryTest.java | 2 ++ 6 files changed, 37 insertions(+) create mode 100644 framework/tests/bumble/src/android/bluetooth/VirtualOnly.java diff --git a/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt b/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt index 9d42f3d794b..e658e8c6452 100644 --- a/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt +++ b/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt @@ -137,6 +137,7 @@ public class DckL2capTest() : Closeable { } @Test + @VirtualOnly fun testSend() { Log.d(TAG, "testSend") val remoteDevice = @@ -189,6 +190,7 @@ public class DckL2capTest() : Closeable { } @Test + @VirtualOnly fun testReceive() { Log.d(TAG, "testReceive: Connect L2CAP") var bluetoothSocket: BluetoothSocket? diff --git a/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java b/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java index 3f728e4a694..ecaa40174eb 100644 --- a/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java +++ b/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java @@ -354,6 +354,7 @@ public class LeScanningTest { } @Test + @VirtualOnly public void startBleScan_withServiceData() { advertiseWithBumbleWithServiceData(); diff --git a/framework/tests/bumble/src/android/bluetooth/VirtualOnly.java b/framework/tests/bumble/src/android/bluetooth/VirtualOnly.java new file mode 100644 index 00000000000..77d7555ff36 --- /dev/null +++ b/framework/tests/bumble/src/android/bluetooth/VirtualOnly.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 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. + */ + +package android.bluetooth; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface VirtualOnly { + String value() default ""; +} diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java index 778fc239e07..cddee2a9adf 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java @@ -49,6 +49,7 @@ import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.bluetooth.PandoraDevice; +import android.bluetooth.VirtualOnly; import android.bluetooth.test_utils.EnableBluetoothRule; import android.content.BroadcastReceiver; import android.content.Context; @@ -92,6 +93,7 @@ import java.util.Arrays; /** Test cases for {@link BluetoothHidHost}. */ @SuppressLint("MissingPermission") @RunWith(AndroidJUnit4.class) +@VirtualOnly public class HidHostDualModeTest { private static final String TAG = HidHostDualModeTest.class.getSimpleName(); private static final String BUMBLE_DEVICE_NAME = "Bumble"; diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java index fde1a292bdf..76eda63d41b 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java @@ -46,6 +46,7 @@ import android.bluetooth.BluetoothHidHost; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.PandoraDevice; +import android.bluetooth.VirtualOnly; import android.bluetooth.cts.EnableBluetoothRule; import android.content.BroadcastReceiver; import android.content.Context; @@ -91,6 +92,7 @@ import java.util.concurrent.TimeUnit; /** Test cases for {@link BluetoothHidHost}. */ @RunWith(AndroidJUnit4.class) +@VirtualOnly public class HidHostTest { private static final String TAG = HidHostTest.class.getSimpleName(); private static final Duration INTENT_TIMEOUT = Duration.ofSeconds(10); diff --git a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java index 27b0f106e45..2f6a56c1348 100644 --- a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java +++ b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java @@ -32,6 +32,7 @@ import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothUuid; import android.bluetooth.Host; import android.bluetooth.PandoraDevice; +import android.bluetooth.VirtualOnly; import android.bluetooth.test_utils.EnableBluetoothRule; import android.content.BroadcastReceiver; import android.content.Context; @@ -204,6 +205,7 @@ public class LeAudioServiceDiscoveryTest { * Classic services */ @Test + @VirtualOnly public void testServiceDiscoveryWithRandomAddr() { registerIntentActions( -- GitLab From de9adba3b86f3d40c3f3407b1ff7a4523a83f18e Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 14:33:54 -0700 Subject: [PATCH 449/875] Remove public visibility on BluetoothGeneratedDumpsysTestData_h Bug: 370993756 Test: m com.android.btservices Flag: EXEMPT, build change Change-Id: I0c0d402fd4b414423858f00f07896a12672c6618 --- system/gd/dumpsys/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/system/gd/dumpsys/Android.bp b/system/gd/dumpsys/Android.bp index f26ef97f9b4..84074824ac4 100644 --- a/system/gd/dumpsys/Android.bp +++ b/system/gd/dumpsys/Android.bp @@ -27,7 +27,6 @@ filegroup { genrule { name: "BluetoothGeneratedDumpsysTestData_h", - visibility: ["//visibility:public"], tools: [ "flatc", ], -- GitLab From ae595fb4496288982f512bc8a09e191a97ce7eff Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 21:40:26 +0000 Subject: [PATCH 450/875] system/stack/avrc: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: If10f34fdcc13cdba269f432692fbfb034f610562 --- system/stack/avrc/avrc_api.cc | 5 +---- system/stack/avrc/avrc_bld_tg.cc | 5 +---- system/stack/avrc/avrc_pars_ct.cc | 6 ++---- system/test/mock/mock_stack_avrc_api.cc | 4 ---- system/test/mock/mock_stack_avrc_bld_tg.cc | 7 ------- system/test/mock/mock_stack_avrc_pars.ct.cc | 8 -------- 6 files changed, 4 insertions(+), 31 deletions(-) diff --git a/system/stack/avrc/avrc_api.cc b/system/stack/avrc/avrc_api.cc index a2d75c218a5..28f6f85064e 100644 --- a/system/stack/avrc/avrc_api.cc +++ b/system/stack/avrc/avrc_api.cc @@ -41,9 +41,6 @@ #include "storage/config_keys.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -156,7 +153,7 @@ void avrc_flush_cmd_q(uint8_t handle) { * Returns Nothing. * *****************************************************************************/ -void avrc_process_timeout(void* data) { +static void avrc_process_timeout(void* data) { tAVRC_PARAM* param = (tAVRC_PARAM*)data; log::verbose("AVRC: command timeout (handle=0x{:02x}, label=0x{:02x})", param->handle, diff --git a/system/stack/avrc/avrc_bld_tg.cc b/system/stack/avrc/avrc_bld_tg.cc index 7b5791a8c2c..a057a03b531 100644 --- a/system/stack/avrc/avrc_bld_tg.cc +++ b/system/stack/avrc/avrc_bld_tg.cc @@ -30,9 +30,6 @@ #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -708,7 +705,7 @@ static tAVRC_STS avrc_bld_set_absolute_volume_rsp(uint8_t abs_vol, BT_HDR* p_pkt * Otherwise, the error code. * ******************************************************************************/ -tAVRC_STS avrc_bld_group_navigation_rsp(uint16_t navi_id, BT_HDR* p_pkt) { +static tAVRC_STS avrc_bld_group_navigation_rsp(uint16_t navi_id, BT_HDR* p_pkt) { if (!AVRC_IS_VALID_GROUP(navi_id)) { log::error("bad navigation op id: {}", navi_id); return AVRC_STS_BAD_PARAM; diff --git a/system/stack/avrc/avrc_pars_ct.cc b/system/stack/avrc/avrc_pars_ct.cc index 2560ebab990..b72fa63b438 100644 --- a/system/stack/avrc/avrc_pars_ct.cc +++ b/system/stack/avrc/avrc_pars_ct.cc @@ -25,9 +25,6 @@ #include "osi/include/osi.h" #include "stack/include/bt_types.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /***************************************************************************** @@ -132,7 +129,8 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg, tAVRC_RESPONSE* p return status; } -tAVRC_STS avrc_parse_notification_rsp(uint8_t* p_stream, uint16_t len, tAVRC_REG_NOTIF_RSP* p_rsp) { +static tAVRC_STS avrc_parse_notification_rsp(uint8_t* p_stream, uint16_t len, + tAVRC_REG_NOTIF_RSP* p_rsp) { uint32_t min_len = 1; if (len < min_len) { diff --git a/system/test/mock/mock_stack_avrc_api.cc b/system/test/mock/mock_stack_avrc_api.cc index 22b3f15f196..655690c7ecd 100644 --- a/system/test/mock/mock_stack_avrc_api.cc +++ b/system/test/mock/mock_stack_avrc_api.cc @@ -25,9 +25,6 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - bool avrcp_absolute_volume_is_enabled() { inc_func_call_count(__func__); return true; @@ -79,7 +76,6 @@ uint16_t AVRC_PassRsp(uint8_t /* handle */, uint8_t /* label */, tAVRC_MSG_PASS* return 0; } void avrc_flush_cmd_q(uint8_t /* handle */) { inc_func_call_count(__func__); } -void avrc_process_timeout(void* /* data */) { inc_func_call_count(__func__); } void avrc_send_next_vendor_cmd(uint8_t /* handle */) { inc_func_call_count(__func__); } void avrc_start_cmd_timer(uint8_t /* handle */, uint8_t /* label */, uint8_t /* msg_mask */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_avrc_bld_tg.cc b/system/test/mock/mock_stack_avrc_bld_tg.cc index 6a1f126edd7..7ff5e8fc265 100644 --- a/system/test/mock/mock_stack_avrc_bld_tg.cc +++ b/system/test/mock/mock_stack_avrc_bld_tg.cc @@ -24,15 +24,8 @@ #include "stack/include/bt_hdr.h" #include "test/common/mock_functions.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - tAVRC_STS AVRC_BldResponse(uint8_t /* handle */, tAVRC_RESPONSE* /* p_rsp */, BT_HDR** /* pp_pkt */) { inc_func_call_count(__func__); return 0; } -tAVRC_STS avrc_bld_group_navigation_rsp(uint16_t /* navi_id */, BT_HDR* /* p_pkt */) { - inc_func_call_count(__func__); - return 0; -} diff --git a/system/test/mock/mock_stack_avrc_pars.ct.cc b/system/test/mock/mock_stack_avrc_pars.ct.cc index 511231e11d4..193f2f21b5f 100644 --- a/system/test/mock/mock_stack_avrc_pars.ct.cc +++ b/system/test/mock/mock_stack_avrc_pars.ct.cc @@ -23,9 +23,6 @@ #include "avrc_defs.h" #include "test/common/mock_functions.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* /* p_msg */, tAVRC_RESPONSE* /* p_result */, uint8_t* /* p_buf */, uint16_t* /* buf_len */) { inc_func_call_count(__func__); @@ -36,8 +33,3 @@ tAVRC_STS AVRC_ParsResponse(tAVRC_MSG* /* p_msg */, tAVRC_RESPONSE* /* p_result inc_func_call_count(__func__); return 0; } -tAVRC_STS avrc_parse_notification_rsp(uint8_t* /* p_stream */, uint16_t /* len */, - tAVRC_REG_NOTIF_RSP* /* p_rsp */) { - inc_func_call_count(__func__); - return 0; -} -- GitLab From e2a5d393ee821c57e8e724aee5ab3c3b3a91fe02 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 14:58:44 -0700 Subject: [PATCH 451/875] Remove unused library system/profile/sdp Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: I3f809f53dccbfb3cad9d803c58a9fc9b6ac98925 --- TEST_MAPPING | 6 - system/profile/sdp/Android.bp | 60 --- .../profile/sdp/common/data_element_reader.cc | 238 ----------- .../profile/sdp/common/data_element_reader.h | 64 --- .../common/test/data_element_reader_test.cc | 382 ------------------ system/profile/sdp/sdp_common.h | 95 ----- system/profile/sdp/sdp_logging_helper.h | 128 ------ 7 files changed, 973 deletions(-) delete mode 100644 system/profile/sdp/Android.bp delete mode 100644 system/profile/sdp/common/data_element_reader.cc delete mode 100644 system/profile/sdp/common/data_element_reader.h delete mode 100644 system/profile/sdp/common/test/data_element_reader_test.cc delete mode 100644 system/profile/sdp/sdp_common.h delete mode 100644 system/profile/sdp/sdp_logging_helper.h diff --git a/TEST_MAPPING b/TEST_MAPPING index bbb5983a531..5da35c4dc00 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -107,9 +107,6 @@ { "name": "bluetooth_test_common" }, - { - "name": "bluetooth_test_sdp" - }, { "name": "bluetooth_vc_test" }, @@ -272,9 +269,6 @@ { "name": "bluetooth_test_common" }, - { - "name": "bluetooth_test_sdp" - }, { "name": "bluetooth_vc_test" }, diff --git a/system/profile/sdp/Android.bp b/system/profile/sdp/Android.bp deleted file mode 100644 index 88e491644f4..00000000000 --- a/system/profile/sdp/Android.bp +++ /dev/null @@ -1,60 +0,0 @@ -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_library_static { - name: "sdp_service", - defaults: [ - "fluoride_defaults", - ], - host_supported: true, - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - ], - srcs: [ - "common/data_element_reader.cc", - ], - static_libs: [ - "lib-bt-packets", - "libbluetooth-types", - "libbluetooth_log", - ], - header_libs: ["libbluetooth_headers"], -} - -cc_test { - name: "bluetooth_test_sdp", - test_suites: ["general-tests"], - defaults: [ - "fluoride_defaults", - "mts_defaults", - ], - host_supported: true, - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - ], - srcs: [ - "common/test/data_element_reader_test.cc", - ], - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth-types", - "libbluetooth_log", - "libchrome", - "libgmock", - "sdp_service", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} diff --git a/system/profile/sdp/common/data_element_reader.cc b/system/profile/sdp/common/data_element_reader.cc deleted file mode 100644 index 95c4d57e154..00000000000 --- a/system/profile/sdp/common/data_element_reader.cc +++ /dev/null @@ -1,238 +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. - */ - -#include "data_element_reader.h" - -#include - -#include - -#include "sdp_logging_helper.h" -#include "types/bluetooth/uuid.h" - -// A helper macro that can verify that there is enough data remaining in the -// reader to extract without overflowing. end_ - it_ should never be negative -// so casting it to a size_t is always safe. If it does fail, set it_ to end_ -// so that all additional readings fail. -#define CHECK_REMAINING_LEN(x) \ - do { \ - if ((size_t)(end_ - it_) < x) { \ - log::warn("Extract would read past end of data."); \ - return ParseFail(); \ - } \ - } while (0) - -namespace bluetooth { -namespace sdp { - -DataElementReader::DataElement DataElementReader::ReadNext() { - if (it_ > end_) { - log::fatal("Beginning of buffer is past end of buffer."); - } - if (it_ == end_) { - return std::monostate(); - } - - uint8_t descriptor = *it_++; - DataElementType type = static_cast(descriptor >> 3); - DataElementSize size = static_cast(descriptor & 0b00000111); - - // All types with a value greater than URL are currently reserved. - if (type > DataElementType::MAX_VALUE) { - log::warn("Trying to use a reserved data element type"); - return ParseFail(); - } - - switch (type) { - case DataElementType::BOOLEAN: - if (size != DataElementSize::BYTE1) { - log::warn("Invalid size for bool: {}", size); - return ParseFail(); - } - - CHECK_REMAINING_LEN(1); - return it_.extract() != 0; - case DataElementType::SIGNED_INT: - return ReadSignedInt(size); - case DataElementType::UNSIGNED_INT: - return ReadUnsignedInt(size); - case DataElementType::UUID: - return ReadUuid(size); - case DataElementType::STRING: - return ReadString(size); - case DataElementType::DATA_ELEMENT_SEQUENCE: - return ReadSequence(size); - default: - // TODO: The other data element types are never used in the previous SDP - // implementation. We should properly handle them in the future though - // for completeness. - log::error("Unhandled Data Element Type: {}", type); - } - - return ParseFail(); -} - -DataElementReader::DataElement DataElementReader::ParseFail() { - it_ = end_; - return std::monostate(); -} - -template -DataElementReader::DataElement DataElementReader::ReadInteger() { - static_assert(std::is_integral::value, "ReadInteger requires an integral type."); - - CHECK_REMAINING_LEN(sizeof(IntegerType)); - return it_.extractBE(); -} - -DataElementReader::DataElement DataElementReader::ReadLargeInt() { - CHECK_REMAINING_LEN(16); - - std::array array; - for (size_t i = 0; i < sizeof(uint8_t[16]); i++) { - array[i] = it_.extract(); - } - - return array; -} - -DataElementReader::DataElement DataElementReader::ReadSignedInt(DataElementSize size) { - switch (size) { - case DataElementSize::BYTE1: - return ReadInteger(); - case DataElementSize::BYTE2: - return ReadInteger(); - case DataElementSize::BYTE4: - return ReadInteger(); - case DataElementSize::BYTE8: - return ReadInteger(); - case DataElementSize::BYTE16: - return ReadLargeInt(); - default: - log::warn("Invalid size for int: {}", size); - } - - return ParseFail(); -} - -DataElementReader::DataElement DataElementReader::ReadUnsignedInt(DataElementSize size) { - switch (size) { - case DataElementSize::BYTE1: - return ReadInteger(); - case DataElementSize::BYTE2: - return ReadInteger(); - case DataElementSize::BYTE4: - return ReadInteger(); - case DataElementSize::BYTE8: - return ReadInteger(); - case DataElementSize::BYTE16: - return ReadLargeInt(); - default: - log::warn("Invalid size for uint: {}", size); - } - - return ParseFail(); -} - -DataElementReader::DataElement DataElementReader::ReadUuid(DataElementSize size) { - if (size == DataElementSize::BYTE2) { - CHECK_REMAINING_LEN(2); - return Uuid::From16Bit(it_.extractBE()); - } - - if (size == DataElementSize::BYTE4) { - CHECK_REMAINING_LEN(4); - return Uuid::From32Bit(it_.extractBE()); - } - - if (size == DataElementSize::BYTE16) { - CHECK_REMAINING_LEN(16); - - Uuid::UUID128Bit uuid_array; - for (int i = 0; i < 16; i++) { - uuid_array[i] = it_.extract(); - } - - return Uuid::From128BitBE(uuid_array); - } - - log::warn("Invalid size for UUID: {}", size); - return ParseFail(); -} - -DataElementReader::DataElement DataElementReader::ReadString(DataElementSize size) { - uint32_t num_bytes = 0; - - switch (size) { - case DataElementSize::ADDITIONAL_8BIT: - CHECK_REMAINING_LEN(1); - num_bytes = it_.extractBE(); - break; - case DataElementSize::ADDITIONAL_16BIT: - CHECK_REMAINING_LEN(2); - num_bytes = it_.extractBE(); - break; - case DataElementSize::ADDITIONAL_32BIT: - CHECK_REMAINING_LEN(4); - num_bytes = it_.extractBE(); - break; - default: - log::warn("Invalid size for string: {}", size); - return ParseFail(); - } - - CHECK_REMAINING_LEN(num_bytes); - - std::string str; - for (uint32_t i = 0; i < num_bytes; i++) { - str.push_back(it_.extractBE()); - } - - return str; -} - -DataElementReader::DataElement DataElementReader::ReadSequence(DataElementSize size) { - uint32_t num_bytes = 0; - - switch (size) { - case DataElementSize::ADDITIONAL_8BIT: - CHECK_REMAINING_LEN(1); - num_bytes = it_.extractBE(); - break; - case DataElementSize::ADDITIONAL_16BIT: - CHECK_REMAINING_LEN(2); - num_bytes = it_.extractBE(); - break; - case DataElementSize::ADDITIONAL_32BIT: - CHECK_REMAINING_LEN(4); - num_bytes = it_.extractBE(); - break; - default: - log::warn("Invalid size for string: {}", size); - return ParseFail(); - } - - CHECK_REMAINING_LEN(num_bytes); - - // Create a parser that points to the beginning of the next sequence and move - // the iterator to past the end of the new sequence. - auto&& temp = DataElementReader(it_, it_ + num_bytes); - it_ += num_bytes; - return std::move(temp); -} - -} // namespace sdp -} // namespace bluetooth diff --git a/system/profile/sdp/common/data_element_reader.h b/system/profile/sdp/common/data_element_reader.h deleted file mode 100644 index eea58ece435..00000000000 --- a/system/profile/sdp/common/data_element_reader.h +++ /dev/null @@ -1,64 +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 - -#include -#include - -#include "bluetooth/uuid.h" -#include "packet.h" -#include "sdp_common.h" -#include "stack/include/bt_octets.h" - -namespace bluetooth { -namespace sdp { - -// A helper class that helps extract data element objects from SDP packets. -class DataElementReader { -public: - // If the DataElement contains monostate, that means parsing has failed. - using DataElement = - std::variant; - - DataElementReader(Iterator begin, Iterator end) : it_(begin), end_(end) {} - - // Get the next Data Element in the data. If reading fails for any reason, - // the DataElementReader becomes invalid and will continuously fail to read - // from that point onward. - DataElement ReadNext(); - -private: - // Extraction Helpers - DataElement ParseFail(); - template - DataElement ReadInteger(); - DataElement ReadLargeInt(); - - // Extraction Functions - DataElement ReadSignedInt(DataElementSize size); - DataElement ReadUnsignedInt(DataElementSize size); - DataElement ReadUuid(DataElementSize size); - DataElement ReadString(DataElementSize size); - DataElement ReadSequence(DataElementSize size); - - Iterator it_; - Iterator end_; -}; - -} // namespace sdp -} // namespace bluetooth diff --git a/system/profile/sdp/common/test/data_element_reader_test.cc b/system/profile/sdp/common/test/data_element_reader_test.cc deleted file mode 100644 index 3203098e0d1..00000000000 --- a/system/profile/sdp/common/test/data_element_reader_test.cc +++ /dev/null @@ -1,382 +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. - */ - -#include "common/data_element_reader.h" - -#include - -#include "types/bluetooth/uuid.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -namespace bluetooth { -namespace sdp { - -using namespace testing; -using DataElement = DataElementReader::DataElement; - -// A helper class to help work with the Data Element classes. -class ReaderPacket : public ::bluetooth::Packet { -public: - using Packet::Packet; - - static std::shared_ptr Make(std::vector payload) { - auto pkt = std::shared_ptr(new ReaderPacket()); - pkt->packet_start_index_ = 0; - pkt->packet_end_index_ = payload.size(); - pkt->data_ = std::make_shared>(std::move(payload)); - return pkt; - } - - std::string ToString() const override { return ""; } - bool IsValid() const override { return true; } - std::pair GetPayloadIndecies() const override { - return std::pair(packet_start_index_, packet_end_index_); - } -}; - -bool operator!=(DataElementReader a, DataElementReader b); - -// A helper function to help compare DataElementReader objects. -bool operator==(DataElementReader a, DataElementReader b) { - while (true) { - DataElement a_elem = a.ReadNext(); - DataElement b_elem = b.ReadNext(); - - if (a_elem != b_elem) { - return false; - } - - // If we get here that means both a and b have reached the end. - if (a_elem == DataElement(std::monostate())) { - break; - } - } - - return true; -} - -bool operator!=(DataElementReader a, DataElementReader b) { return !(a == b); } - -// A helper function to convert a type and a size to a descriptor byte. -constexpr uint8_t Desc(DataElementType t, DataElementSize s) { - return static_cast(t) << 3 | static_cast(s); -} - -// Helper that can create a Data Element reader from a vector. -DataElementReader CreateReader(std::vector payload) { - auto packet = ReaderPacket::Make(std::move(payload)); - return DataElementReader(packet->begin(), packet->end()); -} - -// Test all the valid cases of reading the next Data Element. -using ValidTestParam = std::tuple, DataElement>; -class ValidReadTest : public TestWithParam {}; - -std::vector valid_values = { - // Boolean Tests - ValidTestParam{ - {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01}, - true, - }, - ValidTestParam{ - {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00}, - false, - }, - - // Signed Integer Tests - ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE1), 0xFF}, - static_cast(-1)}, - ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2), 0xFF, 0xFF}, - static_cast(-1)}, - ValidTestParam{ - {Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE4), 0xFF, 0xFF, 0xFF, 0xFF}, - static_cast(-1)}, - ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE8), 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - static_cast(-1)}, - ValidTestParam{ - {Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE16), 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - std::array{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - - // Unsigned Integer Tests - ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE1), 0x01}, - static_cast(1)}, - ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE2), 0x00, 0x01}, - static_cast(1)}, - ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE4), 0x00, 0x00, - 0x00, 0x01}, - static_cast(1)}, - ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE8), 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - static_cast(1)}, - ValidTestParam{ - {Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE16), 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - std::array{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - - // UUID Tests - ValidTestParam{{Desc(DataElementType::UUID, DataElementSize::BYTE2), 0x01, 0x02}, - Uuid::From16Bit(0x0102)}, - ValidTestParam{ - {Desc(DataElementType::UUID, DataElementSize::BYTE4), 0x01, 0x02, 0x03, 0x04}, - Uuid::From32Bit(0x01020304)}, - ValidTestParam{ - {Desc(DataElementType::UUID, DataElementSize::BYTE16), 0x00, 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}, - Uuid::From128BitBE({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F})}, - - // String Tests - ValidTestParam{{Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT), 0x05, 'T', - 'e', 's', 't', '1'}, - std::string("Test1")}, - ValidTestParam{{Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_16BIT), 0x00, - 0x05, 'T', 'e', 's', 't', '2'}, - std::string("Test2")}, - ValidTestParam{{Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_32BIT), 0x00, - 0x00, 0x00, 0x05, 'T', 'e', 's', 't', '3'}, - std::string("Test3")}, - - // Nested Data Element List Tests - ValidTestParam{ - {Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_8BIT), - 0x04, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01, - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00}, - CreateReader({Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01, - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})}, - ValidTestParam{ - {Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_16BIT), - 0x00, 0x04, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01, - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00}, - CreateReader({Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01, - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})}, - ValidTestParam{ - {Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_32BIT), - 0x00, 0x00, 0x00, 0x04, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), - 0x01, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00}, - CreateReader({Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01, - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})}, -}; - -INSTANTIATE_TEST_CASE_P(ReadNext, ValidReadTest, ValuesIn(valid_values)); -TEST_P(ValidReadTest, Test) { - auto packet = ReaderPacket::Make(std::get<0>(GetParam())); - auto value = std::get<1>(GetParam()); - - DataElementReader reader(packet->begin(), packet->end()); - auto read_value = reader.ReadNext(); - - ASSERT_EQ(value, read_value); - - // Test that there is no additional data to read. - ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate())); -} - -// Test that a nested reader is correctly bounded and can't read past its -// defined end. -TEST(ReadNext, BoundedSubreaderTest) { - std::vector payload = { - // Subsequence descriptor byte. - Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_8BIT), - // Subsequence length. - 0x04, - // Subsequence that contains two booleans with values true and false. - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01, - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00, - // Additional int16 at the end of the original sequence. - Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2), 0x01, 0x23}; - - auto packet = ReaderPacket::Make(payload); - DataElementReader reader(packet->begin(), packet->end()); - - // The first thing read should be the subsequence. - auto data_element = reader.ReadNext(); - ASSERT_TRUE(std::holds_alternative(data_element)); - - // Check that the subsequence matches the premade sequence. - auto subreader = std::get(data_element); - data_element = subreader.ReadNext(); - ASSERT_TRUE(std::holds_alternative(data_element)); - ASSERT_TRUE(std::get(data_element)); - data_element = subreader.ReadNext(); - ASSERT_TRUE(std::holds_alternative(data_element)); - ASSERT_FALSE(std::get(data_element)); - - // Check that there is no additional data to be read from the subreader. - ASSERT_EQ(subreader.ReadNext(), DataElement(std::monostate())); - - // Check that we can still read the int16 from the original reader. - data_element = reader.ReadNext(); - ASSERT_TRUE(std::holds_alternative(data_element)); - auto int16_value = std::get(data_element); - ASSERT_EQ(int16_value, 0x0123); - - // Check that there is no additional data to be read from the base reader. - ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate())); -} - -// Test that trying to read an empty packet fails. -TEST(ReadNext, NoDataTest) { - auto packet = ReaderPacket::Make({}); - DataElementReader reader(packet->begin(), packet->end()); - - ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate())); -} - -// Test that using a reserved value for type fails. -TEST(ReadNext, InvalidTypeTest) { - auto packet = ReaderPacket::Make({0xFF}); - DataElementReader reader(packet->begin(), packet->end()); - - ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate())); -} - -// Test all invalid parses due to incorrect lengths or invalid sizes. All tests -// should return std::monostate. -using InvalidTestParam = std::vector; -class InvalidReadTest : public TestWithParam {}; - -std::vector invalid_values = { - // Boolean Tests: - // Invalid size field. - InvalidTestParam{ - Desc(DataElementType::BOOLEAN, DataElementSize::BYTE2), - }, - // Insufficient data. - InvalidTestParam{Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1)}, - - // Signed Integer Tests: - // Invalid size field. - InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::ADDITIONAL_8BIT)}, - // 1 byte insufficient data. - InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE1)}, - // 2 byte insufficient data. - InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2), 0x00}, - // 4 byte insufficient data. - InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE4), 0x00, 0x00, - 0x00}, - // 8 Byte insufficient data. - InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE8), 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}, - // 16 Byte insufficient data. - InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE16), 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - // Unsigned Integer Tests: - // Invalid size field. - InvalidTestParam{Desc(DataElementType::UNSIGNED_INT, DataElementSize::ADDITIONAL_8BIT)}, - // 1 byte insufficient data. - InvalidTestParam{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE1)}, - // 2 byte insufficient data. - InvalidTestParam{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE2), 0x00}, - // 4 byte insufficient data. - InvalidTestParam{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE4), 0x00, 0x00, - 0x00}, - // 8 Byte insufficient data. - InvalidTestParam{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE8), 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}, - // 16 Byte insufficient data. - InvalidTestParam{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE16), 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - // UUID Tests: - // Invalid size field. - InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::ADDITIONAL_8BIT)}, - // 2 byte insufficient data. - InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE2), 0x00}, - // 4 byte insufficient data. - InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE4), 0x00, 0x00, 0x00}, - // 16 Byte insufficient data. - InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE16), 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - - // String Tests: - // Invalid size field. - InvalidTestParam{Desc(DataElementType::STRING, DataElementSize::BYTE1)}, - // Insufficient data for additional 8 bits len. - InvalidTestParam{Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT)}, - // Insufficient data for additional 16 bits len. - InvalidTestParam{ - Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_16BIT), - 0x00, - }, - // Insufficient data for additional 32 bit len. - InvalidTestParam{ - Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_32BIT), - 0x00, - 0x00, - 0x00, - }, - // Insufficient data for reported length. - InvalidTestParam{Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT), 0x04, '1', - '2', '3'}, - - // Nested Data Element List Tests: - // Invalid size field. - InvalidTestParam{Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::BYTE1)}, - // Insufficient data for additional 8 bits len. - InvalidTestParam{ - Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_8BIT)}, - // Insufficient data for additional 16 bits len. - InvalidTestParam{ - Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_16BIT), - 0x00, - }, - // Insufficient data for additional 32 bit len. - InvalidTestParam{ - Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_32BIT), - 0x00, - 0x00, - 0x00, - }, - // Insufficient data for reported length. - InvalidTestParam{ - Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::ADDITIONAL_8BIT), - 0x04, 0x00, 0x00, 0x00}, - - // Unhandled Data Element Types Tests: - // NOTE: These tests should go away as we begin to handle the types. - // Nil Type. - InvalidTestParam{Desc(DataElementType::NIL, DataElementSize::BYTE1)}, - // Data Element Alternative List Type. - InvalidTestParam{ - Desc(DataElementType::DATA_ELEMENT_ALTERNATIVE, DataElementSize::ADDITIONAL_8BIT), - 0x00}, - // URL Type. - InvalidTestParam{Desc(DataElementType::URL, DataElementSize::ADDITIONAL_8BIT), 0x00}}; - -INSTANTIATE_TEST_CASE_P(ReadNext, InvalidReadTest, ValuesIn(invalid_values)); -TEST_P(InvalidReadTest, Test) { - auto packet = ReaderPacket::Make(GetParam()); - DataElementReader reader(packet->begin(), packet->end()); - - ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate())); -} - -// Test that trying to read from a reader with start > end crashes. -TEST(DataElementReader, BadBoundsDeathTest) { - auto packet = ReaderPacket::Make({0x00, 0x00, 0x00, 0x00}); - DataElementReader reader(packet->end(), packet->begin()); - ASSERT_DEATH(reader.ReadNext(), "Beginning of buffer is past end of buffer."); -} - -} // namespace sdp -} // namespace bluetooth diff --git a/system/profile/sdp/sdp_common.h b/system/profile/sdp/sdp_common.h deleted file mode 100644 index 4a07a6306d4..00000000000 --- a/system/profile/sdp/sdp_common.h +++ /dev/null @@ -1,95 +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 - -namespace bluetooth { -namespace sdp { - -enum class PduId : uint8_t { - RESERVED = 0x00, - ERROR = 0x01, - SERVICE_SEARCH_REQUEST = 0x02, - SERVICE_SEARCH_RESPONSE = 0x03, - SERVICE_ATTRIBUTE_REQUEST = 0x04, - SERVICE_ATTRIBUTE_RESPONSE = 0x05, - SERVICE_SEARCH_ATTRIBUTE_REQUEST = 0x06, - SERVICE_SEARCH_ATTRIBUTE_RESPONSE = 0x07, - MAX_VALUE = 0x07, -}; - -enum class AttributeId : uint16_t { - SERVICE_RECORD_HANDLE = 0x0000, - SERVICE_CLASS_ID_LIST = 0x0001, - SERVICE_RECORD_STATE = 0x0002, - SERVICE_ID = 0x0003, - PROTOCOL_DESCRIPTOR_LIST = 0x0004, - BROWSE_GROUP_LIST = 0x0005, - LANGUAGE_BASE_ATTRIBUTE_ID_LIST = 0x0006, - SERVICE_INFO_TIME_TO_LIVE = 0x0007, - SERVICE_AVAILABILITY = 0x0008, - PROFILE_DESCRIPTOR_LIST = 0x0009, - DOCUMENTATION_URL = 0x000A, - CLIENT_EXECUTABLE_URL = 0x000B, - ICON_URL = 0x000C, - ADDITIONAL_PROTOCOL_DESCRIPTOR_LIST = 0x000D, - - // The following attributes are only used in the SDP server service record. - // They are only valid if ServiceDiscoveryServerServiceClassID is in the - // ServiceClassIDList. See Bluetooth Core v5.0 Section 5.2. - VERSION_NUMBER_LIST = 0x0200, - SERVICE_DATABASE_STATE = 0x0201, -}; - -// The Attribute ID's of these attributes are calculated by adding the offset -// value for the attribute to the attribute ID base (contained in the -// LanguageBaseAttributeIDList attribute value). -enum AttributeIdOffset : uint16_t { - SERVICE_NAME = 0x0000, - SERVICE_DESCRIPTION = 0x0001, - PROVIDER_NAME = 0x0002, -}; - -// Constant that define the different types of data element. -enum class DataElementType : uint8_t { - NIL = 0x00, - UNSIGNED_INT = 0x01, - SIGNED_INT = 0x02, - UUID = 0x03, - STRING = 0x04, - BOOLEAN = 0x05, - DATA_ELEMENT_SEQUENCE = 0x06, - DATA_ELEMENT_ALTERNATIVE = 0x07, - URL = 0x08, - MAX_VALUE = 0x08, -}; - -// Constant that define the different sizes of data element. -enum class DataElementSize : uint8_t { - BYTE1 = 0x0, // Exception: If the data element is NIL then size is 0 bytes - BYTE2 = 0x1, - BYTE4 = 0x2, - BYTE8 = 0x3, - BYTE16 = 0x4, - // The size types below represent that the first X bits of the value - // represents the size of the remaining data. - ADDITIONAL_8BIT = 0x5, - ADDITIONAL_16BIT = 0x6, - ADDITIONAL_32BIT = 0x7, -}; - -} // namespace sdp -} // namespace bluetooth diff --git a/system/profile/sdp/sdp_logging_helper.h b/system/profile/sdp/sdp_logging_helper.h deleted file mode 100644 index 4a8d1782969..00000000000 --- a/system/profile/sdp/sdp_logging_helper.h +++ /dev/null @@ -1,128 +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 - -#include - -#include -#include -#include -#include -#include - -#include "macros.h" -#include "sdp_common.h" - -namespace bluetooth { -namespace sdp { - -inline std::string PduIdText(const PduId& id) { - switch (id) { - CASE_RETURN_TEXT(PduId::RESERVED); - CASE_RETURN_TEXT(PduId::ERROR); - CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_REQUEST); - CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_RESPONSE); - CASE_RETURN_TEXT(PduId::SERVICE_ATTRIBUTE_REQUEST); - CASE_RETURN_TEXT(PduId::SERVICE_ATTRIBUTE_RESPONSE); - CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_ATTRIBUTE_REQUEST); - CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_ATTRIBUTE_RESPONSE); - default: - return fmt::format("Unknown PduId: 0x{:x}", (uint8_t)id); - } -} - -inline std::ostream& operator<<(std::ostream& os, const PduId& id) { return os << PduIdText(id); } - -inline std::string AttributeIdText(const AttributeId& id) { - switch (id) { - CASE_RETURN_TEXT(AttributeId::SERVICE_RECORD_HANDLE); - CASE_RETURN_TEXT(AttributeId::SERVICE_CLASS_ID_LIST); - CASE_RETURN_TEXT(AttributeId::SERVICE_RECORD_STATE); - CASE_RETURN_TEXT(AttributeId::SERVICE_ID); - CASE_RETURN_TEXT(AttributeId::PROTOCOL_DESCRIPTOR_LIST); - CASE_RETURN_TEXT(AttributeId::BROWSE_GROUP_LIST); - CASE_RETURN_TEXT(AttributeId::LANGUAGE_BASE_ATTRIBUTE_ID_LIST); - CASE_RETURN_TEXT(AttributeId::SERVICE_INFO_TIME_TO_LIVE); - CASE_RETURN_TEXT(AttributeId::SERVICE_AVAILABILITY); - CASE_RETURN_TEXT(AttributeId::PROFILE_DESCRIPTOR_LIST); - CASE_RETURN_TEXT(AttributeId::DOCUMENTATION_URL); - CASE_RETURN_TEXT(AttributeId::CLIENT_EXECUTABLE_URL); - CASE_RETURN_TEXT(AttributeId::ICON_URL); - CASE_RETURN_TEXT(AttributeId::ADDITIONAL_PROTOCOL_DESCRIPTOR_LIST); - CASE_RETURN_TEXT(AttributeId::VERSION_NUMBER_LIST); - CASE_RETURN_TEXT(AttributeId::SERVICE_DATABASE_STATE); - default: - return fmt::format("Unknown AttributeId: 0x{:x}", (uint16_t)id); - } -} - -inline std::ostream& operator<<(std::ostream& os, const AttributeId& id) { - return os << AttributeIdText(id); -} - -inline std::string DataElementTypeText(const DataElementType& type) { - switch (type) { - CASE_RETURN_TEXT(DataElementType::NIL); - CASE_RETURN_TEXT(DataElementType::UNSIGNED_INT); - CASE_RETURN_TEXT(DataElementType::SIGNED_INT); - CASE_RETURN_TEXT(DataElementType::UUID); - CASE_RETURN_TEXT(DataElementType::STRING); - CASE_RETURN_TEXT(DataElementType::BOOLEAN); - CASE_RETURN_TEXT(DataElementType::DATA_ELEMENT_SEQUENCE); - CASE_RETURN_TEXT(DataElementType::DATA_ELEMENT_ALTERNATIVE); - CASE_RETURN_TEXT(DataElementType::URL); - default: - return fmt::format("Unknown DataElementType: 0x{:x}", (uint8_t)type); - } -} - -inline std::ostream& operator<<(std::ostream& os, const DataElementType& type) { - return os << DataElementTypeText(type); -} - -inline std::string DataElementSizeText(const DataElementSize& size) { - switch (size) { - CASE_RETURN_TEXT(DataElementSize::BYTE1); - CASE_RETURN_TEXT(DataElementSize::BYTE2); - CASE_RETURN_TEXT(DataElementSize::BYTE4); - CASE_RETURN_TEXT(DataElementSize::BYTE8); - CASE_RETURN_TEXT(DataElementSize::BYTE16); - CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_8BIT); - CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_16BIT); - CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_32BIT); - default: - return fmt::format("Unknown DataElementSize: 0x{:x}", (uint8_t)size); - } -} - -inline std::ostream& operator<<(std::ostream& os, const DataElementSize& size) { - return os << DataElementSizeText(size); -} - -} // namespace sdp -} // namespace bluetooth - -namespace fmt { -template <> -struct formatter : ostream_formatter {}; -template <> -struct formatter : ostream_formatter {}; -template <> -struct formatter : ostream_formatter {}; -template <> -struct formatter : ostream_formatter {}; -} // namespace fmt -- GitLab From 0cbc81391dc1955b6d7f12bc84fbbc85101393a3 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 14:43:04 -0700 Subject: [PATCH 452/875] Remove public visibility on BluetoothPacketSources Bug: 370993756 Test: m com.android.btservices Flag: EXEMPT, build change Change-Id: If40de03557ed3010d39bba12e4f8f032bf73ea09 --- system/gd/packet/Android.bp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/system/gd/packet/Android.bp b/system/gd/packet/Android.bp index 851afb6ccfb..c4504a62c83 100644 --- a/system/gd/packet/Android.bp +++ b/system/gd/packet/Android.bp @@ -19,7 +19,10 @@ filegroup { "raw_builder.cc", "view.cc", ], - visibility: ["//visibility:public"], + visibility: [ + "//hardware/interfaces/bluetooth/aidl/vts", + "//packages/modules/Bluetooth/system:__subpackages__", + ], } filegroup { -- GitLab From 9e8859a8008ba1f58b5ec7698d6b1fb19e346d48 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 24 Oct 2024 16:48:52 -0700 Subject: [PATCH 453/875] Jarjar the flag in bluetooth modules Bug: 361398259 Flag: Exempt -- flag infrastructure Test: m com.android.btservices + test mapping presubmit Change-Id: I00f5e405f935a7f17cb00748fee5bdbfae7b324b --- android/app/tests/unit/Android.bp | 1 + flags/Android.bp | 6 +- framework/Android.bp | 5 +- framework/jarjar-rules.txt | 1 + framework/tests/unit/Android.bp | 6 +- .../bluetooth/CallbackWrapperTest.java | 4 +- .../android/bluetooth/le/ScanRecordTest.java | 56 ++++++++++++++----- 7 files changed, 54 insertions(+), 25 deletions(-) diff --git a/android/app/tests/unit/Android.bp b/android/app/tests/unit/Android.bp index e65bf03f659..979650019db 100644 --- a/android/app/tests/unit/Android.bp +++ b/android/app/tests/unit/Android.bp @@ -41,6 +41,7 @@ java_defaults { "truth", ], + jarjar_rules: ":bluetooth-jarjar-rules", asset_dirs: ["src/com/android/bluetooth/btservice/storage/schemas"], // Include all test java files. diff --git a/flags/Android.bp b/flags/Android.bp index 56acb5c0d8e..f08db2fb78c 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -63,11 +63,7 @@ java_aconfig_library { aconfig_declarations: "bluetooth_aconfig_flags", visibility: [ "//cts/tests/tests/bluetooth:__subpackages__", - "//packages/modules/Bluetooth/android/app", - "//packages/modules/Bluetooth/framework", - "//packages/modules/Bluetooth/framework/tests/bumble", - "//packages/modules/Bluetooth/framework/tests/util", - "//packages/modules/Bluetooth/service:__subpackages__", + "//packages/modules/Bluetooth:__subpackages__", ], apex_available: [ "com.android.btservices", diff --git a/framework/Android.bp b/framework/Android.bp index 5be5ed9c249..2eca8df89bc 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -10,6 +10,7 @@ filegroup { "java/**/*.java", ], path: "java", + visibility: ["//packages/modules/Bluetooth/framework/tests/unit"], } // defaults shared between `framework-bluetooth` & `framework-bluetooth-pre-jarjar` @@ -49,6 +50,7 @@ java_library { sdk_version: "module_current", libs: ["framework-annotations-lib"], installable: false, + visibility: ["//packages/modules/Bluetooth:__subpackages__"], } // post-jarjar version of framework-bluetooth @@ -85,7 +87,6 @@ java_sdk_library { permitted_packages: [ "android.bluetooth", - "com.android.bluetooth.flags", "com.android.bluetooth.jarjar", ], plugins: [ @@ -149,7 +150,7 @@ java_defaults { // if sdk_version="" this gets automatically included, but here we need to add manually. "framework-res", ], - defaults_visibility: ["//visibility:public"], + defaults_visibility: ["//packages/modules/Bluetooth:__subpackages__"], } filegroup { diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt index 172bdd439ed..cff2b1aa312 100644 --- a/framework/jarjar-rules.txt +++ b/framework/jarjar-rules.txt @@ -10,3 +10,4 @@ rule android.hardware.radio.V1_0.** com.android.bluetooth.jarjar.@0 rule com.google.android.mms.** com.android.bluetooth.jarjar.@0 rule com.android.internal.util.** com.android.bluetooth.jarjar.@0 rule com.android.modules.expresslog.** com.android.bluetooth.jarjar.@0 +rule com.android.bluetooth.flags.** com.android.bluetooth.jarjar.@0 diff --git a/framework/tests/unit/Android.bp b/framework/tests/unit/Android.bp index 96025ab7fb4..39b3c298615 100644 --- a/framework/tests/unit/Android.bp +++ b/framework/tests/unit/Android.bp @@ -5,8 +5,7 @@ package { android_test { name: "FrameworkBluetoothTests", - defaults: ["framework-bluetooth-tests-defaults"], - + sdk_version: "module_current", min_sdk_version: "Tiramisu", target_sdk_version: "current", @@ -19,11 +18,14 @@ android_test { libs: [ "android.test.base.stubs", "android.test.runner.stubs", + "framework-annotations-lib", + "framework-bluetooth.impl", ], static_libs: [ "androidx.test.ext.truth", "androidx.test.rules", "flag-junit", + "framework-bluetooth-pre-jarjar", "frameworks-base-testutils", "junit", "mockito-target", diff --git a/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java b/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java index a55fb033bc8..0721ead366e 100644 --- a/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java +++ b/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java @@ -22,8 +22,6 @@ import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import android.os.Handler; -import android.os.HandlerExecutor; import android.os.test.TestLooper; import androidx.test.filters.SmallTest; @@ -72,7 +70,7 @@ public class CallbackWrapperTest { @Before public void setUp() { mLooper = new TestLooper(); - mExecutor = new HandlerExecutor(new Handler(mLooper.getLooper())); + mExecutor = mLooper.getNewExecutor(); mCallbackExecutorMap = new HashMap(); mCallbackWrapper = new CallbackWrapper(mRegisterConsumer, mUnregisterConsumer, mCallbackExecutorMap); diff --git a/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java b/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java index ac228c6c9d2..a690e510f52 100644 --- a/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java @@ -22,7 +22,6 @@ import android.os.ParcelUuid; import android.platform.test.flag.junit.SetFlagsRule; import com.android.bluetooth.flags.Flags; -import com.android.internal.util.HexDump; import com.android.modules.utils.BytesMatcher; import org.junit.Rule; @@ -70,11 +69,10 @@ public class ScanRecordTest { final List found = new ArrayList<>(); final Predicate matcher = (v) -> { - found.add(HexDump.toHexString(v)); + found.add(toHexString(v)); return false; }; - ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(RECORD_URL)) - .matchesAnyField(matcher); + ScanRecord.parseFromBytes(hexStringToByteArray(RECORD_URL)).matchesAnyField(matcher); assertThat(found) .isEqualTo( @@ -112,11 +110,10 @@ public class ScanRecordTest { final List found = new ArrayList<>(); final Predicate matcher = (v) -> { - found.add(HexDump.toHexString(v)); + found.add(toHexString(v)); return false; }; - ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(RECORD_IBEACON)) - .matchesAnyField(matcher); + ScanRecord.parseFromBytes(hexStringToByteArray(RECORD_IBEACON)).matchesAnyField(matcher); assertThat(found) .isEqualTo( @@ -265,16 +262,49 @@ public class ScanRecordTest { } private static void assertMatchesAnyField(String record, BytesMatcher matcher) { - assertThat( - ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(record)) - .matchesAnyField(matcher)) + assertThat(ScanRecord.parseFromBytes(hexStringToByteArray(record)).matchesAnyField(matcher)) .isTrue(); } private static void assertNotMatchesAnyField(String record, BytesMatcher matcher) { - assertThat( - ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(record)) - .matchesAnyField(matcher)) + assertThat(ScanRecord.parseFromBytes(hexStringToByteArray(record)).matchesAnyField(matcher)) .isFalse(); } + + private static final char[] HEX_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + private static String toHexString(byte[] array) { + char[] buf = new char[array.length * 2]; + + int bufIndex = 0; + for (int i = 0; i < array.length; i++) { + byte b = array[i]; + buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; + buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; + } + + return new String(buf); + } + + private static int toByte(char c) { + if (c >= '0' && c <= '9') return (c - '0'); + if (c >= 'A' && c <= 'F') return (c - 'A' + 10); + if (c >= 'a' && c <= 'f') return (c - 'a' + 10); + + throw new RuntimeException("Invalid hex char '" + c + "'"); + } + + private static byte[] hexStringToByteArray(String hexString) { + int length = hexString.length(); + byte[] buffer = new byte[length / 2]; + + for (int i = 0; i < length; i += 2) { + buffer[i / 2] = + (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1))); + } + + return buffer; + } } -- GitLab From 9a1379eac7eec08ce4b8357ad50ed76ee03b67a8 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 15:22:26 -0700 Subject: [PATCH 454/875] Factorize system/packet/avrcp/tests/fuzzers/Android.bp Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, build change Change-Id: I6e9a6f9f704896b6191e68e466796e7fa08a942d --- system/packet/tests/fuzzers/Android.bp | 991 +++---------------------- 1 file changed, 99 insertions(+), 892 deletions(-) diff --git a/system/packet/tests/fuzzers/Android.bp b/system/packet/tests/fuzzers/Android.bp index e15bbdc9932..00ea544c828 100644 --- a/system/packet/tests/fuzzers/Android.bp +++ b/system/packet/tests/fuzzers/Android.bp @@ -7,11 +7,10 @@ package { default_applicable_licenses: ["system_bt_license"], } -cc_fuzz { - name: "avrcp_browse_packet_fuzzer", +cc_defaults { + name: "packet_avrcp_fuzz_defaults", defaults: ["fluoride_defaults"], host_supported: true, - include_dirs: [ "packages/modules/Bluetooth/system/", "packages/modules/Bluetooth/system/gd", @@ -21,13 +20,6 @@ cc_fuzz { "packages/modules/Bluetooth/system/packet/tests", "packages/modules/Bluetooth/system/packet/tests/avrcp", ], - srcs: [ - "avrcp_browse_packet_fuzzer.cc", - - ], - - corpus: ["corpus/avrcp_browse_packets_corpus/*"], - static_libs: [ "lib-bt-packets", "lib-bt-packets-avrcp", @@ -47,961 +39,176 @@ cc_fuzz { } cc_fuzz { - name: "change_path_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - //system/libbase/include/android-base" - srcs: [ - "change_path_req_fuzzer.cc", - - ], + name: "avrcp_browse_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["avrcp_browse_packet_fuzzer.cc"], + corpus: ["corpus/avrcp_browse_packets_corpus/*"], +} +cc_fuzz { + name: "change_path_req_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["change_path_req_fuzzer.cc"], corpus: ["corpus/change_path_req_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_capabilities_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_capabilities_req_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_capabilities_req_fuzzer.cc"], corpus: ["corpus/get_capabilities_req_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_capabilities_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_capabilities_res_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_capabilities_res_fuzzer.cc"], corpus: ["corpus/get_capabilities_res_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_item_attributes_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_item_attributes_req_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_item_attributes_req_fuzzer.cc"], corpus: ["corpus/get_item_attributes_req_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_play_status_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_play_status_req_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_play_status_req_fuzzer.cc"], corpus: ["get_play_status_req_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_total_number_of_items_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_total_number_of_items_req_fuzzer.cc"], + corpus: ["corpus/get_total_number_of_items_req_corpus/*"], +} - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], +cc_fuzz { + name: "pass_through_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["pass_through_packet_fuzzer.cc"], + corpus: ["corpus/pass_through_packet_corpus/*"], +} - srcs: [ - "get_total_number_of_items_req_fuzzer.cc", +cc_fuzz { + name: "play_item_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["play_item_packet_fuzzer.cc"], + corpus: ["corpus/play_item_packet_corpus/*"], +} - ], +cc_fuzz { + name: "register_notification_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["register_notification_packet_fuzzer.cc"], + corpus: ["corpus/register_notification_packet_corpus/*"], +} - corpus: ["corpus/get_total_number_of_items_req_corpus/*"], +cc_fuzz { + name: "set_absolute_volume_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["set_absolute_volume_packet_fuzzer.cc"], + corpus: ["corpus/set_absolute_volume_packet_corpus/*"], +} - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], +cc_fuzz { + name: "set_addressed_player_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["set_addressed_player_packet_fuzzer.cc"], + corpus: ["corpus/set_addressed_player_packet_corpus/*"], } cc_fuzz { - name: "pass_through_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, + name: "set_browsed_player_req_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["set_browsed_player_req_fuzzer.cc"], + corpus: ["corpus/set_browsed_player_req_corpus/*"], +} - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], +cc_fuzz { + name: "vendor_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["vendor_packet_fuzzer.cc"], + corpus: ["corpus/vendor_packet_corpus/*"], +} - srcs: [ - "pass_through_packet_fuzzer.cc", +cc_fuzz { + name: "avrcp_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["avrcp_packet_fuzzer.cc"], + corpus: ["corpus/avrcp_packet_corpus/*"], +} - ], +cc_fuzz { + name: "reject_packet_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["reject_packet_fuzzer.cc"], + corpus: ["corpus/reject_packet_corpus/*"], +} - corpus: ["corpus/pass_through_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "play_item_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "play_item_packet_fuzzer.cc", - - ], - - corpus: ["corpus/play_item_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "register_notification_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "register_notification_packet_fuzzer.cc", - - ], - - corpus: ["corpus/register_notification_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "set_absolute_volume_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "set_absolute_volume_packet_fuzzer.cc", - - ], - - corpus: ["corpus/set_absolute_volume_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "set_addressed_player_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "set_addressed_player_packet_fuzzer.cc", - - ], - - corpus: ["corpus/set_addressed_player_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "set_browsed_player_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "set_browsed_player_req_fuzzer.cc", - - ], - - corpus: ["corpus/set_browsed_player_req_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "vendor_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "vendor_packet_fuzzer.cc", - - ], - - corpus: ["corpus/vendor_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "avrcp_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "avrcp_packet_fuzzer.cc", - - ], - - corpus: ["corpus/avrcp_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "reject_packet_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "reject_packet_fuzzer.cc", - - ], - - corpus: ["corpus/reject_packet_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "get_element_attributes_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_element_attributes_req_packet_fuzzer.cc", - - ], - - corpus: ["corpus/get_element_attributes_req_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], -} - -cc_fuzz { - name: "change_path_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "change_path_res_fuzzer.cc", - - ], +cc_fuzz { + name: "get_element_attributes_req_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_element_attributes_req_packet_fuzzer.cc"], + corpus: ["corpus/get_element_attributes_req_corpus/*"], +} +cc_fuzz { + name: "change_path_res_fuzzer", + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["change_path_res_fuzzer.cc"], corpus: ["corpus/change_path_res_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_element_attributes_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_element_attributes_res_packet_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_element_attributes_res_packet_fuzzer.cc"], corpus: ["corpus/get_element_attributes_res_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_folder_items_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_folder_items_res_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_folder_items_res_fuzzer.cc"], corpus: ["corpus/get_folder_items_res_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_folder_items_req_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_folder_items_req_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_folder_items_req_fuzzer.cc"], corpus: ["corpus/get_folder_items_req_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_item_attributes_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_item_attributes_res_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_item_attributes_res_fuzzer.cc"], corpus: ["corpus/get_item_attributes_res_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_play_status_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_play_status_res_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_play_status_res_fuzzer.cc"], corpus: ["corpus/get_play_status_res_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "get_total_number_of_items_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "get_total_number_of_items_res_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["get_total_number_of_items_res_fuzzer.cc"], corpus: ["corpus/get_total_number_of_items_res_corpus/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } cc_fuzz { name: "set_browsed_player_res_fuzzer", - defaults: ["fluoride_defaults"], - host_supported: true, - - include_dirs: [ - "packages/modules/Bluetooth/system/", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/packet/base", - "packages/modules/Bluetooth/system/packet/include", - "packages/modules/Bluetooth/system/packet/tests", - "packages/modules/Bluetooth/system/packet/tests/avrcp", - ], - - srcs: [ - "set_browsed_player_res_fuzzer.cc", - - ], - + defaults: ["packet_avrcp_fuzz_defaults"], + srcs: ["set_browsed_player_res_fuzzer.cc"], corpus: ["corpus/set_browsed_player_res_fuzzer/*"], - - static_libs: [ - "lib-bt-packets", - "lib-bt-packets-avrcp", - "lib-bt-packets-base", - "libbluetooth_log", - "libchrome", - "libgmock", - ], - cflags: [ - "-Wno-missing-prototypes", - "-Wno-unused-parameter", - ], - shared_libs: [ - "libbase", - "liblog", - ], } -- GitLab From 031daf24d36f8d8d4db258b8e15b1e5bbfb77823 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 23 Oct 2024 13:51:36 -0700 Subject: [PATCH 455/875] btif_a2dp_source: Schedule internal calls to bt_main_thread Currently all internal calls of the btif_a2dp_source module are being scheduled to the bt_a2dp_source_worker_thread, which also runs the audio encoder. This is causing many races with the bta_av_co module which runs on the bt_main_thread. This change pushes all of the internal calls to the main thread to keep only the encoder running in the worker thread. The only drawback is the required addition of a mutex to control access to the internal variables between the main and worker threads. Bug: 374166531 Bug: 352246888 Test: m com.android.btservices Test: Manual streaming tests Flag: com.android.bluetooth.flags.a2dp_source_threading_fix Change-Id: Ib49931404258f016f54e46f54842988608e271bf --- system/audio_hal_interface/a2dp_encoding.h | 2 + system/btif/src/btif_a2dp_source.cc | 76 +++++++++++++--------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/system/audio_hal_interface/a2dp_encoding.h b/system/audio_hal_interface/a2dp_encoding.h index d23d023e35b..d1de4138b20 100644 --- a/system/audio_hal_interface/a2dp_encoding.h +++ b/system/audio_hal_interface/a2dp_encoding.h @@ -46,6 +46,8 @@ enum class BluetoothAudioStatus { /// Implements callbacks for the BT Audio HAL to start, suspend and configure /// the audio stream. Completion of the requested operation is indicated /// by the methods ack_stream_started, ack_stream_suspended. +/// +/// The callbacks are always invoked from one of the binder threads. class BluetoothAudioPort { public: virtual ~BluetoothAudioPort() {} diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index d1e425ed039..ae296a4249b 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -55,6 +55,7 @@ #include "stack/include/bt_hdr.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_status.h" +#include "stack/include/main_thread.h" #include "types/raw_address.h" using bluetooth::audio::a2dp::BluetoothAudioStatus; @@ -227,9 +228,14 @@ private: BtifA2dpSource::RunState state_; }; +/// Source worker thread created to run the CPU heavy encoder calls. +/// Exactly three functions are executed on this thread: +/// - btif_a2dp_source_audio_handle_timer +/// - btif_a2dp_source_read_callback +/// - btif_a2dp_source_enqueue_callback static bluetooth::common::MessageLoopThread btif_a2dp_source_thread("bt_a2dp_source_worker_thread"); -static BtifA2dpSource btif_a2dp_source_cb; +static BtifA2dpSource btif_a2dp_source_cb; static uint8_t btif_a2dp_source_dynamic_audio_buffer_size = MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ; static void btif_a2dp_source_init_delayed(void); @@ -313,12 +319,19 @@ static void btif_a2dp_source_accumulate_stats(BtifMediaStats* src, BtifMediaStat src->Reset(); } +/// Select the thread to run a2dp source actions on (a2dp encoder excluded). +static bluetooth::common::MessageLoopThread* local_thread() { + return com::android::bluetooth::flags::a2dp_source_threading_fix() ? get_main_thread() + : &btif_a2dp_source_thread; +} + bool btif_a2dp_source_init(void) { log::info(""); // Start A2DP Source media task btif_a2dp_source_thread.StartUp(); - btif_a2dp_source_thread.DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_init_delayed)); + + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_init_delayed)); return true; } @@ -384,8 +397,7 @@ static void btif_a2dp_source_init_delayed(void) { // the provider needs to be initialized earlier in order to ensure // get_a2dp_configuration and parse_a2dp_configuration can be // invoked before the stream is started. - bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port, - btif_av_is_a2dp_offload_enabled()); + bluetooth::audio::a2dp::init(local_thread(), &a2dp_audio_port, btif_av_is_a2dp_offload_enabled()); } static bool btif_a2dp_source_startup(void) { @@ -401,7 +413,7 @@ static bool btif_a2dp_source_startup(void) { btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX); // Schedule the rest of the operations - btif_a2dp_source_thread.DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_startup_delayed)); + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_startup_delayed)); return true; } @@ -413,7 +425,7 @@ static void btif_a2dp_source_startup_delayed() { log::fatal("unable to enable real time scheduling"); #endif } - if (!bluetooth::audio::a2dp::init(&btif_a2dp_source_thread, &a2dp_audio_port, + if (!bluetooth::audio::a2dp::init(local_thread(), &a2dp_audio_port, btif_av_is_a2dp_offload_enabled())) { log::warn("Failed to setup the bluetooth audio HAL"); } @@ -426,7 +438,7 @@ bool btif_a2dp_source_start_session(const RawAddress& peer_address, btif_a2dp_source_audio_tx_flush_req(); - if (btif_a2dp_source_thread.DoInThread( + if (local_thread()->DoInThread( FROM_HERE, base::BindOnce(&btif_a2dp_source_start_session_delayed, peer_address, std::move(peer_ready_promise)))) { return true; @@ -491,8 +503,8 @@ bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address, bool btif_a2dp_source_end_session(const RawAddress& peer_address) { log::info("peer_address={} state={}", peer_address, btif_a2dp_source_cb.StateStr()); - btif_a2dp_source_thread.DoInThread( - FROM_HERE, base::BindOnce(&btif_a2dp_source_end_session_delayed, peer_address)); + local_thread()->DoInThread(FROM_HERE, + base::BindOnce(&btif_a2dp_source_end_session_delayed, peer_address)); btif_a2dp_source_cleanup_codec(); return true; } @@ -518,7 +530,7 @@ static void btif_a2dp_source_end_session_delayed(const RawAddress& peer_address) void btif_a2dp_source_allow_low_latency_audio(bool allowed) { log::info("allowed={}", allowed); - btif_a2dp_source_thread.DoInThread( + local_thread()->DoInThread( FROM_HERE, base::BindOnce(bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed, allowed)); } @@ -534,9 +546,8 @@ void btif_a2dp_source_shutdown(std::promise shutdown_complete_promise) { /* Make sure no channels are restarted while shutting down */ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateShuttingDown); - btif_a2dp_source_thread.DoInThread( - FROM_HERE, - base::BindOnce(&btif_a2dp_source_shutdown_delayed, std::move(shutdown_complete_promise))); + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_shutdown_delayed, + std::move(shutdown_complete_promise))); } static void btif_a2dp_source_shutdown_delayed(std::promise shutdown_complete_promise) { @@ -614,8 +625,9 @@ static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) { log::error("Cannot stream audio: cannot set active peer to {}", peer_address); return; } - btif_a2dp_source_cb.encoder_interface = bta_av_co_get_encoder_interface(peer_address); - if (btif_a2dp_source_cb.encoder_interface == nullptr) { + + const tA2DP_ENCODER_INTERFACE* encoder_interface = bta_av_co_get_encoder_interface(peer_address); + if (encoder_interface == nullptr) { log::error("Cannot stream audio: no source encoder interface"); return; } @@ -626,11 +638,11 @@ static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) { return; } - btif_a2dp_source_cb.encoder_interface->encoder_init(&peer_params, a2dp_codec_config, - btif_a2dp_source_read_callback, - btif_a2dp_source_enqueue_callback); + encoder_interface->encoder_init(&peer_params, a2dp_codec_config, btif_a2dp_source_read_callback, + btif_a2dp_source_enqueue_callback); // Save a local copy of the encoder_interval_ms + btif_a2dp_source_cb.encoder_interface = encoder_interface; btif_a2dp_source_cb.encoder_interval_ms = btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms(); @@ -645,8 +657,7 @@ static void btif_a2dp_source_cleanup_codec() { log::info("state={}", btif_a2dp_source_cb.StateStr()); // Must stop media task first before cleaning up the encoder btif_a2dp_source_stop_audio_req(); - btif_a2dp_source_thread.DoInThread(FROM_HERE, - base::BindOnce(&btif_a2dp_source_cleanup_codec_delayed)); + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_cleanup_codec_delayed)); } static void btif_a2dp_source_cleanup_codec_delayed() { @@ -660,15 +671,13 @@ static void btif_a2dp_source_cleanup_codec_delayed() { void btif_a2dp_source_start_audio_req(void) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - btif_a2dp_source_thread.DoInThread(FROM_HERE, - base::BindOnce(&btif_a2dp_source_audio_tx_start_event)); + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_audio_tx_start_event)); } void btif_a2dp_source_stop_audio_req(void) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - btif_a2dp_source_thread.DoInThread(FROM_HERE, - base::BindOnce(&btif_a2dp_source_audio_tx_stop_event)); + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_audio_tx_stop_event)); } void btif_a2dp_source_encoder_user_config_update_req( @@ -677,7 +686,8 @@ void btif_a2dp_source_encoder_user_config_update_req( std::promise peer_ready_promise) { log::info("peer_address={} state={} {} codec_preference(s)", peer_address, btif_a2dp_source_cb.StateStr(), codec_user_preferences.size()); - if (!btif_a2dp_source_thread.DoInThread( + + if (!local_thread()->DoInThread( FROM_HERE, base::BindOnce(&btif_a2dp_source_encoder_user_config_update_event, peer_address, codec_user_preferences, std::move(peer_ready_promise)))) { @@ -723,9 +733,8 @@ static void btif_a2dp_source_encoder_user_config_update_event( void btif_a2dp_source_feeding_update_req(const btav_a2dp_codec_config_t& codec_audio_config) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - btif_a2dp_source_thread.DoInThread( - FROM_HERE, - base::BindOnce(&btif_a2dp_source_audio_feeding_update_event, codec_audio_config)); + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_audio_feeding_update_event, + codec_audio_config)); } static void btif_a2dp_source_audio_feeding_update_event( @@ -885,6 +894,12 @@ static void btif_a2dp_source_audio_tx_stop_event(void) { } } +/// Periodic task responsible for encoding the audio stream and forwarding +/// to the remote device. It will read PCM samples from the HAL provided FMQ, +/// encode them into audio frames. Runs on the source worker thread. +/// +/// The timer driving the periodic task is cancelled before any state cleanup +/// when the stream is ended. static void btif_a2dp_source_audio_handle_timer(void) { uint64_t timestamp_us = bluetooth::common::time_get_audio_server_tick_us(); uint64_t stats_timestamp_us = bluetooth::common::time_get_os_boottime_us(); @@ -911,6 +926,8 @@ static void btif_a2dp_source_audio_handle_timer(void) { btif_a2dp_source_cb.encoder_interval_ms * 1000); } +/// Callback invoked by the encoder for reading PCM audio data from the +/// Bluetooth Audio HAL. Runs on the source worker thread. static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) { if (!btif_a2dp_source_cb.sw_audio_is_encoding) { return 0; @@ -1030,8 +1047,7 @@ static void btif_a2dp_source_audio_tx_flush_event(void) { static bool btif_a2dp_source_audio_tx_flush_req(void) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - btif_a2dp_source_thread.DoInThread(FROM_HERE, - base::BindOnce(&btif_a2dp_source_audio_tx_flush_event)); + local_thread()->DoInThread(FROM_HERE, base::BindOnce(&btif_a2dp_source_audio_tx_flush_event)); return true; } -- GitLab From e100ef70d41f845ca959e19210b55c504480e0e8 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 22:49:41 +0000 Subject: [PATCH 456/875] system/stack/l2cap: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I9c17c0fe74e26d05fb25d07db3e4d9f738cc61b3 --- system/stack/acl/btm_acl.cc | 3 +- system/stack/fuzzers/l2cap_fuzzer.cc | 3 +- system/stack/include/l2cap_acl_interface.h | 3 -- .../stack/include/l2cap_hci_link_interface.h | 3 -- system/stack/l2cap/l2c_api.cc | 11 +---- system/stack/l2cap/l2c_ble.cc | 11 ++--- system/stack/l2cap/l2c_ble_conn_params.cc | 4 +- system/stack/l2cap/l2c_int.h | 6 ++- system/stack/l2cap/l2c_link.cc | 47 ++----------------- system/stack/l2cap/l2c_main.cc | 5 +- system/stack/l2cap/l2c_utils.cc | 33 ++----------- system/test/mock/mock_stack_l2cap_api.cc | 5 -- system/test/mock/mock_stack_l2cap_api.h | 11 ----- system/test/mock/mock_stack_l2cap_ble.cc | 6 --- system/test/mock/mock_stack_l2cap_ble.h | 14 ------ system/test/mock/mock_stack_l2cap_link.cc | 20 +++----- system/test/mock/mock_stack_l2cap_utils.cc | 10 ---- 17 files changed, 27 insertions(+), 168 deletions(-) diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 612fd9dc63f..0c52e80bb6a 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -76,6 +76,7 @@ #include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cdefs.h" #include "stack/include/main_thread.h" +#include "stack/l2cap/l2c_int.h" #include "types/hci_role.h" #include "types/raw_address.h" @@ -96,8 +97,6 @@ using bluetooth::legacy::hci::GetInterface; void BTM_update_version_info(const RawAddress& bd_addr, const remote_version_info& remote_version_info); -void l2c_link_hci_conn_comp(tHCI_STATUS status, uint16_t handle, const RawAddress& p_bda); - void BTM_db_reset(void); extern tBTM_CB btm_cb; diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc index fd68f984864..2c5c3d2cde6 100644 --- a/system/stack/fuzzers/l2cap_fuzzer.cc +++ b/system/stack/fuzzers/l2cap_fuzzer.cc @@ -36,6 +36,7 @@ #include "stack/include/l2cap_interface.h" #include "stack/include/l2cap_module.h" #include "stack/include/l2cdefs.h" +#include "stack/l2cap/l2c_int.h" #include "test/fake/fake_osi.h" #include "test/mock/mock_main_shim_entry.h" #include "test/mock/mock_stack_acl.h" @@ -161,8 +162,6 @@ constexpr uint16_t kSmpBrHndl = 0x0222; constexpr uint16_t kNumClassicAclBuffer = 100; constexpr uint16_t kNumLeAclBuffer = 100; -void l2c_link_hci_conn_comp(tHCI_STATUS status, uint16_t handle, const RawAddress& p_bda); - static void Fuzz(const uint8_t* data, size_t size) { memset(&btm_cb, 0, sizeof(btm_cb)); diff --git a/system/stack/include/l2cap_acl_interface.h b/system/stack/include/l2cap_acl_interface.h index 811b5c12880..7751d142556 100644 --- a/system/stack/include/l2cap_acl_interface.h +++ b/system/stack/include/l2cap_acl_interface.h @@ -32,9 +32,6 @@ void acl_write_automatic_flush_timeout(const RawAddress& bd_addr, uint16_t flush // ACL data received from HCI-ACL void l2c_rcv_acl_data(BT_HDR* p_msg); -// Segments is sent to HCI-ACL -void l2c_link_segments_xmitted(BT_HDR* p_msg); - void l2cu_resubmit_pending_sec_req(const RawAddress* p_bda); void l2c_packets_completed(uint16_t handle, uint16_t num_sent); diff --git a/system/stack/include/l2cap_hci_link_interface.h b/system/stack/include/l2cap_hci_link_interface.h index 978aadade57..8699d1aa038 100644 --- a/system/stack/include/l2cap_hci_link_interface.h +++ b/system/stack/include/l2cap_hci_link_interface.h @@ -47,9 +47,6 @@ void l2cble_notify_le_connection(const RawAddress& bda); void l2cble_use_preferred_conn_params(const RawAddress& bda); -void l2cble_process_rc_param_request_evt(uint16_t handle, uint16_t int_min, uint16_t int_max, - uint16_t latency, uint16_t timeout); - // Invoked when HCI mode is changed to HCI_MODE_ACTIVE or HCI_MODE_SNIFF void l2c_OnHciModeChangeSendPendingPackets(RawAddress remote); diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc index cb66ec209db..a233046a747 100644 --- a/system/stack/l2cap/l2c_api.cc +++ b/system/stack/l2cap/l2c_api.cc @@ -45,13 +45,11 @@ #include "stack/include/bt_hdr.h" #include "stack/include/bt_psm_types.h" #include "stack/include/btm_client_interface.h" +#include "stack/include/l2cap_module.h" #include "stack/include/main_thread.h" #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; extern fixed_queue_t* btu_general_alarm_queue; @@ -59,13 +57,6 @@ tL2C_AVDT_CHANNEL_INFO av_media_channels[MAX_ACTIVE_AVDT_CONN]; constexpr uint16_t L2CAP_LE_CREDIT_THRESHOLD = 64; -tBT_TRANSPORT l2c_get_transport_from_fixed_cid(uint16_t fixed_cid) { - if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID) { - return BT_TRANSPORT_LE; - } - return BT_TRANSPORT_BR_EDR; -} - uint16_t L2CA_RegisterWithSecurity(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu, uint16_t required_remote_mtu, diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index fe22262b89a..9d69e5ab36c 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -53,21 +53,18 @@ #include "stack/include/btm_log_history.h" #include "stack/include/btm_status.h" #include "stack/include/l2cap_acl_interface.h" +#include "stack/include/l2cap_controller_interface.h" +#include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_interface.h" #include "stack/include/l2cdefs.h" #include "stack/include/main_thread.h" #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; namespace { - constexpr char kBtmLogTag[] = "L2CAP"; - } extern tBTM_CB btm_cb; @@ -1280,8 +1277,8 @@ void l2cble_send_peer_disc_req(tL2C_CCB* p_ccb) { * Returns void * ******************************************************************************/ -void l2cble_sec_comp(RawAddress bda, tBT_TRANSPORT transport, void* /* p_ref_data */, - tBTM_STATUS btm_status) { +static void l2cble_sec_comp(RawAddress bda, tBT_TRANSPORT transport, void* /* p_ref_data */, + tBTM_STATUS btm_status) { tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE); tL2CAP_SEC_DATA* p_buf = NULL; uint8_t sec_act; diff --git a/system/stack/l2cap/l2c_ble_conn_params.cc b/system/stack/l2cap/l2c_ble_conn_params.cc index f617e59d5df..1e9d4ba7ab9 100644 --- a/system/stack/l2cap/l2c_ble_conn_params.cc +++ b/system/stack/l2cap/l2c_ble_conn_params.cc @@ -38,14 +38,12 @@ #include "stack/include/acl_api.h" #include "stack/include/btm_ble_api_types.h" #include "stack/include/btm_client_interface.h" +#include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_interface.h" #include "stack/include/main_thread.h" #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; void l2cble_start_conn_update(tL2C_LCB* p_lcb); diff --git a/system/stack/l2cap/l2c_int.h b/system/stack/l2cap/l2c_int.h index 2a43844dd7f..02a1fa66adf 100644 --- a/system/stack/l2cap/l2c_int.h +++ b/system/stack/l2cap/l2c_int.h @@ -784,11 +784,12 @@ void l2cu_adjust_out_mps(tL2C_CCB* p_ccb); /* Functions provided by l2c_link.cc *********************************** */ + void l2c_link_timeout(tL2C_LCB* p_lcb); void l2c_info_resp_timer_timeout(void* data); void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, uint16_t local_cid, BT_HDR* p_buf); void l2c_link_adjust_allocation(void); - +void l2c_link_hci_conn_comp(tHCI_STATUS status, uint16_t handle, const RawAddress& p_bda); void l2c_link_sec_comp(RawAddress p_bda, tBT_TRANSPORT transport, void* p_ref_data, tBTM_STATUS status); void l2c_link_adjust_chnl_allocation(void); @@ -832,10 +833,11 @@ void l2c_fcr_stop_timer(tL2C_CCB* p_ccb); /* Functions provided by l2c_ble.cc *********************************** */ + bool l2cble_create_conn(tL2C_LCB* p_lcb); void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len); void l2c_ble_link_adjust_allocation(void); - +void l2cble_start_conn_update(tL2C_LCB* p_lcb); void l2cble_credit_based_conn_req(tL2C_CCB* p_ccb); void l2cble_credit_based_conn_res(tL2C_CCB* p_ccb, tL2CAP_LE_RESULT_CODE result); void l2cble_send_peer_disc_req(tL2C_CCB* p_ccb); diff --git a/system/stack/l2cap/l2c_link.cc b/system/stack/l2cap/l2c_link.cc index b7521ab6776..3a3bb4290d7 100644 --- a/system/stack/l2cap/l2c_link.cc +++ b/system/stack/l2cap/l2c_link.cc @@ -40,15 +40,13 @@ #include "stack/include/btm_status.h" #include "stack/include/hci_error_code.h" #include "stack/include/l2cap_acl_interface.h" +#include "stack/include/l2cap_controller_interface.h" #include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_security_interface.h" #include "stack/l2cap/l2c_int.h" #include "types/bt_transport.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; extern tBTM_CB btm_cb; @@ -1151,45 +1149,6 @@ void l2c_packets_completed(uint16_t handle, uint16_t num_sent) { } } -/******************************************************************************* - * - * Function l2c_link_segments_xmitted - * - * Description This function is called from the HCI Interface when an ACL - * data packet segment is transmitted. - * - * Returns void - * - ******************************************************************************/ -void l2c_link_segments_xmitted(BT_HDR* p_msg) { - uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset; - - /* Extract the handle */ - uint16_t handle{HCI_INVALID_HANDLE}; - STREAM_TO_UINT16(handle, p); - handle = HCID_GET_HANDLE(handle); - - /* Find the LCB based on the handle */ - tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle); - if (p_lcb == nullptr) { - log::warn("Received segment complete for unknown connection handle:{}", handle); - osi_free(p_msg); - return; - } - - if (p_lcb->link_state != LST_CONNECTED) { - log::info("Received segment complete for unconnected connection handle:{}:", handle); - osi_free(p_msg); - return; - } - - /* Enqueue the buffer to the head of the transmit queue, and see */ - /* if we can transmit anything more. */ - list_prepend(p_lcb->link_xmit_data_q, p_msg); - - l2c_link_check_send_pkts(p_lcb, 0, NULL); -} - tBTM_STATUS l2cu_ConnectAclForSecurity(const RawAddress& bd_addr) { tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR); if (p_lcb && (p_lcb->link_state == LST_CONNECTED || p_lcb->link_state == LST_CONNECTING)) { @@ -1222,7 +1181,7 @@ void l2cble_update_sec_act(const RawAddress& bd_addr, uint16_t sec_act) { * Returns pointer to CCB or NULL * ******************************************************************************/ -tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) { +static tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) { tL2C_CCB* p_serve_ccb = NULL; tL2C_CCB* p_ccb; @@ -1320,7 +1279,7 @@ tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) { * Returns pointer to buffer or NULL * ******************************************************************************/ -BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb, tL2C_TX_COMPLETE_CB_INFO* p_cbi) { +static BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb, tL2C_TX_COMPLETE_CB_INFO* p_cbi) { tL2C_CCB* p_ccb; BT_HDR* p_buf; diff --git a/system/stack/l2cap/l2c_main.cc b/system/stack/l2cap/l2c_main.cc index 92592831097..057b474f5ba 100644 --- a/system/stack/l2cap/l2c_main.cc +++ b/system/stack/l2cap/l2c_main.cc @@ -35,14 +35,13 @@ #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" #include "stack/include/hcimsgs.h" // HCID_GET_ +#include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_interface.h" +#include "stack/include/l2cap_module.h" #include "stack/include/l2cdefs.h" #include "stack/l2cap/l2c_int.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /******************************************************************************/ diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index 612b9418958..0e923a559cb 100644 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -44,19 +44,16 @@ #include "stack/include/hci_error_code.h" #include "stack/include/hcidefs.h" #include "stack/include/l2cap_acl_interface.h" +#include "stack/include/l2cap_controller_interface.h" #include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_interface.h" +#include "stack/include/l2cap_security_interface.h" #include "stack/include/l2cdefs.h" #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; -tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb); // TODO Move - /* The offset in a buffer that L2CAP will use when building commands. */ #define L2CAP_SEND_CMD_OFFSET 0 @@ -305,7 +302,7 @@ bool l2c_is_cmd_rejected(uint8_t cmd_code, uint8_t signal_id, tL2C_LCB* p_lcb) { * Returns Pointer to allocated packet or NULL if no resources * ******************************************************************************/ -BT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd, uint8_t signal_id) { +static BT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd, uint8_t signal_id) { BT_HDR* p_buf = (BT_HDR*)osi_malloc(L2CAP_CMD_BUF_SIZE); uint8_t* p; @@ -348,7 +345,7 @@ BT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd, uint8_t si * Returns void * ******************************************************************************/ -void l2cu_adj_id(tL2C_LCB* p_lcb) { +static void l2cu_adj_id(tL2C_LCB* p_lcb) { if (p_lcb->signal_id == 0) { p_lcb->signal_id++; } @@ -2207,28 +2204,6 @@ void l2cu_create_conn_br_edr(tL2C_LCB* p_lcb) { l2cu_create_conn_after_switch(p_lcb); } -/******************************************************************************* - * - * Function l2cu_get_num_hi_priority - * - * Description Gets the number of high priority channels. - * - * Returns - * - ******************************************************************************/ -uint8_t l2cu_get_num_hi_priority(void) { - uint8_t no_hi = 0; - int xx; - tL2C_LCB* p_lcb = &l2cb.lcb_pool[0]; - - for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { - if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) { - no_hi++; - } - } - return no_hi; -} - /******************************************************************************* * * Function l2cu_create_conn_after_switch diff --git a/system/test/mock/mock_stack_l2cap_api.cc b/system/test/mock/mock_stack_l2cap_api.cc index c360878a6b6..b8f3f4e227d 100644 --- a/system/test/mock/mock_stack_l2cap_api.cc +++ b/system/test/mock/mock_stack_l2cap_api.cc @@ -37,7 +37,6 @@ namespace mock { namespace stack_l2cap_api { // Function state capture and return values, if needed -struct l2c_get_transport_from_fixed_cid l2c_get_transport_from_fixed_cid; struct L2CA_RegisterWithSecurity L2CA_RegisterWithSecurity; struct L2CA_Register L2CA_Register; struct L2CA_Deregister L2CA_Deregister; @@ -82,10 +81,6 @@ struct L2CA_LeCreditThreshold L2CA_LeCreditThreshold; } // namespace test // Mocked functions, if any -tBT_TRANSPORT l2c_get_transport_from_fixed_cid(uint16_t fixed_cid) { - inc_func_call_count(__func__); - return test::mock::stack_l2cap_api::l2c_get_transport_from_fixed_cid(fixed_cid); -} uint16_t L2CA_RegisterWithSecurity(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu, uint16_t required_remote_mtu, diff --git a/system/test/mock/mock_stack_l2cap_api.h b/system/test/mock/mock_stack_l2cap_api.h index c2d162afd2f..40d746ecd3c 100644 --- a/system/test/mock/mock_stack_l2cap_api.h +++ b/system/test/mock/mock_stack_l2cap_api.h @@ -39,17 +39,6 @@ namespace test { namespace mock { namespace stack_l2cap_api { - -// Shared state between mocked functions and tests -// Name: l2c_get_transport_from_fixed_cid -// Params: uint16_t fixed_cid -// Returns: tBT_TRANSPORT -struct l2c_get_transport_from_fixed_cid { - std::function body{ - [](uint16_t /* fixed_cid */) { return BT_TRANSPORT_AUTO; }}; - tBT_TRANSPORT operator()(uint16_t fixed_cid) { return body(fixed_cid); } -}; -extern struct l2c_get_transport_from_fixed_cid l2c_get_transport_from_fixed_cid; // Name: L2CA_RegisterWithSecurity // Params: uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, bool enable_snoop, // tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu, uint16_t required_remote_mtu, diff --git a/system/test/mock/mock_stack_l2cap_ble.cc b/system/test/mock/mock_stack_l2cap_ble.cc index ee625765160..7dcd2f6bf01 100644 --- a/system/test/mock/mock_stack_l2cap_ble.cc +++ b/system/test/mock/mock_stack_l2cap_ble.cc @@ -58,7 +58,6 @@ struct l2cble_credit_based_conn_req l2cble_credit_based_conn_req; struct l2cble_credit_based_conn_res l2cble_credit_based_conn_res; struct l2cble_send_flow_control_credit l2cble_send_flow_control_credit; struct l2cble_send_peer_disc_req l2cble_send_peer_disc_req; -struct l2cble_sec_comp l2cble_sec_comp; struct l2ble_sec_access_req l2ble_sec_access_req; struct L2CA_AdjustConnectionIntervals L2CA_AdjustConnectionIntervals; struct L2CA_SetEcosystemBaseInterval L2CA_SetEcosystemBaseInterval; @@ -158,11 +157,6 @@ void l2cble_send_peer_disc_req(tL2C_CCB* p_ccb) { inc_func_call_count(__func__); test::mock::stack_l2cap_ble::l2cble_send_peer_disc_req(p_ccb); } -void l2cble_sec_comp(const RawAddress* bda, tBT_TRANSPORT transport, void* p_ref_data, - tBTM_STATUS status) { - inc_func_call_count(__func__); - test::mock::stack_l2cap_ble::l2cble_sec_comp(bda, transport, p_ref_data, status); -} tL2CAP_LE_RESULT_CODE l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t psm, bool is_originator, tBTM_SEC_CALLBACK* p_callback, void* p_ref_data) { diff --git a/system/test/mock/mock_stack_l2cap_ble.h b/system/test/mock/mock_stack_l2cap_ble.h index 6f13fed7355..c5c3e45a1dc 100644 --- a/system/test/mock/mock_stack_l2cap_ble.h +++ b/system/test/mock/mock_stack_l2cap_ble.h @@ -227,20 +227,6 @@ struct l2cble_send_peer_disc_req { void operator()(tL2C_CCB* p_ccb) { body(p_ccb); } }; extern struct l2cble_send_peer_disc_req l2cble_send_peer_disc_req; -// Name: l2cble_sec_comp -// Params: const RawAddress* bda, tBT_TRANSPORT transport, void* p_ref_data, -// tBTM_STATUS status Returns: void -struct l2cble_sec_comp { - std::function - body{[](const RawAddress* /* bda */, tBT_TRANSPORT /* transport */, - void* /* p_ref_data */, tBTM_STATUS /* status */) {}}; - void operator()(const RawAddress* bda, tBT_TRANSPORT transport, void* p_ref_data, - tBTM_STATUS status) { - body(bda, transport, p_ref_data, status); - } -}; -extern struct l2cble_sec_comp l2cble_sec_comp; // Name: l2ble_sec_access_req // Params: const RawAddress& bd_addr, uint16_t psm, bool is_originator, // tL2CAP_SEC_CBACK* p_callback, void* p_ref_data Returns: tL2CAP_LE_RESULT_CODE diff --git a/system/test/mock/mock_stack_l2cap_link.cc b/system/test/mock/mock_stack_l2cap_link.cc index c0dea8c1fc4..0c520ee5940 100644 --- a/system/test/mock/mock_stack_l2cap_link.cc +++ b/system/test/mock/mock_stack_l2cap_link.cc @@ -22,17 +22,14 @@ #include "stack/include/bt_hdr.h" #include "stack/include/btm_status.h" +#include "stack/include/l2cap_acl_interface.h" +#include "stack/include/l2cap_controller_interface.h" +#include "stack/include/l2cap_hci_link_interface.h" +#include "stack/include/l2cap_security_interface.h" #include "stack/l2cap/l2c_int.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* /* p_lcb */) { - inc_func_call_count(__func__); - return nullptr; -} bool l2c_link_hci_disc_comp(uint16_t /* handle */, tHCI_REASON /* reason */) { inc_func_call_count(__func__); return false; @@ -41,10 +38,6 @@ tBTM_STATUS l2cu_ConnectAclForSecurity(const RawAddress& /* bd_addr */) { inc_func_call_count(__func__); return tBTM_STATUS::BTM_SUCCESS; } -tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* /* p_lcb */) { - inc_func_call_count(__func__); - return nullptr; -} void l2c_OnHciModeChangeSendPendingPackets(RawAddress /* remote */) { inc_func_call_count(__func__); } @@ -64,12 +57,11 @@ void l2c_link_role_changed(const RawAddress* /* bd_addr */, tHCI_ROLE /* new_rol tHCI_STATUS /* hci_status */) { inc_func_call_count(__func__); } -void l2c_link_sec_comp(const RawAddress* /* p_bda */, tBT_TRANSPORT /* transport */, - void* /* p_ref_data */, uint8_t /* status */) { +void l2c_link_sec_comp(const RawAddress /* bda */, tBT_TRANSPORT /* transport */, + void* /* p_ref_data */, tBTM_STATUS /* status */) { inc_func_call_count(__func__); } -void l2c_link_segments_xmitted(BT_HDR* /* p_msg */) { inc_func_call_count(__func__); } void l2c_link_timeout(tL2C_LCB* /* p_lcb */) { inc_func_call_count(__func__); } void l2c_packets_completed(uint16_t /* handle */, uint16_t /* num_sent */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_l2cap_utils.cc b/system/test/mock/mock_stack_l2cap_utils.cc index accdc728813..f485c111e41 100644 --- a/system/test/mock/mock_stack_l2cap_utils.cc +++ b/system/test/mock/mock_stack_l2cap_utils.cc @@ -29,11 +29,6 @@ // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -BT_HDR* l2cu_build_header(tL2C_LCB* /* p_lcb */, uint16_t /* len */, uint8_t /* cmd */, - uint8_t /* signal_id */) { - inc_func_call_count(__func__); - return nullptr; -} bool l2c_is_cmd_rejected(uint8_t /* cmd_code */, uint8_t /* signal_id */, tL2C_LCB* /* p_lcb */) { inc_func_call_count(__func__); return false; @@ -113,15 +108,10 @@ tL2C_RCB* l2cu_find_rcb_by_psm(uint16_t /* psm */) { inc_func_call_count(__func__); return nullptr; } -uint8_t l2cu_get_num_hi_priority(void) { - inc_func_call_count(__func__); - return 0; -} uint8_t l2cu_process_peer_cfg_req(tL2C_CCB* /* p_ccb */, tL2CAP_CFG_INFO* /* p_cfg */) { inc_func_call_count(__func__); return 0; } -void l2cu_adj_id(tL2C_LCB* /* p_lcb */) { inc_func_call_count(__func__); } void l2cu_adjust_out_mps(tL2C_CCB* /* p_ccb */) { inc_func_call_count(__func__); } void l2cu_change_pri_ccb(tL2C_CCB* /* p_ccb */, tL2CAP_CHNL_PRIORITY /* priority */) { inc_func_call_count(__func__); -- GitLab From 64581a64870daeacb535ef25e2516da9b24210ac Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 22 Oct 2024 11:14:40 -0700 Subject: [PATCH 457/875] BluetoothAdapter: throw when system server is dead Calling the manager service must never failed as the manager service cannot be turned off. If a remote exception occurs that mean the whole system is dead and we have to rethrow the exception Test: m . Bug: 311772251 Flag: Exempt refactor Change-Id: I3ab9d5f06c05f26afbc5ad94aaef2db0aa3a8126 --- .../android/bluetooth/BluetoothAdapter.java | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index f345bb5502f..71405a17fe8 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -1403,9 +1403,8 @@ public final class BluetoothAdapter { try { return mManagerService.disableBle(mAttributionSource, mToken); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return false; } /** @@ -1447,10 +1446,8 @@ public final class BluetoothAdapter { try { return mManagerService.enableBle(mAttributionSource, mToken); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - - return false; } /** @@ -1686,9 +1683,8 @@ public final class BluetoothAdapter { try { return mManagerService.enable(mAttributionSource); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return false; } /** @@ -1751,9 +1747,8 @@ public final class BluetoothAdapter { try { return mManagerService.disable(mAttributionSource, persist); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return false; } /** @@ -1770,9 +1765,8 @@ public final class BluetoothAdapter { try { return mManagerService.getAddress(mAttributionSource); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return null; } /** @@ -1789,9 +1783,8 @@ public final class BluetoothAdapter { try { return mManagerService.getName(mAttributionSource); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return null; } /** @hide */ @@ -2396,8 +2389,7 @@ public final class BluetoothAdapter { try { return mManagerService.isBleScanAvailable(); } catch (RemoteException e) { - Log.e(TAG, "remote exception when calling isBleScanAvailable", e); - return false; + throw e.rethrowFromSystemServer(); } } @@ -2744,8 +2736,7 @@ public final class BluetoothAdapter { try { return mManagerService.isHearingAidProfileSupported(); } catch (RemoteException e) { - Log.e(TAG, "remote exception when calling isHearingAidProfileSupported", e); - return false; + throw e.rethrowFromSystemServer(); } } @@ -3924,9 +3915,8 @@ public final class BluetoothAdapter { try { return mManagerService.enableNoAutoConnect(mAttributionSource); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return false; } /** @hide */ @@ -5375,9 +5365,8 @@ public final class BluetoothAdapter { try { return mManagerService.setBtHciSnoopLogMode(mode); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return BluetoothStatusCodes.ERROR_UNKNOWN; } /** @@ -5393,9 +5382,8 @@ public final class BluetoothAdapter { try { return mManagerService.getBtHciSnoopLogMode(); } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } - return BT_SNOOP_LOG_MODE_DISABLED; } /** -- GitLab From b1ba026ac6538c7230538a1e49518fd70467a9d3 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 21 Oct 2024 17:38:45 -0700 Subject: [PATCH 458/875] Framework: utility method to shorter service calls Bug: 311772251 Test: m . Flag: Exempt refactor - adding unused utility code Change-Id: I0774ac8db3cacbd8fd7a1ebafbd9ce1e218db71b --- .../android/bluetooth/BluetoothUtils.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/framework/java/android/bluetooth/BluetoothUtils.java b/framework/java/android/bluetooth/BluetoothUtils.java index 19a9057b557..a2b0393499f 100644 --- a/framework/java/android/bluetooth/BluetoothUtils.java +++ b/framework/java/android/bluetooth/BluetoothUtils.java @@ -21,13 +21,18 @@ import android.annotation.Nullable; import android.annotation.RequiresNoPermission; import android.os.Binder; import android.os.Parcel; +import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; /** @hide */ public final class BluetoothUtils { @@ -343,4 +348,83 @@ public final class BluetoothUtils { } }); } + + /** A {@link Consumer} that automatically logs {@link RemoteException} @hide */ + @FunctionalInterface + public interface RemoteExceptionIgnoringConsumer { + /** Called by {@code accept}. */ + void acceptOrThrow(T t) throws RemoteException; + + @RequiresNoPermission + default void accept(T t) { + try { + acceptOrThrow(t); + } catch (RemoteException ex) { + logRemoteException(TAG, ex); + } + } + } + + /** A {@link Function} that automatically logs {@link RemoteException} @hide */ + @FunctionalInterface + public interface RemoteExceptionIgnoringFunction { + R applyOrThrow(T t) throws RemoteException; + + @RequiresNoPermission + default R apply(T t, R defaultValue) { + try { + return applyOrThrow(t); + } catch (RemoteException ex) { + logRemoteException(TAG, ex); + return defaultValue; + } + } + } + + public static R callServiceIfEnabled( + BluetoothAdapter adapter, + Supplier provider, + RemoteExceptionIgnoringFunction function, + R defaultValue) { + if (!adapter.isEnabled()) { + Log.d(TAG, "BluetoothAdapter is not enabled"); + return defaultValue; + } + final S service = provider.get(); + if (service == null) { + Log.d(TAG, "Proxy not attached to service"); + return defaultValue; + } + return function.apply(service, defaultValue); + } + + public static void callServiceIfEnabled( + BluetoothAdapter adapter, + Supplier provider, + RemoteExceptionIgnoringConsumer consumer) { + if (!adapter.isEnabled()) { + Log.d(TAG, "BluetoothAdapter is not enabled"); + return; + } + final S service = provider.get(); + if (service == null) { + Log.d(TAG, "Proxy not attached to service"); + return; + } + consumer.accept(service); + } + + /** return the current stack trace as a string without new line @hide */ + public static String inlineStackTrace() { + StringBuilder sb = new StringBuilder(); + Arrays.stream(new Throwable().getStackTrace()) + .skip(1) // skip the inlineStackTrace method in the outputted stack trace + .forEach(trace -> sb.append(" [at ").append(trace).append("]")); + return sb.toString(); + } + + /** Gracefully print a RemoteException as a one line warning @hide */ + public static void logRemoteException(String tag, RemoteException ex) { + Log.w(tag, ex.toString() + ": " + inlineStackTrace()); + } } -- GitLab From 2dda064bf57cc703ca845687712a5dab33418b85 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 21 Oct 2024 17:47:12 -0700 Subject: [PATCH 459/875] Framework HAP: use wrapper for readability Bug: 311772251 Test: m Bluetooth Flag: Exempt refactor - HAP is not launched yet Change-Id: I7bce5ca0278af90e07336a81326e36d2744c3ca2 --- .../android/bluetooth/BluetoothHapClient.java | 350 +++++++----------- 1 file changed, 142 insertions(+), 208 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothHapClient.java b/framework/java/android/bluetooth/BluetoothHapClient.java index 61584c4aeab..cea0e6393bc 100644 --- a/framework/java/android/bluetooth/BluetoothHapClient.java +++ b/framework/java/android/bluetooth/BluetoothHapClient.java @@ -19,6 +19,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.callServiceIfEnabled; import static java.util.Objects.requireNonNull; @@ -564,8 +565,7 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable * Set connection policy of the profile * *

    The device should already be paired. Connection policy can be one of {@link - * #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN}, {@link - * #CONNECTION_POLICY_UNKNOWN} + * #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN} * * @param device Paired bluetooth device * @param connectionPolicy is the connection policy to set to for this profile @@ -578,29 +578,22 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable public boolean setConnectionPolicy( @NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { requireNonNull(device); - - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "setConnectionPolicy: Proxy not attached to service"); - } else if (mAdapter.isEnabled() - && isValidDevice(device) - && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { - try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + boolean defaultValue = false; + if (!isValidDevice(device) + || (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + return defaultValue; } - return false; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.setConnectionPolicy(device, connectionPolicy, mAttributionSource), + defaultValue); } /** * Get the connection policy of the profile. * - *

    The connection policy can be any of: {@link #CONNECTION_POLICY_ALLOWED}, {@link - * #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN} - * * @param device Bluetooth device * @return connection policy of the device or {@link #CONNECTION_POLICY_FORBIDDEN} if device is * null @@ -610,17 +603,15 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getConnectionPolicy: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (!isValidDevice(device)) { + return defaultValue; } - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getConnectionPolicy(device, mAttributionSource), + defaultValue); } /** @@ -633,18 +624,13 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) @Override public @NonNull List getConnectedDevices() { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getConnectedDevices: Proxy not attached to service"); - } else if (mAdapter.isEnabled()) { - try { - return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } - return Collections.emptyList(); + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> + Attributable.setAttributionSource( + s.getConnectedDevices(mAttributionSource), mAttributionSource), + Collections.emptyList()); } /** @@ -658,19 +644,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @Override @NonNull public List getDevicesMatchingConnectionStates(@NonNull int[] states) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getDevicesMatchingConnectionStates: Proxy not attached to service"); - } else if (mAdapter.isEnabled()) { - try { - return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), - mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } - return Collections.emptyList(); + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> + Attributable.setAttributionSource( + s.getDevicesMatchingConnectionStates(states, mAttributionSource), + mAttributionSource), + Collections.emptyList()); } /** @@ -684,17 +665,15 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @Override @BluetoothProfile.BtProfileState public int getConnectionState(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getConnectionState: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (!isValidDevice(device)) { + return defaultValue; } - return BluetoothProfile.STATE_DISCONNECTED; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getConnectionState(device, mAttributionSource), + defaultValue); } /** @@ -714,23 +693,18 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @SystemApi @FlaggedApi(Flags.FLAG_SETTINGS_CAN_CONTROL_HAP_PRESET) @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getHapGroup(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getHapGroup: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getHapGroup(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + int defaultValue = BluetoothCsipSetCoordinator.GROUP_ID_INVALID; + if (!isValidDevice(device)) { + return defaultValue; } - return BluetoothCsipSetCoordinator.GROUP_ID_INVALID; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getHapGroup(device, mAttributionSource), + defaultValue); } /** @@ -745,17 +719,16 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getActivePresetIndex(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getActivePresetIndex: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getActivePresetIndex(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + int defaultValue = PRESET_INDEX_UNAVAILABLE; + if (!isValidDevice(device)) { + return defaultValue; } - return PRESET_INDEX_UNAVAILABLE; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getActivePresetIndex(device, mAttributionSource), + defaultValue); } /** @@ -770,18 +743,16 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @Nullable BluetoothHapPresetInfo getActivePresetInfo(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getActivePresetInfo: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getActivePresetInfo(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + BluetoothHapPresetInfo defaultValue = null; + if (!isValidDevice(device)) { + return defaultValue; } - - return null; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getActivePresetInfo(device, mAttributionSource), + defaultValue); } /** @@ -799,16 +770,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void selectPreset(@NonNull BluetoothDevice device, int presetIndex) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "selectPreset: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - service.selectPreset(device, presetIndex, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + if (!isValidDevice(device)) { + return; } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.selectPreset(device, presetIndex, mAttributionSource)); } /** @@ -830,16 +799,10 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void selectPresetForGroup(int groupId, int presetIndex) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "selectPresetForGroup: Proxy not attached to service"); - } else if (mAdapter.isEnabled()) { - try { - service.selectPresetForGroup(groupId, presetIndex, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.selectPresetForGroup(groupId, presetIndex, mAttributionSource)); } /** @@ -856,16 +819,12 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void switchToNextPreset(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "switchToNextPreset: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - service.switchToNextPreset(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + if (!isValidDevice(device)) { + return; } + callServiceIfEnabled( + mAdapter, this::getService, s -> s.switchToNextPreset(device, mAttributionSource)); } /** @@ -885,16 +844,10 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void switchToNextPresetForGroup(int groupId) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "switchToNextPresetForGroup: Proxy not attached to service"); - } else if (mAdapter.isEnabled()) { - try { - service.switchToNextPresetForGroup(groupId, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.switchToNextPresetForGroup(groupId, mAttributionSource)); } /** @@ -911,16 +864,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void switchToPreviousPreset(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "switchToPreviousPreset: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - service.switchToPreviousPreset(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + if (!isValidDevice(device)) { + return; } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.switchToPreviousPreset(device, mAttributionSource)); } /** @@ -940,23 +891,17 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void switchToPreviousPresetForGroup(int groupId) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "switchToPreviousPresetForGroup: Proxy not attached to service"); - } else if (mAdapter.isEnabled()) { - try { - service.switchToPreviousPresetForGroup(groupId, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.switchToPreviousPresetForGroup(groupId, mAttributionSource)); } /** * Requests the preset info * - * @param device is the device for which we want to get the preset name - * @param presetIndex is an index of one of the available presets + * @param device is the device for which we want to get the preset + * @param presetIndex is an index of an available presets * @return preset info * @hide */ @@ -966,17 +911,16 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) @Nullable public BluetoothHapPresetInfo getPresetInfo(@NonNull BluetoothDevice device, int presetIndex) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getPresetInfo: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getPresetInfo(device, presetIndex, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + BluetoothHapPresetInfo defaultValue = null; + if (!isValidDevice(device)) { + return defaultValue; } - return null; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getPresetInfo(device, presetIndex, mAttributionSource), + defaultValue); } /** @@ -990,17 +934,16 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull List getAllPresetInfo(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getAllPresetInfo: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getAllPresetInfo(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + List defaultValue = Collections.emptyList(); + if (!isValidDevice(device)) { + return defaultValue; } - return Collections.emptyList(); + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getAllPresetInfo(device, mAttributionSource), + defaultValue); } /** @@ -1013,17 +956,16 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getFeatures(@NonNull BluetoothDevice device) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "getFeatures: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getFeatures(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + int defaultValue = 0x00; + if (!isValidDevice(device)) { + return defaultValue; } - return 0x00; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getFeatures(device, mAttributionSource), + defaultValue); } /** @@ -1119,16 +1061,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void setPresetName( @NonNull BluetoothDevice device, int presetIndex, @NonNull String name) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "setPresetName: Proxy not attached to service"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - service.setPresetName(device, presetIndex, name, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + requireNonNull(device); + if (!isValidDevice(device)) { + return; } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.setPresetName(device, presetIndex, name, mAttributionSource)); } /** @@ -1150,16 +1090,10 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public void setPresetNameForGroup(int groupId, int presetIndex, @NonNull String name) { - final IBluetoothHapClient service = getService(); - if (service == null) { - Log.d(TAG, "setPresetNameForGroup: Proxy not attached to service"); - } else if (mAdapter.isEnabled()) { - try { - service.setPresetNameForGroup(groupId, presetIndex, name, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.setPresetNameForGroup(groupId, presetIndex, name, mAttributionSource)); } private boolean isValidDevice(BluetoothDevice device) { -- GitLab From afd2c8bfaa89ad0e2f01ecafa8bf912fc09aef10 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 25 Oct 2024 14:13:23 -0700 Subject: [PATCH 460/875] SystemServer: reduce callback visibility Bug: 289584302 Test: m . Flag: com.android.bluetooth.flags.use_new_satellite_mode Change-Id: Ia92cb32676d2f0ed9eac98c699e28efbbda91e31 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 8bd003641d9..709477e2eb4 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -398,6 +398,7 @@ class BluetoothManagerService { private static final Object ON_SATELLITE_MODE_CHANGED_TOKEN = new Object(); private static final Object ON_SWITCH_USER_TOKEN = new Object(); + @VisibleForTesting Unit onAirplaneModeChanged(boolean isAirplaneModeOn) { delayModeChangedIfNeeded( ON_AIRPLANE_MODE_CHANGED_TOKEN, @@ -406,8 +407,7 @@ class BluetoothManagerService { return Unit.INSTANCE; } - // TODO(b/289584302): Update to private once use_new_satellite_mode is enabled - Unit onSatelliteModeChanged(boolean isSatelliteModeOn) { + private Unit onSatelliteModeChanged(boolean isSatelliteModeOn) { delayModeChangedIfNeeded( ON_SATELLITE_MODE_CHANGED_TOKEN, () -> handleSatelliteModeChanged(isSatelliteModeOn), -- GitLab From 1922f13d3087f61a68d76b3cfad9cfc98112da7d Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 17:29:39 -0700 Subject: [PATCH 461/875] Remove obsolete GD style guide Bug: 331817295 Test: None Flag: EXEMPT, documentation update Change-Id: I6587083ec02d6c88bb3880c0d4f411453b9a591f --- system/gd/README.md | 1 - system/gd/docs/architecture/style_guide.md | 188 --------------------- 2 files changed, 189 deletions(-) delete mode 100644 system/gd/docs/architecture/style_guide.md diff --git a/system/gd/README.md b/system/gd/README.md index 18a021132c7..862bb3897c4 100644 --- a/system/gd/README.md +++ b/system/gd/README.md @@ -7,7 +7,6 @@ Please see this [informative video we've prepared](https://www.youtube.com/watch Guidelines for developing the Gabeldorsche (GD) stack * [Architecture](./docs/architecture/architecture.md) -* [Style Guide](./docs/architecture/style_guide.md) ### Testing diff --git a/system/gd/docs/architecture/style_guide.md b/system/gd/docs/architecture/style_guide.md deleted file mode 100644 index 88829823964..00000000000 --- a/system/gd/docs/architecture/style_guide.md +++ /dev/null @@ -1,188 +0,0 @@ -# Gabeldorsche Style Guide - -[TOC] - -## Base - -In general, when not mentioned in this document, developers should follow the -Google C++ and Google Java style guide as much as possible. - -### Google C++ Style Guide - -C++ Style Guide: https://google.github.io/styleguide/cppguide.html - -### Android and Google Java Style Guide - -1. Android Java Style Guide: - https://source.android.com/setup/contribute/code-style - -2. when not covered by (1), see External Java Style Guide: - https://google.github.io/styleguide/javaguide.html - -line length limit is 120 characters for C++ and Java - -### Python Style Guide - -The GD stack uses the Google Python Style Guide: - -* http://google.github.io/styleguide/pyguide.html - -with the following modifications as shown in the -[.style.yapf](https://android.googlesource.com/platform/packages/modules/Bluetooth/system/+/refs/heads/master/.style.yapf) definition: - -```yapf -based_on_style: google -indent_width: 4 -column_limit: 120 -``` - -## Build files - -* One build target for the entire stack in packages/modules/Bluetooth/system (i.e. one cc_library()) - * If only part of the stack needs to be compiled, configure it using the - “target” configuration in Android.bp -* One build target for all unit tests (i.e. one cc_test) -* When needed, filgroup() can be created in Android.bp in sub-directories. The - main build target should use these filegroups() to build the main output - library. -* All targets must have host_supported == true unless it is dependent on the - OS -* If the stack needs to be compiled using other build system, then the build - files should also live in packages/modules/Bluetooth/system - -## Namespace and include - -* Namespace must follow directory names -* Top level namespace for internal code is “bluetooth” -* Top level namespace for externally visible code is “android::bluetooth” -* Include path must be relative to the root directory of the stack. Normally - it is packages/modules/Bluetooth/system, for GD refactor code, it is packages/modules/Bluetooth/system/gd - -## Multiple implementations of the same header - -Since GD interact with many lower level components that are platform dependent, -frequently there is need to implement the same header multiple times for -different platform or hardware. When doing this: - -* Avoid #define macros as much as possible. Instead put code into different - source files and selectively compile them for different targets. -* Convention of operating system used: - * android/ - * All Android devices that use HIDL - * linux/ - * All non-Android linux devices - * linux_generic/ - * Android and non-Android linux devices - -## Directory structure - -Root directory under Android tree: -[**packages/modules/Bluetooth/system/gd/**](https://android.googlesource.com/platform/packages/modules/Bluetooth/system/+/refs/heads/master/gd/) - -* Directory structure should be as flat as possible -* Each file should contain at most one class -* Header, source code, and unit test should live in the same directory with - the following naming guideline: - * Source: bb.cc - * Header: bb.h - * Test: bb_test.cc -* Each profile should have its own directory and module -* Source and sink, server and client profiles should live in two sub folders - of the same common directory where common code can be stored. However, - source and sink must have separate modules -* Module file is also the external API header -* Prefer underscore over dashes - -### Example: utility library with OS dependent implementation - -* os/: OS dependent classes such as Alarm, Thread, Handler - * Android.bp: Build file that defines file groups that would include - different source files based on compile time target - * alarm.h: common header for alarm - * linux_generic/: Implementations for generic Linux OS - * alarm.cc: Linux generic implementation of alarm.h using timer_fd - * alarm_test.cc: unit test for alarm.h - * fuzz/: library needed for fuzz tests in the os/ library - -### Example: module with hardware dependent implementation - -* hal/: Hardware abstraction layer such as HCI interfaces, Audio interfaces - * Android.bp: Build file that defines file groups that would include - different source files based on compile time target - * hci_hal.h: common library header - * hci_hal_android_hidl.cc: implementation of hci_hal.h using Android HIDL - * hci_hal_android_hidl_test.cc: unit tests for the Android HIDL - implementation - * hci_hal_host.cc: implementation of hci_hal.h using linux Bluetooth HCI - socket - * hci_hal_host_rootcanal.cc: implementation of hci_hal.h using root-canal - emulator - * hci_hal_host_test.cc: unit tests for the socket based HAL (root-canal) - emulator implementation - * facade.proto: gRPC automation interface definition for this layer - * facade.h/cc: an implementation of the above gRPC interface for the GD - stack - * cert/: certification tests for this module - * fuzz/: library needed for fuzz tests in the hal/ module - -### Example: similar protocol with the same base - -* l2cap/: L2CAP layer, splitted among classic and LE - * classic/: Classic L2CAP module - * cert/: certification tests for this module - * internal/: internal code to be used only in classic - * Source code and headers being exported to other modules - * le/: LE L2CAP module - * cert/: certification tests for this module - * internal/: internal code to be used only in classic - * Source code and headers being exported to other modules - * internal/: L2CAP internal code that should not be used by sources - outside L2CAP - * data_pipeline_manager.h - * data_pipeline_manager.cc - * data_pipeline_manager_mock.h: Mock of this class, used in unit tests - * dynamic_channel_allocator.h - * dynamic_channel_allocator.cc - * dynamic_channel_allocator_test.cc: GTest unit test of this class - * dynamic_channel_allocator_fuzz_test.cc: Fuzz test of this class - * *.h/.cc: Common headers and sources that is exposed to other modules - -### Example: protocol or profiles with client and server side implementations - -* a2dp/: A2DP profile - * sink/: A2DP sink module (e.g. headset) - * source/: A2DP source module (e.g. phone) -* avrcp/ - * controller/: AVRCP peripheral module (e.g. carkit) - * target/: AVRCP target module (e.g. Phone) -* hfp/ - * hf/: Handsfree device (e.g. headset) - * ag/: Audio gateway (e.g. phone) - -## External libraries - -To maintain high portability, we are trying to stick with C++ STL as much as -possible. Hence, before including an external library, please ask the team for -review. - -Examples of currently used libraries: - -* boringssl: Google's openssl implementation -* small parts of libchrome, to be removed or replaced eventually - * base::OnceCallback - * base::Callback - * base::BindOnce - * base::Bind -* google-breakpad: host binary crash handler -* libunwindstack: print stacktrace on crash on host - -## Exposed symbols - -Given that entire Fluoride library is held in libbluetooth.so dynamic library -file, we need a way to load this library and extract entry points to it. The -only symbols that should be exposed are: - -* An entry point to a normal running adapter module libbluetooth.so -* A header library to all exposed API service to profiles and layers -* An entry point to a certification interface, libbluetooth\_certification.so -* A header library to this certification stack -- GitLab From 31492985961ce63827a1c66de160745bbbe643d7 Mon Sep 17 00:00:00 2001 From: Etienne Ruffieux Date: Fri, 18 Oct 2024 11:30:16 +0000 Subject: [PATCH 462/875] Add avrcp_16_default flag Bug: 374271695 Bug: 315241296 Test: m Bluetooth Flag: avrcp_16_default Change-Id: I7b6ffdb83095cafe4dbf744007b9cb866e824227 --- flags/avrcp.aconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/flags/avrcp.aconfig b/flags/avrcp.aconfig index 8a6a553b344..1c50da09491 100644 --- a/flags/avrcp.aconfig +++ b/flags/avrcp.aconfig @@ -50,3 +50,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "avrcp_16_default" + namespace: "bluetooth" + description: "Set AVRCP 1.6 as default AVRCP version" + bug: "374271695" +} -- GitLab From 42ec73bc7d145d893d0e7b8099acf522c1b76561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Thu, 24 Oct 2024 17:51:06 +0000 Subject: [PATCH 463/875] CsipSetCoordinatorService: Fix possible null ptr dereference Bug: 364916949 Flag: Exempt, trivial fix Test: mmm packages/modules/Bluetooth Change-Id: Ie89a03b2131521bbf1674d48a866c523ec7d71a7 --- .../csip/CsipSetCoordinatorService.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java index 9febc119543..f1cdefc1b21 100644 --- a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java +++ b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java @@ -911,6 +911,16 @@ public class CsipSetCoordinatorService extends ProfileService { /** Process a change in the bonding state for a device */ public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) { + if (mHandler == null) { + Log.e( + TAG, + "mHandler is null, service is stopped. Ignore Bond State for " + + device + + " to state: " + + toState); + return; + } + mHandler.post(() -> bondStateChanged(device, toState)); } @@ -972,6 +982,15 @@ public class CsipSetCoordinatorService extends ProfileService { } void handleConnectionStateChanged(BluetoothDevice device, int fromState, int toState) { + if (mHandler == null) { + Log.e( + TAG, + "mHandler is null, service is stopped. Ignore Connection State for " + + device + + " to state: " + + toState); + return; + } mHandler.post(() -> connectionStateChanged(device, fromState, toState)); } -- GitLab From 2267a58317132f7bc631c8bb4be0e18be0b9e7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Mon, 28 Oct 2024 16:15:44 +0000 Subject: [PATCH 464/875] leaudio: Non functional change Some minor comment fixups i minor non functional code changes. Bug: 331775328 Flag: EXEMPT, non functional change Test: mmm packages/modules/Bluetooth Change-Id: I93141047f5caf6829883cf964f56bf4d9d7d0f01 --- system/bta/le_audio/client.cc | 52 +++++++++++++-------- system/bta/le_audio/le_audio_client_test.cc | 2 +- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 01c2856e99f..6a3e3e8d75a 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -867,7 +867,10 @@ public: BidirectionalPair remote_contexts) { LeAudioDeviceGroup* group = aseGroups_.FindById(group_id); - log::debug("configuration_context_type= {}", ToString(configuration_context_type)); + log::debug( + "configuration_context_type= {}, remote sink contexts= {}, remote source contexts= {}", + ToString(configuration_context_type), ToString(remote_contexts.sink), + ToString(remote_contexts.source)); log::debug(""); if (configuration_context_type >= LeAudioContextType::RFU) { @@ -4701,16 +4704,18 @@ public: continue; } + // Use only available contexts contexts_pair.get(dir) &= group_available_contexts; + + // Check we we should add UNSPECIFIED as well in case not available context is also not + // supported auto unavail_but_supported = (unavail_contexts & group->GetSupportedContexts(dir)); if (unavail_but_supported.none() && group_available_contexts.test(LeAudioContextType::UNSPECIFIED)) { - log::debug("Replaced the unsupported contexts: {} with UNSPECIFIED", - ToString(unavail_contexts)); - /* All unavailable are also unsupported - replace with UNSPECIFIED if - * available - */ contexts_pair.get(dir).set(LeAudioContextType::UNSPECIFIED); + + log::debug("Replaced the unsupported contexts: {} with UNSPECIFIED -> {}", + ToString(unavail_contexts), ToString(contexts_pair.get(dir))); } else { log::debug("Some contexts are supported but currently unavailable: {}!", ToString(unavail_but_supported)); @@ -4732,7 +4737,8 @@ public: std::tie(dir, other_dir, local_hal_state) = entry; if (contexts_pair.get(dir).test(LeAudioContextType::UNSPECIFIED)) { - /* Try to use the other direction context if not UNSPECIFIED and active + /* If this directions is streaming just UNSPECIFIED and if other direction is streaming some + * meaningfull context type, try to use the meaningful context type */ if (contexts_pair.get(dir) == AudioContexts(LeAudioContextType::UNSPECIFIED)) { auto is_other_direction_streaming = (*local_hal_state == AudioState::STARTED) || @@ -4746,7 +4752,8 @@ public: contexts_pair.get(dir) = contexts_pair.get(other_dir); } } else { - log::debug("Removing UNSPECIFIED from the remote sink context: {}", + log::debug("Removing UNSPECIFIED from the remote {} context: {}", + dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" : " Source", ToString(contexts_pair.get(other_dir))); contexts_pair.get(dir).unset(LeAudioContextType::UNSPECIFIED); } @@ -4794,14 +4801,23 @@ public: BidirectionalPair DirectionalRealignMetadataAudioContexts( LeAudioDeviceGroup* group, int remote_direction) { - auto remote_other_direction = - (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink - ? bluetooth::le_audio::types::kLeAudioDirectionSource - : bluetooth::le_audio::types::kLeAudioDirectionSink); - auto other_direction_hal = - (remote_other_direction == bluetooth::le_audio::types::kLeAudioDirectionSource - ? audio_receiver_state_ - : audio_sender_state_); + uint8_t remote_other_direction; + std::string remote_direction_str; + std::string remote_other_direction_str; + AudioState other_direction_hal; + + if (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink) { + remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSource; + remote_direction_str = "Sink"; + remote_other_direction_str = "Source"; + other_direction_hal = audio_receiver_state_; + } else { + remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSink; + remote_direction_str = "Source"; + remote_other_direction_str = "Sink"; + other_direction_hal = audio_sender_state_; + } + auto is_streaming_other_direction = (other_direction_hal == AudioState::STARTED) || (other_direction_hal == AudioState::READY_TO_START); auto is_releasing_for_reconfiguration = @@ -4863,9 +4879,7 @@ public: ToString(local_metadata_context_types_.sink)); log::debug("remote_metadata.source= {}", ToString(remote_metadata.source)); log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink)); - log::debug("remote_direction= {}", - (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSource ? "Source" - : "Sink")); + log::debug("remote_direction= {}", remote_direction_str); log::debug("is_streaming_other_direction= {}", is_streaming_other_direction ? "True" : "False"); log::debug("is_releasing_for_reconfiguration= {}", is_releasing_for_reconfiguration ? "True" : "False"); diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 05a26249ac4..37367f040d7 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -10606,7 +10606,7 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - log::info("TESTPOING 4: Disable call so we could go back to MEDIA"); + log::info("TESTPOINT 4: Disable call so we could go back to MEDIA"); // --------------------------------------- // Suspend should stop the stream EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1); -- GitLab From 78d2c3edc9b9e435c9f70998c5174f28224945d6 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 25 Oct 2024 14:54:27 -0700 Subject: [PATCH 465/875] Metadata: broadcast from main thread and improve logging Test: atest CtsBluetoothTestCases:setGetMetadata Bug: 366295491 Flag: Exempt refactor & logging change Change-Id: I68c7645146fa32724ca613ab58fc78bd2ae9f26c --- .../btservice/AdapterNativeInterface.java | 6 ++- .../bluetooth/btservice/AdapterService.java | 14 ++++-- .../btservice/storage/DatabaseManager.java | 13 +++--- .../storage/DatabaseManagerTest.java | 43 +++++++++---------- .../android/bluetooth/BluetoothAdapter.java | 4 +- 5 files changed, 42 insertions(+), 38 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java index 4a5bb81267d..33bf3c3f8ff 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java @@ -16,9 +16,11 @@ package com.android.bluetooth.btservice; +import android.bluetooth.BluetoothDevice; import android.bluetooth.OobData; import android.os.ParcelUuid; +import com.android.bluetooth.Utils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -210,8 +212,8 @@ public class AdapterNativeInterface { return allowLowLatencyAudioNative(allowed, address); } - void metadataChanged(byte[] address, int key, byte[] value) { - metadataChangedNative(address, key, value); + void metadataChanged(BluetoothDevice device, int key, byte[] value) { + metadataChangedNative(Utils.getBytesFromAddress(device.getAddress()), key, value); } boolean interopMatchAddr(String featureName, String address) { diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 3739d4580eb..961cb0d1bce 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -6287,24 +6287,30 @@ public class AdapterService extends Service { /** Update metadata change to registered listeners */ @VisibleForTesting - public void metadataChanged(String address, int key, byte[] value) { - BluetoothDevice device = mRemoteDevices.getDevice(Utils.getBytesFromAddress(address)); + public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) { + mHandler.post(() -> onMetadataChangedInternal(device, key, value)); + } + + private void onMetadataChangedInternal(BluetoothDevice device, int key, byte[] value) { + String info = "onMetadataChangedInternal(" + device + ", " + key + ")"; // pass just interesting metadata to native, to reduce spam if (key == BluetoothDevice.METADATA_LE_AUDIO) { - mNativeInterface.metadataChanged(Utils.getBytesFromAddress(address), key, value); + mNativeInterface.metadataChanged(device, key, value); } RemoteCallbackList list = mMetadataListeners.get(device); if (list == null) { + Log.d(TAG, info + ": No registered listener"); return; } int n = list.beginBroadcast(); + Log.d(TAG, info + ": Broadcast to " + n + " receivers"); for (int i = 0; i < n; i++) { try { list.getBroadcastItem(i).onMetadataChanged(device, key, value); } catch (RemoteException e) { - Log.d(TAG, "metadataChanged() - Callback #" + i + " failed (" + e + ")"); + Log.d(TAG, info + ": Callback #" + i + " failed (" + e + ")"); } } list.finishBroadcast(); diff --git a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java index b710c858f57..32379933d91 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java @@ -244,7 +244,7 @@ public class DatabaseManager { Metadata data = mMetadataCache.get(address); byte[] oldValue = data.getCustomizedMeta(key); if (oldValue != null && Arrays.equals(oldValue, newValue)) { - Log.v(TAG, "setCustomMeta: metadata not changed."); + Log.d(TAG, "setCustomMeta: metadata not changed."); return true; } logManufacturerInfo(device, key, newValue); @@ -253,7 +253,7 @@ public class DatabaseManager { updateDatabase(data); } - mAdapterService.metadataChanged(address, key, newValue); + mAdapterService.onMetadataChanged(device, key, newValue); return true; } @@ -1198,13 +1198,12 @@ public class DatabaseManager { && !Arrays.asList(bondedDevices).stream() .anyMatch(device -> address.equals(device.getAddress()))) { List list = metadata.getChangedCustomizedMeta(); + BluetoothDevice device = + BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); for (int key : list) { - mAdapterService.metadataChanged(address, key, null); + mAdapterService.onMetadataChanged(device, key, null); } - Log.i( - TAG, - "remove unpaired device from database " - + metadata.getAnonymizedAddress()); + Log.i(TAG, "remove unpaired device from database " + device); deleteDatabase(mMetadataCache.get(address)); } }); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java index 09062e51395..be78d864637 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java @@ -19,7 +19,6 @@ package com.android.bluetooth.btservice.storage; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -84,6 +83,8 @@ public final class DatabaseManagerTest { private BluetoothDevice mTestDevice; private BluetoothDevice mTestDevice2; private BluetoothDevice mTestDevice3; + private BluetoothDevice mTestDevice4; + private BluetoothDevice mTestDevice5; private static final String LOCAL_STORAGE = "LocalStorage"; private static final String TEST_BT_ADDR = "11:22:33:44:55:66"; @@ -93,7 +94,7 @@ public final class DatabaseManagerTest { private static final String OTHER_BT_ADDR2 = "22:22:22:22:22:22"; private static final String DB_NAME = "test_db"; private static final int A2DP_SUPPORT_OP_CODEC_TEST = 0; - private static final int A2DP_ENALBED_OP_CODEC_TEST = 1; + private static final int A2DP_ENABLED_OP_CODEC_TEST = 1; private static final int MAX_META_ID = 16; private static final byte[] TEST_BYTE_ARRAY = "TEST_VALUE".getBytes(); @@ -113,6 +114,8 @@ public final class DatabaseManagerTest { mTestDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR); mTestDevice2 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR2); mTestDevice3 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR3); + mTestDevice4 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(OTHER_BT_ADDR1); + mTestDevice5 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(OTHER_BT_ADDR2); // Create a memory database for DatabaseManager instead of use a real database. mDatabase = @@ -131,7 +134,7 @@ public final class DatabaseManagerTest { BluetoothDevice[] bondedDevices = {mTestDevice}; doReturn(bondedDevices).when(mAdapterService).getBondedDevices(); - doNothing().when(mAdapterService).metadataChanged(anyString(), anyInt(), any(byte[].class)); + doNothing().when(mAdapterService).onMetadataChanged(any(), anyInt(), any()); restartDatabaseManagerHelper(); } @@ -271,44 +274,44 @@ public final class DatabaseManagerTest { // Cases of device not in database testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, false, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, false, BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, false, BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, false, badValue, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); // Cases of device already in database testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, true, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, true, BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED, BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED); testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, true, BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED, BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED); testSetGetA2dpOptionalCodecsCase( - A2DP_ENALBED_OP_CODEC_TEST, + A2DP_ENABLED_OP_CODEC_TEST, true, badValue, BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); @@ -333,7 +336,7 @@ public final class DatabaseManagerTest { TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper()); // Check removed device report metadata changed to null - verify(mAdapterService).metadataChanged(OTHER_BT_ADDR1, 0, null); + verify(mAdapterService).onMetadataChanged(mTestDevice4, 0, null); List list = mDatabase.load(); @@ -374,18 +377,14 @@ public final class DatabaseManagerTest { mDatabase.insert(otherData2); // Add OTHER_BT_ADDR1 OTHER_BT_ADDR2 to bonded devices - BluetoothDevice otherDevice1 = - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(OTHER_BT_ADDR1); - BluetoothDevice otherDevice2 = - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(OTHER_BT_ADDR2); - BluetoothDevice[] bondedDevices = {otherDevice1, otherDevice2}; + BluetoothDevice[] bondedDevices = {mTestDevice4, mTestDevice5}; doReturn(bondedDevices).when(mAdapterService).getBondedDevices(); mDatabaseManager.removeUnusedMetadata(); TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper()); // Check TEST_BT_ADDR report metadata changed to null - verify(mAdapterService).metadataChanged(TEST_BT_ADDR, 0, null); + verify(mAdapterService).onMetadataChanged(mTestDevice, 0, null); // Check number of metadata in the database List list = mDatabase.load(); @@ -1692,14 +1691,14 @@ public final class DatabaseManagerTest { mDatabase.insert(data); Assert.assertEquals( expectedResult, mDatabaseManager.setCustomMeta(mTestDevice, key, testValue)); - verify(mAdapterService).metadataChanged(TEST_BT_ADDR, key, testValue); + verify(mAdapterService).onMetadataChanged(mTestDevice, key, testValue); verifyTime++; } Assert.assertEquals( expectedResult, mDatabaseManager.setCustomMeta(mTestDevice, key, value)); if (expectedResult) { // Check for callback and get value - verify(mAdapterService, times(verifyTime)).metadataChanged(TEST_BT_ADDR, key, value); + verify(mAdapterService, times(verifyTime)).onMetadataChanged(mTestDevice, key, value); Assert.assertEquals(value, mDatabaseManager.getCustomMeta(mTestDevice, key)); } else { Assert.assertNull(mDatabaseManager.getCustomMeta(mTestDevice, key)); @@ -1841,9 +1840,7 @@ public final class DatabaseManagerTest { return null; }; - doAnswer(answer) - .when(mAdapterService) - .metadataChanged(any(String.class), anyInt(), any(byte[].class)); + doAnswer(answer).when(mAdapterService).onMetadataChanged(any(), anyInt(), any()); mDatabaseManager.setCustomMeta(mTestDevice, key, newValue); diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index f345bb5502f..050ea75b79c 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -4556,7 +4556,7 @@ public final class BluetoothAdapter { @NonNull BluetoothDevice device, @NonNull Executor executor, @NonNull OnMetadataChangedListener listener) { - if (DBG) Log.d(TAG, "addOnMetadataChangedListener()"); + if (DBG) Log.d(TAG, "addOnMetadataChangedListener(" + device + ", " + listener + ")"); requireNonNull(device); requireNonNull(executor); requireNonNull(listener); @@ -4631,7 +4631,7 @@ public final class BluetoothAdapter { @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener( @NonNull BluetoothDevice device, @NonNull OnMetadataChangedListener listener) { - if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()"); + if (DBG) Log.d(TAG, "removeOnMetadataChangedListener(" + device + ", " + listener + ")"); requireNonNull(device); requireNonNull(listener); -- GitLab From a39ff179e772388f03193c939dd5ae03e6f947e2 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 23 Oct 2024 18:24:10 -0700 Subject: [PATCH 466/875] A2dpService: merge "start" into constructor Test: atest BluetoothInstrumentationTests Flag: Exempt refactor no-op Bug: 311772251 Change-Id: I5fe50f03a6ac5761f19da9e046e7c7dc606674ba --- .../android/bluetooth/a2dp/A2dpService.java | 132 ++--- .../bluetooth/a2dp/A2dpStackEvent.java | 22 +- .../bluetooth/a2dp/A2dpStateMachine.java | 478 +++++++----------- .../bluetooth/a2dp/A2dpServiceTest.java | 240 +++------ .../bluetooth/a2dp/A2dpStateMachineTest.java | 438 +++++++--------- system/include/hardware/bt_av.h | 2 +- 6 files changed, 494 insertions(+), 818 deletions(-) diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java index d370baaeec7..9f4ddf423a3 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java @@ -18,6 +18,8 @@ package com.android.bluetooth.a2dp; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static com.android.bluetooth.Utils.checkCallerTargetSdk; @@ -84,17 +86,18 @@ public class A2dpService extends ProfileService { private static A2dpService sA2dpService; private final A2dpNativeInterface mNativeInterface; + private final A2dpCodecConfig mA2dpCodecConfig; private final AdapterService mAdapterService; private final AudioManager mAudioManager; private final DatabaseManager mDatabaseManager; private final CompanionDeviceManager mCompanionDeviceManager; private final Looper mLooper; private final Handler mHandler; - - private HandlerThread mStateMachinesThread; + private final HandlerThread mStateMachinesThread; + // Upper limit of all A2DP devices that are Connected or Connecting + private final int mMaxConnectedAudioDevices; @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); - private A2dpCodecConfig mA2dpCodecConfig; @GuardedBy("mStateMachines") private BluetoothDevice mActiveDevice; @@ -111,10 +114,8 @@ public class A2dpService extends ProfileService { // Upper limit of all A2DP devices: Bonded or Connected private static final int MAX_A2DP_STATE_MACHINES = 50; - // Upper limit of all A2DP devices that are Connected or Connecting - private int mMaxConnectedAudioDevices = 1; // A2DP Offload Enabled in platform - boolean mA2dpOffloadEnabled = false; + private final boolean mA2dpOffloadEnabled; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); @@ -133,62 +134,43 @@ public class A2dpService extends ProfileService { mCompanionDeviceManager = requireNonNull(getSystemService(CompanionDeviceManager.class)); mLooper = requireNonNull(looper); mHandler = new Handler(mLooper); - } - - public static boolean isEnabled() { - return BluetoothProperties.isProfileA2dpSourceEnabled().orElse(false); - } - - ActiveDeviceManager getActiveDeviceManager() { - return mAdapterService.getActiveDeviceManager(); - } - @Override - protected IProfileServiceBinder initBinder() { - return new BluetoothA2dpBinder(this); - } - - @Override - public void start() { - Log.i(TAG, "start()"); - if (sA2dpService != null) { - throw new IllegalStateException("start() called twice"); - } - - // Step 2: Get maximum number of connected audio devices mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices(); Log.i(TAG, "Max connected audio devices set to " + mMaxConnectedAudioDevices); - // Step 3: Start handler thread for state machines - // Setup Handler. - mStateMachines.clear(); - if (!Flags.a2dpServiceLooper()) { mStateMachinesThread = new HandlerThread("A2dpService.StateMachines"); mStateMachinesThread.start(); + } else { + mStateMachinesThread = null; } - // Step 4: Setup codec config mA2dpCodecConfig = new A2dpCodecConfig(this, mNativeInterface); - // Step 5: Initialize native interface mNativeInterface.init( mMaxConnectedAudioDevices, mA2dpCodecConfig.codecConfigPriorities(), mA2dpCodecConfig.codecConfigOffloading()); - // Step 6: Check if A2DP is in offload mode mA2dpOffloadEnabled = mAdapterService.isA2dpOffloadEnabled(); Log.d(TAG, "A2DP offload flag set to " + mA2dpOffloadEnabled); - // Step 7: Register Audio Device callback mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); - // Step 8: Mark service as started setA2dpService(this); + } - // Step 9: Clear active device - removeActiveDevice(false); + public static boolean isEnabled() { + return BluetoothProperties.isProfileA2dpSourceEnabled().orElse(false); + } + + ActiveDeviceManager getActiveDeviceManager() { + return mAdapterService.getActiveDeviceManager(); + } + + @Override + protected IProfileServiceBinder initBinder() { + return new BluetoothA2dpBinder(this); } @Override @@ -211,14 +193,10 @@ public class A2dpService extends ProfileService { // Step 6: Cleanup native interface mNativeInterface.cleanup(); - // Step 5: Clear codec config - mA2dpCodecConfig = null; - // Step 4: Destroy state machines and stop handler thread synchronized (mStateMachines) { for (A2dpStateMachine sm : mStateMachines.values()) { sm.doQuit(); - sm.cleanup(); } mStateMachines.clear(); } @@ -227,21 +205,12 @@ public class A2dpService extends ProfileService { try { mStateMachinesThread.quitSafely(); mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); - mStateMachinesThread = null; } catch (InterruptedException e) { // Do not rethrow as we are shutting down anyway } } mHandler.removeCallbacksAndMessages(null); - - // Step 2: Reset maximum number of connected audio devices - mMaxConnectedAudioDevices = 1; - } - - @Override - public void cleanup() { - Log.i(TAG, "cleanup()"); } public static synchronized A2dpService getA2dpService() { @@ -301,7 +270,7 @@ public class A2dpService extends ProfileService { Log.e(TAG, "Cannot connect to " + device + " : no state machine"); return false; } - smConnect.sendMessage(A2dpStateMachine.CONNECT); + smConnect.sendMessage(A2dpStateMachine.MESSAGE_CONNECT); return true; } } @@ -321,7 +290,7 @@ public class A2dpService extends ProfileService { Log.e(TAG, "Ignored disconnect request for " + device + " : no state machine"); return false; } - sm.sendMessage(A2dpStateMachine.DISCONNECT); + sm.sendMessage(A2dpStateMachine.MESSAGE_DISCONNECT); return true; } } @@ -402,14 +371,14 @@ public class A2dpService extends ProfileService { } } if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_UNKNOWN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { + && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { if (!isOutgoingRequest) { HeadsetService headsetService = HeadsetService.getHeadsetService(); if (headsetService != null && headsetService.okToAcceptConnection(device, true)) { Log.d( - TAG, - "okToConnect: return false," - + " Fallback connection to allowed HFP profile"); + TAG, + "okToConnect: return false," + + " Fallback connection to allowed HFP profile"); headsetService.connect(device); return false; } @@ -938,8 +907,7 @@ public class A2dpService extends ProfileService { if (sm == null) { if (stackEvent.type == A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { switch (stackEvent.valueInt) { - case A2dpStackEvent.CONNECTION_STATE_CONNECTED: - case A2dpStackEvent.CONNECTION_STATE_CONNECTING: + case STATE_CONNECTED, STATE_CONNECTING -> { // Create a new state machine only when connecting to a device if (!connectionAllowedCheckMaxDevices(device)) { Log.e( @@ -950,9 +918,7 @@ public class A2dpService extends ProfileService { return; } sm = getOrCreateStateMachine(device); - break; - default: - break; + } } } } @@ -960,7 +926,7 @@ public class A2dpService extends ProfileService { Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); return; } - sm.sendMessage(A2dpStateMachine.STACK_EVENT, stackEvent); + sm.sendMessage(A2dpStateMachine.MESSAGE_STACK_EVENT, stackEvent); } } @@ -1045,10 +1011,11 @@ public class A2dpService extends ProfileService { } Log.d(TAG, "Creating a new state machine for " + device); sm = - A2dpStateMachine.make( - device, + new A2dpStateMachine( this, + device, mNativeInterface, + mA2dpOffloadEnabled, Flags.a2dpServiceLooper() ? mLooper : mStateMachinesThread.getLooper()); mStateMachines.put(device, sm); return sm; @@ -1225,7 +1192,6 @@ public class A2dpService extends ProfileService { } Log.i(TAG, "removeStateMachine: removing state machine for device: " + device); sm.doQuit(); - sm.cleanup(); mStateMachines.remove(device); } } @@ -1697,25 +1663,21 @@ public class A2dpService extends ProfileService { ProfileService.println(sb, "mActiveDevice: " + mActiveDevice); } ProfileService.println(sb, "mMaxConnectedAudioDevices: " + mMaxConnectedAudioDevices); - if (mA2dpCodecConfig != null) { - ProfileService.println(sb, "codecConfigPriorities:"); - for (BluetoothCodecConfig codecConfig : mA2dpCodecConfig.codecConfigPriorities()) { - ProfileService.println( - sb, - " " - + BluetoothCodecConfig.getCodecName(codecConfig.getCodecType()) - + ": " - + codecConfig.getCodecPriority()); - } - ProfileService.println(sb, "mA2dpOffloadEnabled: " + mA2dpOffloadEnabled); - if (mA2dpOffloadEnabled) { - ProfileService.println(sb, "codecConfigOffloading:"); - for (BluetoothCodecConfig codecConfig : mA2dpCodecConfig.codecConfigOffloading()) { - ProfileService.println(sb, " " + codecConfig); - } + ProfileService.println(sb, "codecConfigPriorities:"); + for (BluetoothCodecConfig codecConfig : mA2dpCodecConfig.codecConfigPriorities()) { + ProfileService.println( + sb, + " " + + BluetoothCodecConfig.getCodecName(codecConfig.getCodecType()) + + ": " + + codecConfig.getCodecPriority()); + } + ProfileService.println(sb, "mA2dpOffloadEnabled: " + mA2dpOffloadEnabled); + if (mA2dpOffloadEnabled) { + ProfileService.println(sb, "codecConfigOffloading:"); + for (BluetoothCodecConfig codecConfig : mA2dpCodecConfig.codecConfigOffloading()) { + ProfileService.println(sb, " " + codecConfig); } - } else { - ProfileService.println(sb, "mA2dpCodecConfig: null"); } for (A2dpStateMachine sm : mStateMachines.values()) { sm.dump(sb); diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java b/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java index d5dedd852d0..6c66f0119b0 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java @@ -16,6 +16,8 @@ package com.android.bluetooth.a2dp; +import static android.bluetooth.BluetoothProfile.getConnectionStateName; + import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; @@ -30,12 +32,6 @@ public class A2dpStackEvent { public static final int EVENT_TYPE_AUDIO_STATE_CHANGED = 2; public static final int EVENT_TYPE_CODEC_CONFIG_CHANGED = 3; - // Do not modify without updating the HAL bt_av.h files. - // Match up with btav_connection_state_t enum of bt_av.h - static final int CONNECTION_STATE_DISCONNECTED = 0; - static final int CONNECTION_STATE_CONNECTING = 1; - static final int CONNECTION_STATE_CONNECTED = 2; - static final int CONNECTION_STATE_DISCONNECTING = 3; // Match up with btav_audio_state_t enum of bt_av.h static final int AUDIO_STATE_REMOTE_SUSPEND = 0; static final int AUDIO_STATE_STOPPED = 1; @@ -82,19 +78,7 @@ public class A2dpStackEvent { private static String eventTypeValueIntToString(int type, int value) { switch (type) { case EVENT_TYPE_CONNECTION_STATE_CHANGED: - switch (value) { - case CONNECTION_STATE_DISCONNECTED: - return "DISCONNECTED"; - case CONNECTION_STATE_CONNECTING: - return "CONNECTING"; - case CONNECTION_STATE_CONNECTED: - return "CONNECTED"; - case CONNECTION_STATE_DISCONNECTING: - return "DISCONNECTING"; - default: - break; - } - break; + return getConnectionStateName(value); case EVENT_TYPE_AUDIO_STATE_CHANGED: switch (value) { case AUDIO_STATE_REMOTE_SUSPEND: diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java index b53ee4c5056..f0b5a028ac0 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java @@ -14,22 +14,38 @@ * limitations under the License. */ -/** - * Bluetooth A2DP StateMachine. There is one instance per remote device. - "Disconnected" and - * "Connected" are steady states. - "Connecting" and "Disconnecting" are transient states until the - * connection / disconnection is completed. - * - *

    (Disconnected) | ^ CONNECT | | DISCONNECTED V | (Connecting)<--->(Disconnecting) | ^ CONNECTED - * | | DISCONNECT V | (Connected) NOTES: - If state machine is in "Connecting" state and the remote - * device sends DISCONNECT request, the state machine transitions to "Disconnecting" state. - - * Similarly, if the state machine is in "Disconnecting" state and the remote device sends CONNECT - * request, the state machine transitions to "Connecting" state. - * - *

    DISCONNECT (Connecting) ---------------> (Disconnecting) <--------------- CONNECT - */ +// Bluetooth A2DP StateMachine. There is one instance per remote device. +// - "Disconnected" and "Connected" are steady states. +// - "Connecting" and "Disconnecting" are transient states until the +// connection / disconnection is completed. + +// (Disconnected) +// | ^ +// CONNECT | | DISCONNECTED +// V | +// (Connecting)<--->(Disconnecting) +// | ^ +// CONNECTED | | DISCONNECT +// V | +// (Connected) +// NOTES: +// - If state machine is in "Connecting" state and the remote device sends +// DISCONNECT request, the state machine transitions to "Disconnecting" state. +// - Similarly, if the state machine is in "Disconnecting" state and the remote device +// sends CONNECT request, the state machine transitions to "Connecting" state. + +// DISCONNECT +// (Connecting) ---------------> (Disconnecting) +// <--------------- +// CONNECT package com.android.bluetooth.a2dp; 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 android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; +import static android.bluetooth.BluetoothProfile.getConnectionStateName; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothCodecConfig; @@ -54,6 +70,7 @@ import com.android.internal.util.StateMachine; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Duration; import java.util.List; import java.util.Objects; import java.util.Scanner; @@ -61,32 +78,32 @@ import java.util.Scanner; final class A2dpStateMachine extends StateMachine { private static final String TAG = A2dpStateMachine.class.getSimpleName(); - static final int CONNECT = 1; - static final int DISCONNECT = 2; - @VisibleForTesting static final int STACK_EVENT = 101; - private static final int CONNECT_TIMEOUT = 201; + static final int MESSAGE_CONNECT = 1; + static final int MESSAGE_DISCONNECT = 2; + @VisibleForTesting static final int MESSAGE_STACK_EVENT = 101; + private static final int MESSAGE_CONNECT_TIMEOUT = 201; - // NOTE: the value is not "final" - it is modified in the unit tests - @VisibleForTesting static int sConnectTimeoutMs = 30000; // 30s + @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(30); - private Disconnected mDisconnected; - private Connecting mConnecting; - private Disconnecting mDisconnecting; - private Connected mConnected; - private int mConnectionState = BluetoothProfile.STATE_DISCONNECTED; - private int mLastConnectionState = -1; - - private A2dpService mA2dpService; - private A2dpNativeInterface mA2dpNativeInterface; - @VisibleForTesting boolean mA2dpOffloadEnabled = false; + private final A2dpService mA2dpService; + private final A2dpNativeInterface mA2dpNativeInterface; private final BluetoothDevice mDevice; + private final Disconnected mDisconnected; + private final Connecting mConnecting; + private final Disconnecting mDisconnecting; + private final Connected mConnected; + private final boolean mA2dpOffloadEnabled; + private boolean mIsPlaying = false; + private int mConnectionState = STATE_DISCONNECTED; + private int mLastConnectionState = -1; private BluetoothCodecStatus mCodecStatus; A2dpStateMachine( - BluetoothDevice device, A2dpService a2dpService, + BluetoothDevice device, A2dpNativeInterface a2dpNativeInterface, + boolean a2dpOffloadEnabled, Looper looper) { super(TAG, looper); @@ -107,31 +124,20 @@ final class A2dpStateMachine extends StateMachine { addState(mConnecting); addState(mDisconnecting); addState(mConnected); - mA2dpOffloadEnabled = mA2dpService.mA2dpOffloadEnabled; + mA2dpOffloadEnabled = a2dpOffloadEnabled; setInitialState(mDisconnected); - } - - static A2dpStateMachine make( - BluetoothDevice device, - A2dpService a2dpService, - A2dpNativeInterface a2dpNativeInterface, - Looper looper) { - Log.i(TAG, "make for device " + device); - A2dpStateMachine a2dpSm = - new A2dpStateMachine(device, a2dpService, a2dpNativeInterface, looper); - a2dpSm.start(); - return a2dpSm; + start(); } public void doQuit() { log("doQuit for device " + mDevice); if (Flags.a2dpBroadcastConnectionStateWhenTurnedOff() - && mConnectionState != BluetoothProfile.STATE_DISCONNECTED + && mConnectionState != STATE_DISCONNECTED && mLastConnectionState != -1) { // Broadcast CONNECTION_STATE_CHANGED when A2dpService is turned off while // the device is connected - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED, mConnectionState); + broadcastConnectionState(STATE_DISCONNECTED, mConnectionState); } if (mIsPlaying) { // Broadcast AUDIO_STATE_CHANGED when A2dpService is turned off while @@ -142,10 +148,6 @@ final class A2dpStateMachine extends StateMachine { quitNow(); } - public void cleanup() { - log("cleanup for device " + mDevice); - } - @VisibleForTesting class Disconnected extends State { @Override @@ -159,9 +161,9 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - mConnectionState = BluetoothProfile.STATE_DISCONNECTED; + mConnectionState = STATE_DISCONNECTED; - removeDeferredMessages(DISCONNECT); + removeDeferredMessages(MESSAGE_DISCONNECT); if (mLastConnectionState != -1) { // Don't broadcast during startup @@ -187,7 +189,7 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; + mLastConnectionState = STATE_DISCONNECTED; } @Override @@ -199,7 +201,7 @@ final class A2dpStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: + case MESSAGE_CONNECT -> { Log.i(TAG, "Connecting to " + mDevice); if (!mA2dpNativeInterface.connectA2dp(mDevice)) { Log.e(TAG, "Disconnected: error connecting to " + mDevice); @@ -211,30 +213,26 @@ final class A2dpStateMachine extends StateMachine { // Reject the request and stay in Disconnected state Log.w(TAG, "Outgoing A2DP Connecting request rejected: " + mDevice); } - break; - case DISCONNECT: - Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice); - break; - case STACK_EVENT: + } + case MESSAGE_DISCONNECT -> + Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice); + case MESSAGE_STACK_EVENT -> { A2dpStackEvent event = (A2dpStackEvent) message.obj; log("Disconnected: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt); - break; - case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; + case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> + processConnectionEvent(event.valueInt); + case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED -> + processCodecConfigEvent(event.codecStatus); + default -> Log.e(TAG, "Disconnected: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -242,10 +240,7 @@ final class A2dpStateMachine extends StateMachine { // in Disconnected state private void processConnectionEvent(int event) { switch (event) { - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Ignore A2DP DISCONNECTED event: " + mDevice); - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTING: + case STATE_CONNECTING -> { if (mA2dpService.okToConnect(mDevice, false)) { Log.i(TAG, "Incoming A2DP Connecting request accepted: " + mDevice); transitionTo(mConnecting); @@ -254,8 +249,8 @@ final class A2dpStateMachine extends StateMachine { Log.w(TAG, "Incoming A2DP Connecting request rejected: " + mDevice); mA2dpNativeInterface.disconnectA2dp(mDevice); } - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { Log.w(TAG, "A2DP Connected from Disconnected state: " + mDevice); if (mA2dpService.okToConnect(mDevice, false)) { Log.i(TAG, "Incoming A2DP Connected request accepted: " + mDevice); @@ -265,23 +260,18 @@ final class A2dpStateMachine extends StateMachine { Log.w(TAG, "Incoming A2DP Connected request rejected: " + mDevice); mA2dpNativeInterface.disconnectA2dp(mDevice); } - break; - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Ignore A2DP DISCONNECTING event: " + mDevice); - break; - default: - Log.e(TAG, "Incorrect event: " + event + " device: " + mDevice); - break; + } + default -> Log.e(TAG, "Incorrect event: " + event + " device: " + mDevice); } } private void logFailureIfNeeded() { - if (mLastConnectionState == BluetoothProfile.STATE_CONNECTING - || mLastConnectionState == BluetoothProfile.STATE_DISCONNECTED) { + if (mLastConnectionState == STATE_CONNECTING + || mLastConnectionState == STATE_DISCONNECTED) { // Result for disconnected -> disconnected is unknown as it should // not have occurred. int result = - (mLastConnectionState == BluetoothProfile.STATE_CONNECTING) + (mLastConnectionState == STATE_CONNECTING) ? BluetoothProtoEnums.RESULT_FAILURE : BluetoothProtoEnums.RESULT_UNKNOWN; @@ -290,7 +280,7 @@ final class A2dpStateMachine extends StateMachine { BluetoothProfile.A2DP, result, mLastConnectionState, - BluetoothProfile.STATE_DISCONNECTED, + STATE_DISCONNECTED, BluetoothProtoEnums.REASON_UNEXPECTED_STATE, MetricsLogger.getInstance().getRemoteDeviceInfoProto(mDevice)); } @@ -310,8 +300,8 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - mConnectionState = BluetoothProfile.STATE_CONNECTING; + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + mConnectionState = STATE_CONNECTING; broadcastConnectionState(mConnectionState, mLastConnectionState); } @@ -325,8 +315,8 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; - removeMessages(CONNECT_TIMEOUT); + mLastConnectionState = STATE_CONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override @@ -338,51 +328,41 @@ final class A2dpStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - { - Log.w(TAG, "Connecting connection timeout: " + mDevice); - mA2dpNativeInterface.disconnectA2dp(mDevice); - A2dpStackEvent event = - new A2dpStackEvent( - A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = mDevice; - event.valueInt = A2dpStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, event); - MetricsLogger.getInstance() - .count(BluetoothProtoEnums.A2DP_CONNECTION_TIMEOUT, 1); - break; - } - case DISCONNECT: + case MESSAGE_CONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { + Log.w(TAG, "Connecting connection timeout: " + mDevice); + mA2dpNativeInterface.disconnectA2dp(mDevice); + A2dpStackEvent event = + new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + event.device = mDevice; + event.valueInt = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, event); + MetricsLogger.getInstance() + .count(BluetoothProtoEnums.A2DP_CONNECTION_TIMEOUT, 1); + } + case MESSAGE_DISCONNECT -> { // Cancel connection Log.i(TAG, "Connecting: connection canceled to " + mDevice); mA2dpNativeInterface.disconnectA2dp(mDevice); transitionTo(mDisconnected); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { A2dpStackEvent event = (A2dpStackEvent) message.obj; log("Connecting: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt); - break; - case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus); - break; - case A2dpStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - break; - default: - Log.e(TAG, "Connecting: ignoring stack event: " + event); - break; + case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> + processConnectionEvent(event.valueInt); + case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED -> + processCodecConfigEvent(event.codecStatus); + default -> Log.e(TAG, "Connecting: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -390,23 +370,16 @@ final class A2dpStateMachine extends StateMachine { // in Connecting state private void processConnectionEvent(int event) { switch (event) { - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.w(TAG, "Connecting device disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTING: - // Ignored - probably an event that the outgoing connection was initiated - break; - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTING: + } + case STATE_CONNECTED -> transitionTo(mConnected); + case STATE_DISCONNECTING -> { Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Incorrect event: " + event); - break; + } + default -> Log.e(TAG, "Incorrect event: " + event); } } } @@ -424,8 +397,8 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - mConnectionState = BluetoothProfile.STATE_DISCONNECTING; + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + mConnectionState = STATE_DISCONNECTING; broadcastConnectionState(mConnectionState, mLastConnectionState); } @@ -439,8 +412,8 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); + mLastConnectionState = STATE_DISCONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override @@ -452,45 +425,33 @@ final class A2dpStateMachine extends StateMachine { + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - { - Log.w(TAG, "Disconnecting connection timeout: " + mDevice); - mA2dpNativeInterface.disconnectA2dp(mDevice); - A2dpStackEvent event = - new A2dpStackEvent( - A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = mDevice; - event.valueInt = A2dpStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, event); - break; - } - case DISCONNECT: - deferMessage(message); - break; - case STACK_EVENT: + case MESSAGE_CONNECT, MESSAGE_DISCONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { + Log.w(TAG, "Disconnecting connection timeout: " + mDevice); + mA2dpNativeInterface.disconnectA2dp(mDevice); + A2dpStackEvent event = + new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + event.device = mDevice; + event.valueInt = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, event); + } + case MESSAGE_STACK_EVENT -> { A2dpStackEvent event = (A2dpStackEvent) message.obj; log("Disconnecting: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt); - break; - case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus); - break; - case A2dpStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - default: - Log.e(TAG, "Disconnecting: ignoring stack event: " + event); - break; + case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> + processConnectionEvent(event.valueInt); + case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED -> + processCodecConfigEvent(event.codecStatus); + default -> Log.e(TAG, "Disconnecting: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -498,11 +459,11 @@ final class A2dpStateMachine extends StateMachine { // in Disconnecting state private void processConnectionEvent(int event) { switch (event) { - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected: " + mDevice); transitionTo(mDisconnected); - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { if (mA2dpService.okToConnect(mDevice, false)) { Log.w(TAG, "Disconnecting interrupted: device is connected: " + mDevice); transitionTo(mConnected); @@ -511,8 +472,8 @@ final class A2dpStateMachine extends StateMachine { Log.w(TAG, "Incoming A2DP Connected request rejected: " + mDevice); mA2dpNativeInterface.disconnectA2dp(mDevice); } - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTING: + } + case STATE_CONNECTING -> { if (mA2dpService.okToConnect(mDevice, false)) { Log.i(TAG, "Disconnecting interrupted: try to reconnect: " + mDevice); transitionTo(mConnecting); @@ -521,13 +482,8 @@ final class A2dpStateMachine extends StateMachine { Log.w(TAG, "Incoming A2DP Connecting request rejected: " + mDevice); mA2dpNativeInterface.disconnectA2dp(mDevice); } - break; - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTING: - // We are already disconnecting, do nothing - break; - default: - Log.e(TAG, "Incorrect event: " + event); - break; + } + default -> Log.e(TAG, "Incorrect event: " + event); } } } @@ -545,9 +501,9 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - mConnectionState = BluetoothProfile.STATE_CONNECTED; + mConnectionState = STATE_CONNECTED; - removeDeferredMessages(CONNECT); + removeDeferredMessages(MESSAGE_CONNECT); // Each time a device connects, we want to re-check if it supports optional // codecs (perhaps it's had a firmware update, etc.) and save that state if @@ -571,7 +527,7 @@ final class A2dpStateMachine extends StateMachine { + (currentMessage == null ? "null" : messageWhatToString(currentMessage.what))); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; + mLastConnectionState = STATE_CONNECTED; } @Override @@ -579,45 +535,36 @@ final class A2dpStateMachine extends StateMachine { log("Connected process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); - break; - case DISCONNECT: - { - Log.i(TAG, "Disconnecting from " + mDevice); - if (!mA2dpNativeInterface.disconnectA2dp(mDevice)) { - // If error in the native stack, transition directly to Disconnected - // state. - Log.e(TAG, "Connected: error disconnecting from " + mDevice); - transitionTo(mDisconnected); - break; - } - transitionTo(mDisconnecting); + case MESSAGE_DISCONNECT -> { + Log.i(TAG, "Disconnecting from " + mDevice); + if (!mA2dpNativeInterface.disconnectA2dp(mDevice)) { + // If error in the native stack, transition directly to Disconnected + // state. + Log.e(TAG, "Connected: error disconnecting from " + mDevice); + transitionTo(mDisconnected); + break; } - break; - case STACK_EVENT: + transitionTo(mDisconnecting); + } + case MESSAGE_STACK_EVENT -> { A2dpStackEvent event = (A2dpStackEvent) message.obj; log("Connected: stack event: " + event); if (!mDevice.equals(event.device)) { Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); } switch (event.type) { - case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt); - break; - case A2dpStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - processAudioStateEvent(event.valueInt); - break; - case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus); - break; - default: - Log.e(TAG, "Connected: ignoring stack event: " + event); - break; + case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> + processConnectionEvent(event.valueInt); + case A2dpStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED -> + processAudioStateEvent(event.valueInt); + case A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED -> + processCodecConfigEvent(event.codecStatus); + default -> Log.e(TAG, "Connected: ignoring stack event: " + event); } - break; - default: + } + default -> { return NOT_HANDLED; + } } return HANDLED; } @@ -625,30 +572,23 @@ final class A2dpStateMachine extends StateMachine { // in Connected state private void processConnectionEvent(int event) { switch (event) { - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTED: + case STATE_DISCONNECTED -> { Log.i(TAG, "Disconnected from " + mDevice); transitionTo(mDisconnected); - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTED: - Log.w(TAG, "Ignore A2DP CONNECTED event: " + mDevice); - break; - case A2dpStackEvent.CONNECTION_STATE_CONNECTING: - Log.w(TAG, "Ignore A2DP CONNECTING event: " + mDevice); - break; - case A2dpStackEvent.CONNECTION_STATE_DISCONNECTING: + } + case STATE_DISCONNECTING -> { Log.i(TAG, "Disconnecting from " + mDevice); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad event: " + event); - break; + } + default -> + Log.e(TAG, "Connection State Device: " + mDevice + " bad event: " + event); } } // in Connected state private void processAudioStateEvent(int state) { switch (state) { - case A2dpStackEvent.AUDIO_STATE_STARTED: + case A2dpStackEvent.AUDIO_STATE_STARTED -> { synchronized (this) { if (!mIsPlaying) { Log.i(TAG, "Connected: started playing: " + mDevice); @@ -657,9 +597,9 @@ final class A2dpStateMachine extends StateMachine { BluetoothA2dp.STATE_PLAYING, BluetoothA2dp.STATE_NOT_PLAYING); } } - break; - case A2dpStackEvent.AUDIO_STATE_REMOTE_SUSPEND: - case A2dpStackEvent.AUDIO_STATE_STOPPED: + } + case A2dpStackEvent.AUDIO_STATE_REMOTE_SUSPEND, + A2dpStackEvent.AUDIO_STATE_STOPPED -> { synchronized (this) { if (mIsPlaying) { Log.i(TAG, "Connected: stopped playing: " + mDevice); @@ -668,22 +608,20 @@ final class A2dpStateMachine extends StateMachine { BluetoothA2dp.STATE_NOT_PLAYING, BluetoothA2dp.STATE_PLAYING); } } - break; - default: - Log.e(TAG, "Audio State Device: " + mDevice + " bad state: " + state); - break; + } + default -> Log.e(TAG, "Audio State Device: " + mDevice + " bad state: " + state); } } private void logSuccessIfNeeded() { - if (mLastConnectionState == BluetoothProfile.STATE_CONNECTING - || mLastConnectionState == BluetoothProfile.STATE_DISCONNECTED) { + if (mLastConnectionState == STATE_CONNECTING + || mLastConnectionState == STATE_DISCONNECTED) { BluetoothStatsLog.write( BluetoothStatsLog.BLUETOOTH_PROFILE_CONNECTION_ATTEMPTED, BluetoothProfile.A2DP, BluetoothProtoEnums.RESULT_SUCCESS, mLastConnectionState, - BluetoothProfile.STATE_CONNECTED, + STATE_CONNECTED, BluetoothProtoEnums.REASON_SUCCESS, MetricsLogger.getInstance().getRemoteDeviceInfoProto(mDevice)); } @@ -700,7 +638,7 @@ final class A2dpStateMachine extends StateMachine { boolean isConnected() { synchronized (this) { - return (getConnectionState() == BluetoothProfile.STATE_CONNECTED); + return (getConnectionState() == STATE_CONNECTED); } } @@ -793,9 +731,9 @@ final class A2dpStateMachine extends StateMachine { "Connection state " + mDevice + ": " - + profileStateToString(prevState) + + getConnectionStateName(prevState) + "->" - + profileStateToString(newState)); + + getConnectionStateName(newState)); Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); @@ -860,47 +798,21 @@ final class A2dpStateMachine extends StateMachine { } private static String messageWhatToString(int what) { - switch (what) { - case CONNECT: - return "CONNECT"; - case DISCONNECT: - return "DISCONNECT"; - case STACK_EVENT: - return "STACK_EVENT"; - case CONNECT_TIMEOUT: - return "CONNECT_TIMEOUT"; - default: - break; - } - return Integer.toString(what); - } - - private static String profileStateToString(int state) { - switch (state) { - case BluetoothProfile.STATE_DISCONNECTED: - return "DISCONNECTED"; - case BluetoothProfile.STATE_CONNECTING: - return "CONNECTING"; - case BluetoothProfile.STATE_CONNECTED: - return "CONNECTED"; - case BluetoothProfile.STATE_DISCONNECTING: - return "DISCONNECTING"; - default: - break; - } - return Integer.toString(state); + return switch (what) { + case MESSAGE_CONNECT -> "CONNECT"; + case MESSAGE_DISCONNECT -> "DISCONNECT"; + case MESSAGE_STACK_EVENT -> "STACK_EVENT"; + case MESSAGE_CONNECT_TIMEOUT -> "CONNECT_TIMEOUT"; + default -> Integer.toString(what); + }; } private static String audioStateToString(int state) { - switch (state) { - case BluetoothA2dp.STATE_PLAYING: - return "PLAYING"; - case BluetoothA2dp.STATE_NOT_PLAYING: - return "NOT_PLAYING"; - default: - break; - } - return Integer.toString(state); + return switch (state) { + case BluetoothA2dp.STATE_PLAYING -> "PLAYING"; + case BluetoothA2dp.STATE_NOT_PLAYING -> "NOT_PLAYING"; + default -> Integer.toString(state); + }; } public void dump(StringBuilder sb) { @@ -912,9 +824,9 @@ final class A2dpStateMachine extends StateMachine { ProfileService.println( sb, " mConnectionState: " - + profileStateToString(mConnectionState) + + getConnectionStateName(mConnectionState) + ", mLastConnectionState: " - + profileStateToString(mLastConnectionState)); + + getConnectionStateName(mLastConnectionState)); ProfileService.println(sb, " mIsPlaying: " + mIsPlaying); ProfileService.println( sb, diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java index de5cde429b4..89bc2a819c7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java @@ -16,6 +16,11 @@ package com.android.bluetooth.a2dp; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; + import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; @@ -141,12 +146,8 @@ public class A2dpServiceTest { doReturn(mSilenceDeviceManager).when(mAdapterService).getSilenceDeviceManager(); mA2dpService = new A2dpService(mAdapterService, mMockNativeInterface, mLooper.getLooper()); - mA2dpService.start(); mA2dpService.setAvailable(true); - // Override the timeout value to speed up the test - A2dpStateMachine.sConnectTimeoutMs = (int) TIMEOUT.toMillis(); - // Get a device for testing doReturn(BluetoothDevice.BOND_BONDED) .when(mAdapterService) @@ -203,10 +204,7 @@ public class A2dpServiceTest { if (Flags.a2dpBroadcastConnectionStateWhenTurnedOff()) { // Verify that the intent CONNECTION_STATE_CHANGED is generated // for the existing connections. - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTED); + verifyConnectionStateIntent(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTED); } // Verify that setActiveDevice(null) was called during shutdown @@ -329,6 +327,7 @@ public class A2dpServiceTest { /** Test that an outgoing connection times out */ @Test + @EnableFlags(Flags.FLAG_A2DP_SERVICE_LOOPER) public void testOutgoingConnectTimeout() { // Update the device priority so okToConnect() returns true when(mDatabaseManager.getProfileConnectionPolicy(sTestDevice, BluetoothProfile.A2DP)) @@ -341,24 +340,16 @@ public class A2dpServiceTest { dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + verifyConnectionStateIntent(sTestDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTING); // Verify a timeout after 1sec. - moveTimeForward(TIMEOUT.toMillis()); + moveTimeForward(A2dpStateMachine.CONNECT_TIMEOUT.toMillis()); dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Disconnected state - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyConnectionStateIntent(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); } /** Test that an outgoing connection/disconnection succeeds */ @@ -377,25 +368,19 @@ public class A2dpServiceTest { dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + verifyConnectionStateIntent(sTestDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTING); // Send a message to trigger connection completed connCompletedEvent = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connCompletedEvent.device = sTestDevice; - connCompletedEvent.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; + connCompletedEvent.valueInt = STATE_CONNECTED; mA2dpService.messageFromNative(connCompletedEvent); dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - sTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + verifyConnectionStateIntent(sTestDevice, STATE_CONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTED); // Verify the list of connected devices assertThat(mA2dpService.getConnectedDevices()).contains(sTestDevice); @@ -405,27 +390,19 @@ public class A2dpServiceTest { dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Disconnecting state - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTING); + verifyConnectionStateIntent(sTestDevice, STATE_DISCONNECTING, STATE_CONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTING); // Send a message to trigger disconnection completed connCompletedEvent = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connCompletedEvent.device = sTestDevice; - connCompletedEvent.valueInt = A2dpStackEvent.CONNECTION_STATE_DISCONNECTED; + connCompletedEvent.valueInt = STATE_DISCONNECTED; mA2dpService.messageFromNative(connCompletedEvent); dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Disconnected state - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_DISCONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyConnectionStateIntent(sTestDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); // Verify the list of connected devices assertThat(mA2dpService.getConnectedDevices()).doesNotContain(sTestDevice); @@ -451,26 +428,18 @@ public class A2dpServiceTest { assertThat(mA2dpService.connect(testDevice)).isTrue(); dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - testDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(testDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + verifyConnectionStateIntent(testDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(testDevice)).isEqualTo(STATE_CONNECTING); // Send a message to trigger connection completed connCompletedEvent = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connCompletedEvent.device = testDevice; - connCompletedEvent.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; + connCompletedEvent.valueInt = STATE_CONNECTED; mA2dpService.messageFromNative(connCompletedEvent); dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - testDevice, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(testDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + verifyConnectionStateIntent(testDevice, STATE_CONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(testDevice)).isEqualTo(STATE_CONNECTED); // Verify the list of connected devices assertThat(mA2dpService.getConnectedDevices()).contains(testDevice); } @@ -496,21 +465,13 @@ public class A2dpServiceTest { doReturn(true).when(mMockNativeInterface).disconnectA2dp(any(BluetoothDevice.class)); // A2DP stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + generateConnectionMessageFromNative(sTestDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTING); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_NONE); @@ -518,10 +479,8 @@ public class A2dpServiceTest { assertThat(mA2dpService.getDevices()).doesNotContain(sTestDevice); // A2DP stack event: CONNECTION_STATE_CONNECTED - state machine should be created - generateConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: EVENT_TYPE_AUDIO_STATE_CHANGED - Intent broadcast should be generated @@ -535,10 +494,8 @@ public class A2dpServiceTest { hasExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothA2dp.STATE_PLAYING)); // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed - generateConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_NONE); @@ -546,17 +503,13 @@ public class A2dpServiceTest { assertThat(mA2dpService.getDevices()).doesNotContain(sTestDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTING - state machine should not be created - generateUnexpectedConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_DISCONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateUnexpectedConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).doesNotContain(sTestDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine should not be created - generateUnexpectedConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateUnexpectedConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).doesNotContain(sTestDevice); } @@ -596,21 +549,18 @@ public class A2dpServiceTest { // A2DP stack event: EVENT_TYPE_AUDIO_STATE_CHANGED - state machine should not be created generateUnexpectedAudioMessageFromNative(sTestDevice, A2dpStackEvent.AUDIO_STATE_STARTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).doesNotContain(sTestDevice); // A2DP stack event: EVENT_TYPE_CODEC_CONFIG_CHANGED - state machine should not be created generateUnexpectedCodecMessageFromNative(sTestDevice, codecStatus); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).doesNotContain(sTestDevice); // A2DP stack event: CONNECTION_STATE_CONNECTED - state machine should be created generateConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + sTestDevice, STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: EVENT_TYPE_AUDIO_STATE_CHANGED - Intent broadcast should be generated @@ -628,21 +578,17 @@ public class A2dpServiceTest { A2dpStackEvent.AUDIO_STATE_STARTED, BluetoothA2dp.STATE_PLAYING, BluetoothA2dp.STATE_NOT_PLAYING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: EVENT_TYPE_CODEC_CONFIG_CHANGED - Intent broadcast should be generated generateCodecMessageFromNative(sTestDevice, codecStatus); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed - generateConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_NONE); dispatchAtLeastOneMessage(); @@ -661,12 +607,8 @@ public class A2dpServiceTest { doReturn(true).when(mMockNativeInterface).disconnectA2dp(any(BluetoothDevice.class)); // A2DP stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + generateConnectionMessageFromNative(sTestDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTING); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // Device unbond - state machine is not removed mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_NONE); @@ -674,10 +616,8 @@ public class A2dpServiceTest { // A2DP stack event: CONNECTION_STATE_CONNECTED - state machine is not removed mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_BONDED); - generateConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_CONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // Device unbond - state machine is not removed mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_NONE); @@ -685,12 +625,8 @@ public class A2dpServiceTest { // A2DP stack event: CONNECTION_STATE_DISCONNECTING - state machine is not removed mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_BONDED); - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTING); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTING, STATE_CONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTING); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // Device unbond - state machine is not removed mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_NONE); @@ -698,12 +634,8 @@ public class A2dpServiceTest { // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_BONDED); - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_DISCONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // Device unbond - state machine is removed mA2dpService.bondStateChanged(sTestDevice, BluetoothDevice.BOND_NONE); @@ -725,30 +657,18 @@ public class A2dpServiceTest { doReturn(true).when(mMockNativeInterface).disconnectA2dp(any(BluetoothDevice.class)); // A2DP stack event: CONNECTION_STATE_CONNECTING - state machine should be created - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + generateConnectionMessageFromNative(sTestDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTING); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: CONNECTION_STATE_CONNECTING - state machine remains - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + generateConnectionMessageFromNative(sTestDevice, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_CONNECTING); assertThat(mA2dpService.getDevices()).contains(sTestDevice); // Device bond state marked as unbond - state machine is not removed @@ -758,12 +678,8 @@ public class A2dpServiceTest { assertThat(mA2dpService.getDevices()).contains(sTestDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine is removed - generateConnectionMessageFromNative( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(sTestDevice)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(sTestDevice)).isEqualTo(STATE_DISCONNECTED); assertThat(mA2dpService.getDevices()).doesNotContain(sTestDevice); } @@ -823,10 +739,7 @@ public class A2dpServiceTest { assertThat(mA2dpService.disconnect(sTestDevice)).isTrue(); dispatchAtLeastOneMessage(); - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); + verifyConnectionStateIntent(sTestDevice, STATE_DISCONNECTING, STATE_CONNECTED); mA2dpService.removeActiveDevice(false); ArgumentCaptor connectionInfoArgumentCaptor = @@ -853,10 +766,7 @@ public class A2dpServiceTest { assertThat(mA2dpService.disconnect(sTestDevice)).isTrue(); dispatchAtLeastOneMessage(); - verifyConnectionStateIntent( - sTestDevice, - BluetoothProfile.STATE_DISCONNECTING, - BluetoothProfile.STATE_CONNECTED); + verifyConnectionStateIntent(sTestDevice, STATE_DISCONNECTING, STATE_CONNECTED); mA2dpService.removeActiveDevice(true); ArgumentCaptor connectionInfoArgumentCaptor = @@ -1080,10 +990,8 @@ public class A2dpServiceTest { dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Connecting state - verifyConnectionStateIntent( - device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mA2dpService.getConnectionState(device)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); + verifyConnectionStateIntent(device, STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mA2dpService.getConnectionState(device)).isEqualTo(STATE_CONNECTING); if (codecStatus != null) { generateCodecMessageFromNative(device, codecStatus); @@ -1092,15 +1000,13 @@ public class A2dpServiceTest { // Send a message to trigger connection completed connCompletedEvent = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connCompletedEvent.device = device; - connCompletedEvent.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; + connCompletedEvent.valueInt = STATE_CONNECTED; mA2dpService.messageFromNative(connCompletedEvent); dispatchAtLeastOneMessage(); // Verify the connection state broadcast, and that we are in Connected state - verifyConnectionStateIntent( - device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - assertThat(mA2dpService.getConnectionState(device)) - .isEqualTo(BluetoothProfile.STATE_CONNECTED); + verifyConnectionStateIntent(device, STATE_CONNECTED, STATE_CONNECTING); + assertThat(mA2dpService.getConnectionState(device)).isEqualTo(STATE_CONNECTED); // Verify that the device is in the list of connected devices assertThat(mA2dpService.getConnectedDevices()).contains(device); @@ -1299,13 +1205,11 @@ public class A2dpServiceTest { // Generate connection request from native with bad codec status connectDeviceWithCodecStatus(sTestDevice, badCodecStatus); - generateConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTED); // Generate connection request from native with good codec status connectDeviceWithCodecStatus(sTestDevice, codecStatus); - generateConnectionMessageFromNative( - sTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); + generateConnectionMessageFromNative(sTestDevice, STATE_DISCONNECTED, STATE_CONNECTED); // Check optional codec status is set properly verify(mDatabaseManager, times(verifyNotSupportTime)) diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java index 5f1c1e9ecd8..eae499a93f9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java @@ -16,35 +16,52 @@ package com.android.bluetooth.a2dp; +import static android.bluetooth.BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED; +import static android.bluetooth.BluetoothProfile.EXTRA_PREVIOUS_STATE; +import static android.bluetooth.BluetoothProfile.EXTRA_STATE; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; + +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; + +import static com.android.bluetooth.a2dp.A2dpStateMachine.MESSAGE_CONNECT; +import static com.android.bluetooth.a2dp.A2dpStateMachine.MESSAGE_STACK_EVENT; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothCodecConfig; import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.Bundle; -import android.os.HandlerThread; +import android.os.test.TestLooper; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; -import com.android.bluetooth.btservice.ActiveDeviceManager; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.SilenceDeviceManager; -import org.junit.After; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; 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.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -53,247 +70,128 @@ import java.util.Arrays; @MediumTest @RunWith(AndroidJUnit4.class) public class A2dpStateMachineTest { - private BluetoothAdapter mAdapter; - private HandlerThread mHandlerThread; - private A2dpStateMachine mA2dpStateMachine; - private BluetoothDevice mTestDevice; - private static final int TIMEOUT_MS = 1000; // 1s - - private BluetoothCodecConfig mCodecConfigSbc; - private BluetoothCodecConfig mCodecConfigAac; - private BluetoothCodecConfig mCodecConfigOpus; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock private AdapterService mAdapterService; - @Mock private ActiveDeviceManager mActiveDeviceManager; - @Mock private SilenceDeviceManager mSilenceDeviceManager; - @Mock private A2dpService mA2dpService; - @Mock private A2dpNativeInterface mA2dpNativeInterface; + @Mock private A2dpService mService; + @Mock private A2dpNativeInterface mNativeInterface; + + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 39); + private final BluetoothCodecConfig mCodecConfigSbc = + new BluetoothCodecConfig.Builder() + .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) + .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) + .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_44100) + .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_16) + .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO) + .setCodecSpecific1(0) + .setCodecSpecific2(0) + .setCodecSpecific3(0) + .setCodecSpecific4(0) + .build(); + private final BluetoothCodecConfig mCodecConfigAac = + new BluetoothCodecConfig.Builder() + .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC) + .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) + .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_48000) + .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_16) + .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO) + .setCodecSpecific1(0) + .setCodecSpecific2(0) + .setCodecSpecific3(0) + .setCodecSpecific4(0) + .build(); + private final BluetoothCodecConfig mCodecConfigOpus = + new BluetoothCodecConfig.Builder() + .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS) + .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) + .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_48000) + .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_16) + .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO) + .setCodecSpecific1(0) + .setCodecSpecific2(0) + .setCodecSpecific3(0) + .setCodecSpecific4(0) + .build(); + + private A2dpStateMachine mStateMachine; + private InOrder mInOrder; + private TestLooper mLooper; @Before public void setUp() throws Exception { - doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); - doReturn(mSilenceDeviceManager).when(mAdapterService).getSilenceDeviceManager(); - - TestUtils.setAdapterService(mAdapterService); - - mAdapter = BluetoothAdapter.getDefaultAdapter(); - - // Get a device for testing - mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); - - // Set up sample codec config - mCodecConfigSbc = - new BluetoothCodecConfig.Builder() - .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) - .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) - .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_44100) - .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_16) - .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO) - .setCodecSpecific1(0) - .setCodecSpecific2(0) - .setCodecSpecific3(0) - .setCodecSpecific4(0) - .build(); - mCodecConfigAac = - new BluetoothCodecConfig.Builder() - .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC) - .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) - .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_48000) - .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_16) - .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO) - .setCodecSpecific1(0) - .setCodecSpecific2(0) - .setCodecSpecific3(0) - .setCodecSpecific4(0) - .build(); - - mCodecConfigOpus = - new BluetoothCodecConfig.Builder() - .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS) - .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) - .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_48000) - .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_16) - .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO) - .setCodecSpecific1(0) - .setCodecSpecific2(0) - .setCodecSpecific3(0) - .setCodecSpecific4(0) - .build(); - - // Set up thread and looper - mHandlerThread = new HandlerThread("A2dpStateMachineTestHandlerThread"); - mHandlerThread.start(); - mA2dpStateMachine = - new A2dpStateMachine( - mTestDevice, - mA2dpService, - mA2dpNativeInterface, - mHandlerThread.getLooper()); - // Override the timeout value to speed up the test - A2dpStateMachine.sConnectTimeoutMs = 1000; // 1s - mA2dpStateMachine.start(); - } + doReturn(true).when(mService).okToConnect(any(), anyBoolean()); - @After - public void tearDown() throws Exception { - mA2dpStateMachine.doQuit(); - mHandlerThread.quit(); - mHandlerThread.join(TIMEOUT_MS); - TestUtils.clearAdapterService(mAdapterService); - } + doReturn(true).when(mNativeInterface).connectA2dp(any(BluetoothDevice.class)); + doReturn(true).when(mNativeInterface).disconnectA2dp(any(BluetoothDevice.class)); - /** Test that default state is disconnected */ - @Test - public void testDefaultDisconnectedState() { - assertThat(mA2dpStateMachine.getConnectionState()) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + mInOrder = inOrder(mService); + mLooper = new TestLooper(); + + mStateMachine = + new A2dpStateMachine( + mService, mDevice, mNativeInterface, false, mLooper.getLooper()); } - /** - * Allow/disallow connection to any device. - * - * @param allow if true, connection is allowed - */ - private void allowConnection(boolean allow) { - doReturn(allow).when(mA2dpService).okToConnect(any(BluetoothDevice.class), anyBoolean()); + @Test + public void initialState_isDisconnected() { + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } - /** Test that an incoming connection with low priority is rejected */ @Test - public void testIncomingPriorityReject() { - allowConnection(false); + public void incomingConnect_whenNotOkToConnect_isRejected() { + doReturn(false).when(mService).okToConnect(any(), anyBoolean()); // Inject an event for when incoming connection is requested A2dpStackEvent connStCh = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; - mA2dpStateMachine.sendMessage(A2dpStateMachine.STACK_EVENT, connStCh); - - // Verify that no connection state broadcast is executed - verify(mA2dpService, after(TIMEOUT_MS).never()) - .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); - // Check that we are in Disconnected state - assertThat(mA2dpStateMachine.getCurrentState()) + connStCh.device = mDevice; + connStCh.valueInt = STATE_CONNECTED; + sendAndDispatchMessage(MESSAGE_STACK_EVENT, connStCh); + + verify(mService, never()).sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); + assertThat(mStateMachine.getCurrentState()) .isInstanceOf(A2dpStateMachine.Disconnected.class); } - /** Test that an incoming connection with high priority is accepted */ @Test - public void testIncomingPriorityAccept() { - allowConnection(true); + public void incomingConnect_whenOkToConnect_isConnected() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()).isInstanceOf(A2dpStateMachine.Connecting.class); - // Inject an event for when incoming connection is requested - A2dpStackEvent connStCh = - new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTING; - mA2dpStateMachine.sendMessage(A2dpStateMachine.STACK_EVENT, connStCh); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mA2dpService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString(), any(Bundle.class)); - assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - - // Check that we are in Connecting state - assertThat(mA2dpStateMachine.getCurrentState()) - .isInstanceOf(A2dpStateMachine.Connecting.class); - - // Send a message to trigger connection completed - A2dpStackEvent connCompletedEvent = - new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mTestDevice; - connCompletedEvent.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; - mA2dpStateMachine.sendMessage(A2dpStateMachine.STACK_EVENT, connCompletedEvent); - - // Verify that the expected number of broadcasts are executed: - // - two calls to broadcastConnectionState(): Disconnected -> Connecting -> Connected - // - one call to broadcastAudioState() when entering Connected state - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mA2dpService, timeout(TIMEOUT_MS).times(3)) - .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); - // Verify that the last broadcast was to change the A2DP playing state - // to STATE_NOT_PLAYING - assertThat(intentArgument2.getValue().getAction()) - .isEqualTo(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED); - assertThat(intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) - .isEqualTo(BluetoothA2dp.STATE_NOT_PLAYING); - // Check that we are in Connected state - assertThat(mA2dpStateMachine.getCurrentState()) - .isInstanceOf(A2dpStateMachine.Connected.class); + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()).isInstanceOf(A2dpStateMachine.Connected.class); + + verifyIntentSent( + hasAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED), + hasExtra(EXTRA_STATE, BluetoothA2dp.STATE_NOT_PLAYING), + hasExtra(EXTRA_PREVIOUS_STATE, BluetoothA2dp.STATE_PLAYING)); } - /** Test that an outgoing connection times out */ @Test - public void testOutgoingTimeout() { - allowConnection(true); - doReturn(true).when(mA2dpNativeInterface).connectA2dp(any(BluetoothDevice.class)); - doReturn(true).when(mA2dpNativeInterface).disconnectA2dp(any(BluetoothDevice.class)); - - // Send a connect request - mA2dpStateMachine.sendMessage(A2dpStateMachine.CONNECT, mTestDevice); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mA2dpService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString(), any(Bundle.class)); - assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - - // Check that we are in Connecting state - assertThat(mA2dpStateMachine.getCurrentState()) - .isInstanceOf(A2dpStateMachine.Connecting.class); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mA2dpService, timeout(A2dpStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); - assertThat(intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); - - // Check that we are in Disconnected state - assertThat(mA2dpStateMachine.getCurrentState()) + public void outgoingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { + sendAndDispatchMessage(MESSAGE_CONNECT, mDevice); + verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()).isInstanceOf(A2dpStateMachine.Connecting.class); + + mLooper.moveTimeForward(A2dpStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) .isInstanceOf(A2dpStateMachine.Disconnected.class); } - /** Test that an incoming connection times out */ @Test - public void testIncomingTimeout() { - allowConnection(true); - doReturn(true).when(mA2dpNativeInterface).connectA2dp(any(BluetoothDevice.class)); - doReturn(true).when(mA2dpNativeInterface).disconnectA2dp(any(BluetoothDevice.class)); + public void incomingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()).isInstanceOf(A2dpStateMachine.Connecting.class); - // Inject an event for when incoming connection is requested - A2dpStackEvent connStCh = - new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTING; - mA2dpStateMachine.sendMessage(A2dpStateMachine.STACK_EVENT, connStCh); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mA2dpService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString(), any(Bundle.class)); - assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) - .isEqualTo(BluetoothProfile.STATE_CONNECTING); - - // Check that we are in Connecting state - assertThat(mA2dpStateMachine.getCurrentState()) - .isInstanceOf(A2dpStateMachine.Connecting.class); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mA2dpService, timeout(A2dpStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); - assertThat(intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); - - // Check that we are in Disconnected state - assertThat(mA2dpStateMachine.getCurrentState()) + mLooper.moveTimeForward(A2dpStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) .isInstanceOf(A2dpStateMachine.Disconnected.class); } @@ -309,21 +207,20 @@ public class A2dpStateMachineTest { */ @Test public void testProcessCodecConfigEvent_OffloadEnabled() { + // create mStateMachine with offload enabled + mStateMachine = + new A2dpStateMachine( + mService, mDevice, mNativeInterface, true, mLooper.getLooper()); + testProcessCodecConfigEventCase(true); } /** Helper methold to test processCodecConfigEvent() */ public void testProcessCodecConfigEventCase(boolean offloadEnabled) { - if (offloadEnabled) { - mA2dpStateMachine.mA2dpOffloadEnabled = true; - } - doNothing() - .when(mA2dpService) + .when(mService) .codecConfigUpdated( any(BluetoothDevice.class), any(BluetoothCodecStatus.class), anyBoolean()); - doNothing().when(mA2dpService).updateOptionalCodecsSupport(any(BluetoothDevice.class)); - allowConnection(true); BluetoothCodecConfig[] codecsSelectableSbc; codecsSelectableSbc = new BluetoothCodecConfig[1]; @@ -363,63 +260,50 @@ public class A2dpStateMachineTest { // Set default codec status when device disconnected // Selected codec = SBC, selectable codec = SBC - mA2dpStateMachine.processCodecConfigEvent(codecStatusSbcAndSbc); - verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusSbcAndSbc, false); - verify(mA2dpService).updateLowLatencyAudioSupport(mTestDevice); - - // Inject an event to change state machine to connected state - A2dpStackEvent connStCh = - new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; - mA2dpStateMachine.sendMessage(A2dpStateMachine.STACK_EVENT, connStCh); + mStateMachine.processCodecConfigEvent(codecStatusSbcAndSbc); + verify(mService).codecConfigUpdated(mDevice, codecStatusSbcAndSbc, false); + verify(mService).updateLowLatencyAudioSupport(mDevice); - // Verify that the expected number of broadcasts are executed: - // - two calls to broadcastConnectionState(): Disconnected -> Conecting -> Connected - // - one call to broadcastAudioState() when entering Connected state - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mA2dpService, timeout(TIMEOUT_MS).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_DISCONNECTED); // Verify that state machine update optional codec when enter connected state - verify(mA2dpService).updateOptionalCodecsSupport(mTestDevice); - verify(mA2dpService, times(2)).updateLowLatencyAudioSupport(mTestDevice); + verify(mService).updateOptionalCodecsSupport(mDevice); + verify(mService, times(2)).updateLowLatencyAudioSupport(mDevice); // Change codec status when device connected. // Selected codec = SBC, selectable codec = SBC+AAC - mA2dpStateMachine.processCodecConfigEvent(codecStatusSbcAndSbcAac); + mStateMachine.processCodecConfigEvent(codecStatusSbcAndSbcAac); if (!offloadEnabled) { - verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusSbcAndSbcAac, true); + verify(mService).codecConfigUpdated(mDevice, codecStatusSbcAndSbcAac, true); } - verify(mA2dpService, times(2)).updateOptionalCodecsSupport(mTestDevice); - verify(mA2dpService, times(3)).updateLowLatencyAudioSupport(mTestDevice); + verify(mService, times(2)).updateOptionalCodecsSupport(mDevice); + verify(mService, times(3)).updateLowLatencyAudioSupport(mDevice); // Update selected codec with selectable codec unchanged. // Selected codec = AAC, selectable codec = SBC+AAC - mA2dpStateMachine.processCodecConfigEvent(codecStatusAacAndSbcAac); - verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusAacAndSbcAac, false); - verify(mA2dpService, times(2)).updateOptionalCodecsSupport(mTestDevice); - verify(mA2dpService, times(4)).updateLowLatencyAudioSupport(mTestDevice); + mStateMachine.processCodecConfigEvent(codecStatusAacAndSbcAac); + verify(mService).codecConfigUpdated(mDevice, codecStatusAacAndSbcAac, false); + verify(mService, times(2)).updateOptionalCodecsSupport(mDevice); + verify(mService, times(4)).updateLowLatencyAudioSupport(mDevice); // Update selected codec // Selected codec = OPUS, selectable codec = SBC+AAC+OPUS - mA2dpStateMachine.processCodecConfigEvent(codecStatusOpusAndSbcAacOpus); + mStateMachine.processCodecConfigEvent(codecStatusOpusAndSbcAacOpus); if (!offloadEnabled) { - verify(mA2dpService) - .codecConfigUpdated(mTestDevice, codecStatusOpusAndSbcAacOpus, true); + verify(mService).codecConfigUpdated(mDevice, codecStatusOpusAndSbcAacOpus, true); } - verify(mA2dpService, times(3)).updateOptionalCodecsSupport(mTestDevice); + verify(mService, times(3)).updateOptionalCodecsSupport(mDevice); // Check if low latency audio been updated. - verify(mA2dpService, times(5)).updateLowLatencyAudioSupport(mTestDevice); + verify(mService, times(5)).updateLowLatencyAudioSupport(mDevice); // Update selected codec with selectable codec changed. // Selected codec = SBC, selectable codec = SBC+AAC - mA2dpStateMachine.processCodecConfigEvent(codecStatusSbcAndSbcAac); + mStateMachine.processCodecConfigEvent(codecStatusSbcAndSbcAac); if (!offloadEnabled) { - verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusSbcAndSbcAac, true); + verify(mService).codecConfigUpdated(mDevice, codecStatusSbcAndSbcAac, true); } // Check if low latency audio been update. - verify(mA2dpService, times(6)).updateLowLatencyAudioSupport(mTestDevice); + verify(mService, times(6)).updateLowLatencyAudioSupport(mDevice); } @Test @@ -438,8 +322,38 @@ public class A2dpStateMachineTest { mCodecConfigSbc, Arrays.asList(codecsSelectableSbcAac), Arrays.asList(codecsSelectableSbc)); - mA2dpStateMachine.processCodecConfigEvent(codecStatusSbcAndSbc); + mStateMachine.processCodecConfigEvent(codecStatusSbcAndSbc); + + mStateMachine.dump(new StringBuilder()); + } + + private void sendAndDispatchMessage(int what, Object obj) { + mStateMachine.sendMessage(what, obj); + mLooper.dispatchAll(); + } + + @SafeVarargs + private void verifyIntentSent(Matcher... matchers) { + mInOrder.verify(mService) + .sendBroadcast(MockitoHamcrest.argThat(AllOf.allOf(matchers)), any(), any()); + } + + private void verifyConnectionStateIntent(int newState, int oldState) { + verifyIntentSent( + hasAction(ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(EXTRA_STATE, newState), + hasExtra(EXTRA_PREVIOUS_STATE, oldState)); + assertThat(mStateMachine.getConnectionState()).isEqualTo(newState); + } + + private void generateConnectionMessageFromNative(int newState, int oldState) { + A2dpStackEvent event = + new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + event.device = mDevice; + event.valueInt = newState; - mA2dpStateMachine.dump(new StringBuilder()); + sendAndDispatchMessage(MESSAGE_STACK_EVENT, event); + verifyConnectionStateIntent(newState, oldState); } } diff --git a/system/include/hardware/bt_av.h b/system/include/hardware/bt_av.h index befbfb45300..df4b18c5750 100644 --- a/system/include/hardware/bt_av.h +++ b/system/include/hardware/bt_av.h @@ -26,7 +26,7 @@ __BEGIN_DECLS -/* Bluetooth AV connection states */ +// Must be kept in sync with BluetoothProfile.java typedef enum { BTAV_CONNECTION_STATE_DISCONNECTED = 0, BTAV_CONNECTION_STATE_CONNECTING, -- GitLab From 152d20e6e2b2a63f97a834bc096951ea944b62c4 Mon Sep 17 00:00:00 2001 From: Rishab Date: Fri, 25 Oct 2024 20:50:38 +0000 Subject: [PATCH 467/875] API change to support additional remote device metadata fields Test: m com.android.btservices Bug: 358631232 Change-Id: I01c66584db3850287d98356cb8f6d3b5affd88c4 --- framework/api/system-current.txt | 5 ++ .../android/bluetooth/BluetoothDevice.java | 57 ++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 7aa89155b14..ebc05424215 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -258,6 +258,10 @@ package android.bluetooth { field public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; // 0x10 field @FlaggedApi("com.android.bluetooth.flags.support_exclusive_manager") public static final int METADATA_EXCLUSIVE_MANAGER = 29; // 0x1d field public static final int METADATA_HARDWARE_VERSION = 3; // 0x3 + field @FlaggedApi("com.android.bluetooth.flags.support_remote_device_metadata") public static final int METADATA_HEAD_UNIT_BUILD = 33; // 0x21 + field @FlaggedApi("com.android.bluetooth.flags.support_remote_device_metadata") public static final int METADATA_HEAD_UNIT_MANUFACTURER_NAME = 31; // 0x1f + field @FlaggedApi("com.android.bluetooth.flags.support_remote_device_metadata") public static final int METADATA_HEAD_UNIT_MODEL_NAME = 32; // 0x20 + field @FlaggedApi("com.android.bluetooth.flags.support_remote_device_metadata") public static final int METADATA_HEAD_UNIT_SOFTWARE_VERSION = 34; // 0x22 field public static final int METADATA_IS_UNTETHERED_HEADSET = 6; // 0x6 field public static final int METADATA_LE_AUDIO = 26; // 0x1a field public static final int METADATA_MAIN_BATTERY = 18; // 0x12 @@ -267,6 +271,7 @@ package android.bluetooth { field public static final int METADATA_MANUFACTURER_NAME = 0; // 0x0 field public static final int METADATA_MAX_LENGTH = 2048; // 0x800 field public static final int METADATA_MODEL_NAME = 1; // 0x1 + field @FlaggedApi("com.android.bluetooth.flags.support_remote_device_metadata") public static final int METADATA_MODEL_YEAR = 30; // 0x1e field public static final int METADATA_SOFTWARE_VERSION = 2; // 0x2 field public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; // 0xc field public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; // 0xf diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 9bd547d33a9..0ccc9707cac 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -516,6 +516,7 @@ public final class BluetoothDevice implements Parcelable, Attributable { value = { METADATA_MANUFACTURER_NAME, METADATA_MODEL_NAME, + METADATA_MODEL_YEAR, METADATA_SOFTWARE_VERSION, METADATA_HARDWARE_VERSION, METADATA_COMPANION_APP, @@ -543,7 +544,11 @@ public final class BluetoothDevice implements Parcelable, Attributable { METADATA_LE_AUDIO, METADATA_GMCS_CCCD, METADATA_GTBS_CCCD, - METADATA_EXCLUSIVE_MANAGER + METADATA_EXCLUSIVE_MANAGER, + METADATA_HEAD_UNIT_MANUFACTURER_NAME, + METADATA_HEAD_UNIT_MODEL_NAME, + METADATA_HEAD_UNIT_BUILD, + METADATA_HEAD_UNIT_SOFTWARE_VERSION }) @Retention(RetentionPolicy.SOURCE) public @interface MetadataKey {} @@ -570,6 +575,15 @@ public final class BluetoothDevice implements Parcelable, Attributable { */ @SystemApi public static final int METADATA_MODEL_NAME = 1; + /** + * Model year of the Bluetooth device. Data type should be {@link String} as {@link Byte} array. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SUPPORT_REMOTE_DEVICE_METADATA) + @SystemApi + public static final int METADATA_MODEL_YEAR = 30; + /** * Software version of this Bluetooth device Data type should be {@link String} as {@link Byte} * array. @@ -810,6 +824,47 @@ public final class BluetoothDevice implements Parcelable, Attributable { private static final int METADATA_MAX_KEY = METADATA_EXCLUSIVE_MANAGER; + /** + * Head unit manufacturer name of the Bluetooth device. Data type should be {@link String} as + * {@link Byte} array. Should only be set/available for a car device. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SUPPORT_REMOTE_DEVICE_METADATA) + @SystemApi + public static final int METADATA_HEAD_UNIT_MANUFACTURER_NAME = 31; + + /** + * Head unit model name of the Bluetooth device. Data type should be {@link String} as {@link + * Byte} array. Should only be set/available for a car device. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SUPPORT_REMOTE_DEVICE_METADATA) + @SystemApi + public static final int METADATA_HEAD_UNIT_MODEL_NAME = 32; + + /** + * Build of the overall head unit device. Not specific to hardware or software. Example can be + * 'manufacturer_country'. Data type should be {@link String} as {@link Byte} array. Should only + * be set/available for a car device. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SUPPORT_REMOTE_DEVICE_METADATA) + @SystemApi + public static final int METADATA_HEAD_UNIT_BUILD = 33; + + /** + * Head unit software version of the Bluetooth device. Data type should be {@link String} as + * {@link Byte} array. Should only be set/available for a car device. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SUPPORT_REMOTE_DEVICE_METADATA) + @SystemApi + public static final int METADATA_HEAD_UNIT_SOFTWARE_VERSION = 34; + /** * Device type which is used in METADATA_DEVICE_TYPE Indicates this Bluetooth device is a * standard Bluetooth accessory or not listed in METADATA_DEVICE_TYPE_*. -- GitLab From 73076fd51ebbe186c31a7850d9921159a0982b53 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Mon, 28 Oct 2024 18:20:44 +0000 Subject: [PATCH 468/875] system/stack/sdp: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I1e3c65bf3ea8829fe4464bf4ed7c3df161676ddb --- system/stack/sdp/sdp_db.cc | 4 +--- system/stack/sdp/sdp_discovery.cc | 5 +---- system/stack/sdp/sdp_server.cc | 5 +---- system/stack/sdp/sdpint.h | 10 ++++------ system/stack/test/sdp/stack_sdp_utils_test.cc | 8 +------- system/test/mock/mock_stack_sdp_api.cc | 5 ++--- system/test/mock/mock_stack_sdp_db.cc | 10 ++++------ system/test/mock/mock_stack_sdp_main.cc | 7 +++---- system/test/mock/mock_stack_sdp_server.cc | 4 +--- 9 files changed, 18 insertions(+), 40 deletions(-) diff --git a/system/stack/sdp/sdp_db.cc b/system/stack/sdp/sdp_db.cc index e7bd4cf37b8..9e53a9ddf48 100644 --- a/system/stack/sdp/sdp_db.cc +++ b/system/stack/sdp/sdp_db.cc @@ -35,12 +35,10 @@ #include "stack/include/bt_types.h" #include "stack/include/bt_uuid16.h" #include "stack/include/sdpdefs.h" +#include "stack/sdp/internal/sdp_api.h" #include "stack/sdp/sdp_discovery_db.h" #include "stack/sdp/sdpint.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /******************************************************************************* diff --git a/system/stack/sdp/sdp_discovery.cc b/system/stack/sdp/sdp_discovery.cc index 01429371044..183c3e71934 100644 --- a/system/stack/sdp/sdp_discovery.cc +++ b/system/stack/sdp/sdp_discovery.cc @@ -38,9 +38,6 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::Uuid; using namespace bluetooth; @@ -252,7 +249,7 @@ static bool sdp_copy_raw_data(tCONN_CB* p_ccb, bool offset) { * Returns pointer to next byte in data stream * ******************************************************************************/ -tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db, const RawAddress& bd_addr) { +static tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db, const RawAddress& bd_addr) { tSDP_DISC_REC* p_rec; /* See if there is enough space in the database */ diff --git a/system/stack/sdp/sdp_server.cc b/system/stack/sdp/sdp_server.cc index 58a17727cfa..864280cba41 100644 --- a/system/stack/sdp/sdp_server.cc +++ b/system/stack/sdp/sdp_server.cc @@ -61,9 +61,6 @@ #define PBAP_1_2 0x0102 #define PBAP_1_2_BL_LEN 14 -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /* Used to set PBAP local SDP device record for PBAP 1.2 upgrade */ @@ -163,7 +160,7 @@ bool sdp_dynamic_change_hfp_version(const tSDP_ATTRIBUTE* p_attr, * Returns void * *****************************************************************************/ -void hfp_fallback(bool& is_hfp_fallback, const tSDP_ATTRIBUTE* p_attr) { +static void hfp_fallback(bool& is_hfp_fallback, const tSDP_ATTRIBUTE* p_attr) { /* Update HFP version back to 1.6 */ p_attr->value_ptr[PROFILE_VERSION_POSITION] = HFP_PROFILE_MINOR_VERSION_6; log::verbose("Restore HFP version to 1.6"); diff --git a/system/stack/sdp/sdpint.h b/system/stack/sdp/sdpint.h index fcbdb93abd9..e831065798c 100644 --- a/system/stack/sdp/sdpint.h +++ b/system/stack/sdp/sdpint.h @@ -292,19 +292,17 @@ bool sdpu_process_pend_ccb_new_cid(const tCONN_CB& ccb); void sdpu_clear_pend_ccb(const tCONN_CB& ccb); void sdpu_callback(const tCONN_CB& ccb, tSDP_REASON reason); -/* Functions provided by sdp_db.cc - */ +/* Functions provided by sdp_db.cc */ const tSDP_RECORD* sdp_db_service_search(const tSDP_RECORD* p_rec, const tSDP_UUID_SEQ* p_seq); tSDP_RECORD* sdp_db_find_record(uint32_t handle); const tSDP_ATTRIBUTE* sdp_db_find_attr_in_rec(const tSDP_RECORD* p_rec, uint16_t start_attr, uint16_t end_attr); -/* Functions provided by sdp_server.cc - */ +/* Functions provided by sdp_server.cc */ void sdp_server_handle_client_req(tCONN_CB* p_ccb, BT_HDR* p_msg); +bool sdp_dynamic_change_hfp_version(const tSDP_ATTRIBUTE* p_attr, const RawAddress& remote_address); -/* Functions provided by sdp_discovery.cc - */ +/* Functions provided by sdp_discovery.cc */ void sdp_disc_connected(tCONN_CB* p_ccb); void sdp_disc_server_rsp(tCONN_CB* p_ccb, BT_HDR* p_msg); diff --git a/system/stack/test/sdp/stack_sdp_utils_test.cc b/system/stack/test/sdp/stack_sdp_utils_test.cc index c089f48df7a..5a6b1fc9a1c 100644 --- a/system/stack/test/sdp/stack_sdp_utils_test.cc +++ b/system/stack/test/sdp/stack_sdp_utils_test.cc @@ -64,9 +64,6 @@ using ::testing::ReturnArg; using ::testing::SaveArg; using ::testing::SetArrayArgument; -bool sdp_dynamic_change_hfp_version(const tSDP_ATTRIBUTE* p_attr, const RawAddress& remote_address); -void hfp_fallback(bool& is_hfp_fallback, const tSDP_ATTRIBUTE* p_attr); - void sdp_callback(const RawAddress& bd_addr, tSDP_RESULT result); tCONN_CB* find_ccb(uint16_t cid, uint8_t state); @@ -577,10 +574,7 @@ TEST_F(StackSdpUtilsTest, check_HFP_version_fallback_success) { EXPECT_CALL(*localIopMock, InteropMatchAddrOrName(INTEROP_HFP_1_9_ALLOWLIST, &bdaddr, &btif_storage_get_remote_device_property)) .WillOnce(Return(true)); - bool is_hfp_fallback = sdp_dynamic_change_hfp_version(&hfp_attr, bdaddr); - ASSERT_EQ(hfp_attr.value_ptr[PROFILE_VERSION_POSITION], HFP_PROFILE_MINOR_VERSION_7); - hfp_fallback(is_hfp_fallback, &hfp_attr); - ASSERT_EQ(hfp_attr.value_ptr[PROFILE_VERSION_POSITION], HFP_PROFILE_MINOR_VERSION_6); + ASSERT_TRUE(sdp_dynamic_change_hfp_version(&hfp_attr, bdaddr)); } TEST_F(StackSdpUtilsTest, sdpu_compare_uuid_with_attr_u16) { diff --git a/system/test/mock/mock_stack_sdp_api.cc b/system/test/mock/mock_stack_sdp_api.cc index 8ae3af47624..728062397a6 100644 --- a/system/test/mock/mock_stack_sdp_api.cc +++ b/system/test/mock/mock_stack_sdp_api.cc @@ -25,6 +25,8 @@ #include +#include "stack/include/sdp_api.h" +#include "stack/sdp/internal/sdp_api.h" #include "test/common/mock_functions.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" @@ -32,9 +34,6 @@ // Mocked compile conditionals, if any // Mocked internal structures, if any -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace test { namespace mock { namespace stack_sdp_api { diff --git a/system/test/mock/mock_stack_sdp_db.cc b/system/test/mock/mock_stack_sdp_db.cc index 57c4db280d4..1d182baa5f0 100644 --- a/system/test/mock/mock_stack_sdp_db.cc +++ b/system/test/mock/mock_stack_sdp_db.cc @@ -19,12 +19,10 @@ * Functions generated:14 */ +#include "stack/sdp/internal/sdp_api.h" #include "stack/sdp/sdpint.h" #include "test/common/mock_functions.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - bool SDP_AddAdditionProtoLists(uint32_t /* handle */, uint16_t /* num_elem */, tSDP_PROTO_LIST_ELEM* /* p_proto_list */) { inc_func_call_count(__func__); @@ -69,8 +67,8 @@ bool SDP_DeleteRecord(uint32_t /* handle */) { inc_func_call_count(__func__); return false; } -tSDP_ATTRIBUTE* sdp_db_find_attr_in_rec(tSDP_RECORD* /* p_rec */, uint16_t /* start_attr */, - uint16_t /* end_attr */) { +const tSDP_ATTRIBUTE* sdp_db_find_attr_in_rec(const tSDP_RECORD* /* p_rec */, + uint16_t /* start_attr */, uint16_t /* end_attr */) { inc_func_call_count(__func__); return nullptr; } @@ -79,7 +77,7 @@ tSDP_RECORD* sdp_db_find_record(uint32_t /* handle */) { return nullptr; } const tSDP_RECORD* sdp_db_service_search(const tSDP_RECORD* /* p_rec */, - tSDP_UUID_SEQ* /* p_seq */) { + const tSDP_UUID_SEQ* /* p_seq */) { inc_func_call_count(__func__); return nullptr; } diff --git a/system/test/mock/mock_stack_sdp_main.cc b/system/test/mock/mock_stack_sdp_main.cc index 751daba254f..1a2303712da 100644 --- a/system/test/mock/mock_stack_sdp_main.cc +++ b/system/test/mock/mock_stack_sdp_main.cc @@ -23,14 +23,13 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - tCONN_CB* sdp_conn_originate(const RawAddress& /* p_bd_addr */) { inc_func_call_count(__func__); return nullptr; } void sdp_conn_timer_timeout(void* /* data */) { inc_func_call_count(__func__); } -void sdp_disconnect(tCONN_CB* /* p_ccb */, uint16_t /* reason */) { inc_func_call_count(__func__); } +void sdp_disconnect(tCONN_CB* /* p_ccb */, tSDP_REASON /* reason */) { + inc_func_call_count(__func__); +} void sdp_free(void) { inc_func_call_count(__func__); } void sdp_init(void) { inc_func_call_count(__func__); } diff --git a/system/test/mock/mock_stack_sdp_server.cc b/system/test/mock/mock_stack_sdp_server.cc index 6802bc4d6ef..b20e5da05bc 100644 --- a/system/test/mock/mock_stack_sdp_server.cc +++ b/system/test/mock/mock_stack_sdp_server.cc @@ -14,12 +14,10 @@ * limitations under the License. */ +#include "stack/sdp/sdpint.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - void update_pce_entry_to_interop_database(RawAddress /* remote_addr */) { inc_func_call_count(__func__); } -- GitLab From 8426c3937ef18a32d0fb2597146d9bc09ffd0a48 Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Mon, 28 Oct 2024 06:39:29 +0000 Subject: [PATCH 469/875] Add missing reset for expected address rotation time When unregistering the last client, the expected address rotation time were not reset. This generated a warning log (false alarm) when starting a new scanning after unregistering all clients. This CL only affects variables for logging purposes. Bug: 344712454 Flag: EXEMPT, only affects logging Test: m -j; Test: Unregister scan client and start a new scan. The warning log is not printed. Change-Id: I78f9154fdffd2e34de19cd55d1fef113bd3eac17 --- system/gd/hci/le_address_manager.cc | 6 ++++++ system/gd/hci/le_advertising_manager.cc | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/system/gd/hci/le_address_manager.cc b/system/gd/hci/le_address_manager.cc index 322b8d8220d..e72b9c03ff7 100644 --- a/system/gd/hci/le_address_manager.cc +++ b/system/gd/hci/le_address_manager.cc @@ -265,6 +265,12 @@ void LeAddressManager::unregister_client(LeAddressManagerCallback* callback) { if (address_rotation_non_wake_alarm_ != nullptr) { address_rotation_non_wake_alarm_->Cancel(); } + if (address_rotation_interval_min.has_value()) { + address_rotation_interval_min.reset(); + } + if (address_rotation_interval_max.has_value()) { + address_rotation_interval_max.reset(); + } log::info("Cancelled address rotation alarm"); } } diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc index 9abe04f83cd..dd3b4a001ea 100644 --- a/system/gd/hci/le_advertising_manager.cc +++ b/system/gd/hci/le_advertising_manager.cc @@ -435,6 +435,12 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Cancel(); advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_.reset(); } + if (advertising_sets_[advertiser_id].address_rotation_interval_min.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_min.reset(); + } + if (advertising_sets_[advertiser_id].address_rotation_interval_max.has_value()) { + advertising_sets_[advertiser_id].address_rotation_interval_max.reset(); + } } advertising_sets_.erase(advertiser_id); if (advertising_sets_.empty() && address_manager_registered) { -- GitLab From bdb4351b7308143f7d7a47bebfa2953ada3b1f8b Mon Sep 17 00:00:00 2001 From: Kokoa Matsuda Date: Tue, 29 Oct 2024 17:55:36 +0900 Subject: [PATCH 470/875] Replace libchrome HexStringToInt with android-base's one This change is to remove the direct dependency on libchrome. This change is very mechanical, no change in program behavior. Test: m . Bug: 360917504 Change-Id: I08079869e89af0bbb3e496ec2df9ec81c610ade4 --- system/gd/metrics/chromeos/metrics_event.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/gd/metrics/chromeos/metrics_event.cc b/system/gd/metrics/chromeos/metrics_event.cc index a8c8c46b3fe..806db26bfe6 100644 --- a/system/gd/metrics/chromeos/metrics_event.cc +++ b/system/gd/metrics/chromeos/metrics_event.cc @@ -15,6 +15,7 @@ */ #include "metrics/chromeos/metrics_event.h" +#include #include #include #include @@ -665,7 +666,7 @@ static int64_t GetChipsetInfoId(const char* path, const char* file) { int64_t id; if (base::ReadFileToString(base::FilePath(path).Append(file), &content)) { - if (base::HexStringToInt64(base::CollapseWhitespaceASCII(content, false), &id)) { + if (android::base::ParseInt(base::CollapseWhitespaceASCII(content, false), &id)) { return id; } } -- GitLab From 29b039b990eea9605d1c7c59ba2a1dd272bb6632 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Mon, 28 Oct 2024 20:30:23 +0800 Subject: [PATCH 471/875] Floss: Support multiple volume callbacks Currently we assume there is only one volume callback and we always replace the callback if a new audio device is connected. When two audio devices are connected simultaneously, the later device is disconnected because we can only stream audio to one device. However, the volume callback is tied to that device, so now if the user changes the volume, we can't call the correct callback. This CL stores callback to all connected devices, so we can get the correct callback when user updates the system volume. Also, to simplify things, whenever floss layer receives an AVRCP connection when there is an existing connection, we ask libbluetooth to drop the newer connection. This behavior can be updated later, e.g. when the old connection is disconnected we can smartly switch to the new connection. Bug: 366387141 Test: m -j Test: Pair two headsets that connects AVRCP when they reconnects. Connect each headset one by one. Verify the 2nd device is disconnected, and the 1st device still receive volume updates. Flag: EXEMPT, floss only change Change-Id: I2e0f707fd11a3a6dbf827d839f95ec57f47e98d9 --- .../rust/linux/stack/src/bluetooth_media.rs | 94 +++++++++++-------- system/gd/rust/topshim/btav/btav_shim.cc | 20 ++-- system/gd/rust/topshim/btav/btav_shim.h | 2 +- system/gd/rust/topshim/src/profiles/avrcp.rs | 6 +- 4 files changed, 72 insertions(+), 50 deletions(-) diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs index 4e6f6d28113..1479df3684b 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_media.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs @@ -1,8 +1,8 @@ //! Anything related to audio and media API. use bt_topshim::btif::{ - BluetoothInterface, BtBondState, BtConnectionDirection, BtStatus, BtTransport, DisplayAddress, - RawAddress, ToggleableProfile, + BluetoothInterface, BtBondState, BtStatus, BtTransport, DisplayAddress, RawAddress, + ToggleableProfile, }; use bt_topshim::profiles::a2dp::{ A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode, @@ -472,7 +472,8 @@ pub struct BluetoothMedia { adapter: Arc>>, a2dp: A2dp, avrcp: Avrcp, - avrcp_direction: BtConnectionDirection, + avrcp_address: Option, + avrcp_states: HashMap, a2dp_states: HashMap, a2dp_audio_state: HashMap, a2dp_has_interrupted_stream: bool, // Only used for qualification. @@ -548,7 +549,8 @@ impl BluetoothMedia { adapter, a2dp, avrcp, - avrcp_direction: BtConnectionDirection::Unknown, + avrcp_address: None, + avrcp_states: HashMap::new(), a2dp_states: HashMap::new(), a2dp_audio_state: HashMap::new(), a2dp_has_interrupted_stream: false, @@ -1307,6 +1309,31 @@ impl BluetoothMedia { supported ); + // If is device initiated the AVRCP connection, emit a fake connecting state as + // stack don't receive one. + if self.avrcp_states.get(&addr) != Some(&BtavConnectionState::Connecting) { + metrics::profile_connection_state_changed( + addr, + Profile::AvrcpController as u32, + BtStatus::Success, + BtavConnectionState::Connecting as u32, + ); + } + metrics::profile_connection_state_changed( + addr, + Profile::AvrcpController as u32, + BtStatus::Success, + BtavConnectionState::Connected as u32, + ); + self.avrcp_states.insert(addr, BtavConnectionState::Connected); + + if self.avrcp_address.is_some() { + warn!("Another AVRCP connection exists. Disconnect {}", DisplayAddress(&addr)); + self.avrcp.disconnect(addr); + return; + } + self.avrcp_address = Some(addr); + match self.uinput.create(self.adapter_get_remote_name(addr), addr.to_string()) { Ok(()) => info!("uinput device created for: {}", DisplayAddress(&addr)), Err(e) => warn!("{}", e), @@ -1325,30 +1352,34 @@ impl BluetoothMedia { } self.absolute_volume = supported; + self.add_connected_profile(addr, Profile::AvrcpController); + } + AvrcpCallbacks::AvrcpDeviceDisconnected(addr) => { + info!("[{}]: avrcp disconnected.", DisplayAddress(&addr)); - // If is device initiated the AVRCP connection, emit a fake connecting state as - // stack don't receive one. - if self.avrcp_direction != BtConnectionDirection::Outgoing { + // If the peer device initiated the AVRCP disconnection, emit a fake connecting + // state as stack don't receive one. + if self.avrcp_states.get(&addr) != Some(&BtavConnectionState::Disconnecting) { metrics::profile_connection_state_changed( addr, Profile::AvrcpController as u32, BtStatus::Success, - BtavConnectionState::Connecting as u32, + BtavConnectionState::Disconnecting as u32, ); } metrics::profile_connection_state_changed( addr, Profile::AvrcpController as u32, BtStatus::Success, - BtavConnectionState::Connected as u32, + BtavConnectionState::Disconnected as u32, ); - // Reset direction to unknown. - self.avrcp_direction = BtConnectionDirection::Unknown; + self.avrcp_states.remove(&addr); - self.add_connected_profile(addr, Profile::AvrcpController); - } - AvrcpCallbacks::AvrcpDeviceDisconnected(addr) => { - info!("[{}]: avrcp disconnected.", DisplayAddress(&addr)); + if self.avrcp_address != Some(addr) { + // Ignore disconnection to address we don't care + return; + } + self.avrcp_address = None; self.uinput.close(addr.to_string()); @@ -1362,25 +1393,6 @@ impl BluetoothMedia { None => false, }; - // If the peer device initiated the AVRCP disconnection, emit a fake connecting - // state as stack don't receive one. - if self.avrcp_direction != BtConnectionDirection::Outgoing { - metrics::profile_connection_state_changed( - addr, - Profile::AvrcpController as u32, - BtStatus::Success, - BtavConnectionState::Disconnecting as u32, - ); - } - metrics::profile_connection_state_changed( - addr, - Profile::AvrcpController as u32, - BtStatus::Success, - BtavConnectionState::Disconnected as u32, - ); - // Reset direction to unknown. - self.avrcp_direction = BtConnectionDirection::Unknown; - self.rm_connected_profile(addr, Profile::AvrcpController, is_profile_critical); } AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => { @@ -3336,11 +3348,11 @@ impl IBluetoothMedia for BluetoothMedia { BtStatus::Success, BtavConnectionState::Connecting as u32, ); - self.avrcp_direction = BtConnectionDirection::Outgoing; + self.avrcp_states.insert(addr, BtavConnectionState::Connecting); let status = self.avrcp.connect(addr); if BtStatus::Success != status { // Reset direction to unknown. - self.avrcp_direction = BtConnectionDirection::Unknown; + self.avrcp_states.remove(&addr); metrics::profile_connection_state_changed( addr, Profile::AvrcpController as u32, @@ -3463,11 +3475,11 @@ impl IBluetoothMedia for BluetoothMedia { BtStatus::Success, BtavConnectionState::Disconnecting as u32, ); - self.avrcp_direction = BtConnectionDirection::Outgoing; + self.avrcp_states.insert(addr, BtavConnectionState::Disconnecting); let status = self.avrcp.disconnect(addr); if BtStatus::Success != status { // Reset direction to unknown. - self.avrcp_direction = BtConnectionDirection::Unknown; + self.avrcp_states.remove(&addr); metrics::profile_connection_state_changed( addr, Profile::AvrcpController as u32, @@ -3569,6 +3581,10 @@ impl IBluetoothMedia for BluetoothMedia { } fn set_volume(&mut self, volume: u8) { + if self.avrcp_address.is_none() { + return; + } + // Guard the range 0-127 by the try_from cast from u8 to i8. let vol = match i8::try_from(volume) { Ok(val) => val, @@ -3578,7 +3594,7 @@ impl IBluetoothMedia for BluetoothMedia { } }; - self.avrcp.set_volume(vol); + self.avrcp.set_volume(self.avrcp_address.unwrap(), vol); } fn set_hfp_volume(&mut self, volume: u8, addr: RawAddress) { diff --git a/system/gd/rust/topshim/btav/btav_shim.cc b/system/gd/rust/topshim/btav/btav_shim.cc index ed4f6fe3b08..316d16fd58b 100644 --- a/system/gd/rust/topshim/btav/btav_shim.cc +++ b/system/gd/rust/topshim/btav/btav_shim.cc @@ -17,6 +17,7 @@ #include "rust/topshim/btav/btav_shim.h" #include +#include #include #include "base/functional/callback.h" @@ -155,12 +156,12 @@ public: } void DeviceConnected(const RawAddress& addr, VolumeChangedCb cb) override { - volumeCb = std::move(cb); + volumeCbs[addr] = std::move(cb); rusty::avrcp_device_connected(addr, /*absolute_volume_enabled=*/true); } void DeviceDisconnected(const RawAddress& addr) override { - volumeCb.Reset(); + volumeCbs.erase(addr); rusty::avrcp_device_disconnected(addr); } @@ -174,16 +175,19 @@ public: } // Set CT's (headsets, speakers) volume. - void SetDeviceVolume(int8_t volume) { - if (!volumeCb || volume < 0) { + void SetDeviceVolume(const RawAddress& addr, int8_t volume) { + if (volume < 0) { return; } - volumeCb.Run(volume); + const auto& cb_iter = this->volumeCbs.find(addr); + if (cb_iter != this->volumeCbs.end()) { + cb_iter->second.Run(volume); + } } private: - VolumeInterface::VolumeChangedCb volumeCb; + std::map volumeCbs; }; } // namespace bluetooth::avrcp @@ -361,7 +365,9 @@ void AvrcpIntf::cleanup() { intf_->Cleanup(); } uint32_t AvrcpIntf::connect(RawAddress addr) { return intf_->ConnectDevice(addr); } uint32_t AvrcpIntf::disconnect(RawAddress addr) { return intf_->DisconnectDevice(addr); } -void AvrcpIntf::set_volume(int8_t volume) { return mVolumeInterface.SetDeviceVolume(volume); } +void AvrcpIntf::set_volume(RawAddress addr, int8_t volume) { + return mVolumeInterface.SetDeviceVolume(addr, volume); +} void AvrcpIntf::set_playback_status(const ::rust::String& status) { avrcp::PlayState state = avrcp::PlayState::STOPPED; diff --git a/system/gd/rust/topshim/btav/btav_shim.h b/system/gd/rust/topshim/btav/btav_shim.h index 6482bca94f9..f32fb241c3b 100644 --- a/system/gd/rust/topshim/btav/btav_shim.h +++ b/system/gd/rust/topshim/btav/btav_shim.h @@ -67,7 +67,7 @@ public: uint32_t disconnect(RawAddress addr); // interface for Audio server - void set_volume(int8_t volume); + void set_volume(RawAddress addr, int8_t volume); void set_playback_status(const ::rust::String& status); void set_position(int64_t position_us); diff --git a/system/gd/rust/topshim/src/profiles/avrcp.rs b/system/gd/rust/topshim/src/profiles/avrcp.rs index 16039a1a268..1b63ef537ac 100644 --- a/system/gd/rust/topshim/src/profiles/avrcp.rs +++ b/system/gd/rust/topshim/src/profiles/avrcp.rs @@ -38,7 +38,7 @@ pub mod ffi { fn cleanup(self: Pin<&mut AvrcpIntf>); fn connect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u32; fn disconnect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u32; - fn set_volume(self: Pin<&mut AvrcpIntf>, volume: i8); + fn set_volume(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress, volume: i8); fn set_playback_status(self: Pin<&mut AvrcpIntf>, status: &String); fn set_position(self: Pin<&mut AvrcpIntf>, position_us: i64); fn set_metadata( @@ -173,8 +173,8 @@ impl Avrcp { } #[profile_enabled_or] - pub fn set_volume(&mut self, volume: i8) { - self.internal.pin_mut().set_volume(volume); + pub fn set_volume(&mut self, addr: RawAddress, volume: i8) { + self.internal.pin_mut().set_volume(addr, volume); } #[profile_enabled_or(false)] -- GitLab From 615fdc1277e7be0d66664c72839a86e4e103152d Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 26 Sep 2024 12:50:16 +0000 Subject: [PATCH 472/875] LeAudio: Improve the debug state dumps and logs - reduce the number of system calls (dprintf) on dumpsys when accessing file descriptor - make the state dumping functions available in regular debug printing without the need for file descriptors (usable for state printing during debbugging) - rearrange and cleanup the LE Audio dumpsys output - improve some regular logs for readability (incl. mono location) - indicate codec extensibility status (enabled/disabled) Bug: 374933885 Test: m -j Flag: Exempt; No functional changes Change-Id: I5ba5b54f175df374cc5fdd26e543e75e42ed0844 --- system/bta/gmap/gmap_client.cc | 6 +- system/bta/le_audio/client.cc | 105 +++++++++++++++----------- system/bta/le_audio/device_groups.cc | 79 +++++++++---------- system/bta/le_audio/device_groups.h | 4 +- system/bta/le_audio/devices.cc | 93 +++++++++++------------ system/bta/le_audio/devices.h | 4 +- system/bta/le_audio/gmap_client.h | 3 +- system/bta/le_audio/le_audio_types.cc | 17 +++-- system/bta/le_audio/state_machine.cc | 4 +- 9 files changed, 165 insertions(+), 150 deletions(-) diff --git a/system/bta/gmap/gmap_client.cc b/system/bta/gmap/gmap_client.cc index 917070e2ac9..a27602d1f12 100644 --- a/system/bta/gmap/gmap_client.cc +++ b/system/bta/gmap/gmap_client.cc @@ -51,15 +51,13 @@ void GmapClient::AddFromStorage(const RawAddress &addr, const uint8_t role, UGT_feature_handle_ = UGT_feature_handle; } -void GmapClient::DebugDump(int fd) { - std::stringstream stream; +void GmapClient::DebugDump(std::stringstream &stream) { if (!IsGmapClientEnabled()) { - dprintf(fd, "%s", "GmapClient not enabled"); + stream << "GmapClient not enabled\n"; return; } stream << "GmapClient device: " << addr_ << ", Role: " << role_ << ", "; stream << "UGT Feature: " << UGT_feature_ << "\n"; - dprintf(fd, "%s", stream.str().c_str()); } bool GmapClient::IsGmapClientEnabled() { diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 01c2856e99f..5ac9402c312 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -352,6 +352,7 @@ public: close_vbc_timeout_, timeoutMs, [](void*) { if (instance) { + log::debug("Reconfigure after VBC close"); instance->ReconfigureAfterVbcClose(); } }, @@ -382,7 +383,9 @@ public: suspend_timeout_, timeoutMs, [](void* data) { if (instance) { - instance->GroupStop(PTR_TO_INT(data)); + auto const group_id = PTR_TO_INT(data); + log::debug("No resume request received. Stop the group ID: {}", group_id); + instance->GroupStop(group_id); } }, INT_TO_PTR(active_group_id_)); @@ -3298,7 +3301,7 @@ public: } void scheduleAttachDeviceToTheStream(const RawAddress& addr) { - log::info("Device {} scheduler for stream", addr); + log::info("Device {} is scheduled for streaming", addr); do_in_main_thread_delayed(base::BindOnce(&LeAudioClientImpl::restartAttachToTheStream, weak_factory_.GetWeakPtr(), addr), std::chrono::milliseconds(kDeviceAttachDelayMs)); @@ -3883,64 +3886,79 @@ public: stack::l2cap::get_interface().L2CA_SetEcosystemBaseInterval(0 /* clear recommendation */); } - void printCurrentStreamConfiguration(int fd) { - std::stringstream stream; + void printCurrentStreamConfiguration(std::stringstream& stream) { auto config_printer = [&stream](LeAudioCodecConfiguration& conf) { - stream << "\tsample rate: " << +conf.sample_rate << ",\tchan: " << +conf.num_channels - << ",\tbits: " << +conf.bits_per_sample - << ",\tdata_interval_us: " << +conf.data_interval_us << "\n"; + stream << "\tsample rate: " << +conf.sample_rate << ", chan: " << +conf.num_channels + << ", bits: " << +conf.bits_per_sample + << ", data_interval_us: " << +conf.data_interval_us << "\n"; }; - stream << " Speaker codec config (audio framework) \n"; + stream << "\n"; + stream << " Speaker codec config (audio framework):\n"; stream << "\taudio sender state: " << audio_sender_state_ << "\n"; config_printer(audio_framework_source_config); - stream << " Microphone codec config (audio framework) \n"; + stream << " Microphone codec config (audio framework):\n"; stream << "\taudio receiver state: " << audio_receiver_state_ << "\n"; config_printer(audio_framework_sink_config); - stream << " Speaker codec config (SW encoder)\n"; + stream << " Speaker codec config (SW encoder):\n"; config_printer(current_encoder_config_); - stream << " Microphone codec config (SW decoder)\n"; + stream << " Microphone codec config (SW decoder):\n"; config_printer(current_decoder_config_); - - dprintf(fd, "%s", stream.str().c_str()); } void Dump(int fd) { - dprintf(fd, " APP ID: %d \n", gatt_if_); - dprintf(fd, " Active group: %d\n", active_group_id_); - dprintf(fd, " reconnection mode: %s \n", - (reconnection_mode_ == BTM_BLE_BKG_CONNECT_ALLOW_LIST ? "Allow List" - : "Targeted Announcements")); - dprintf(fd, " configuration: %s (0x%08x)\n", - bluetooth::common::ToString(configuration_context_type_).c_str(), - static_cast(configuration_context_type_)); - dprintf(fd, " local source metadata context type mask: %s\n", - local_metadata_context_types_.source.to_string().c_str()); - dprintf(fd, " local sink metadata context type mask: %s\n", - local_metadata_context_types_.sink.to_string().c_str()); - dprintf(fd, " TBS state: %s\n", in_call_ ? " In call" : "No calls"); - dprintf(fd, " Sink listening mode: %s\n", sink_monitor_mode_ ? "true" : "false"); + std::stringstream stream; + + stream << " APP ID: " << +gatt_if_ << "\n"; + stream << " TBS state: " << (in_call_ ? " In call" : "No calls") << "\n"; + stream << " Active group: " << +active_group_id_ << "\n"; + stream << " Reconnection mode: " + << (reconnection_mode_ == BTM_BLE_BKG_CONNECT_ALLOW_LIST ? "Allow List" + : "Targeted Announcements") + << "\n"; + stream << " Configuration: " << bluetooth::common::ToString(configuration_context_type_) + << " (" << loghex(static_cast(configuration_context_type_)) << ")\n"; + stream << " Local source metadata context type mask: " + << local_metadata_context_types_.source.to_string() << "\n"; + stream << " Local sink metadata context type mask: " + << local_metadata_context_types_.sink.to_string() << "\n"; + stream << " Sink listening mode: " << (sink_monitor_mode_ ? "true" : "false") << "\n"; if (sink_monitor_notified_status_) { - dprintf(fd, " Local sink notified state: %d\n", - static_cast(sink_monitor_notified_status_.value())); + stream << " Local sink notified state: " + << static_cast(sink_monitor_notified_status_.value()) << "\n"; + } + stream << " Source monitor mode: " << (source_monitor_mode_ ? "true" : "false") << "\n"; + + auto codec_loc = CodecManager::GetInstance()->GetCodecLocation(); + if (codec_loc == bluetooth::le_audio::types::CodecLocation::HOST) { + stream << " Codec location: HOST\n"; + } else if (codec_loc == bluetooth::le_audio::types::CodecLocation::CONTROLLER) { + stream << " Codec location: CONTROLLER\n"; + } else if (codec_loc == bluetooth::le_audio::types::CodecLocation::ADSP) { + stream << " Codec location: ADSP" + << (CodecManager::GetInstance()->IsUsingCodecExtensibility() ? " (codec extensibility)" + : "") + << "\n"; + } else { + dprintf(fd, " Codec location: UNKNOWN\n"); } - dprintf(fd, " Source monitor mode: %s\n", source_monitor_mode_ ? "true" : "false"); - dprintf(fd, " Codec extensibility: %s\n", - CodecManager::GetInstance()->IsUsingCodecExtensibility() ? "true" : "false"); - dprintf(fd, " Start time: "); + + stream << " Start time: "; for (auto t : stream_start_history_queue_) { - dprintf(fd, ", %d ms", static_cast(t)); + stream << static_cast(t) << " ms, "; } - dprintf(fd, "\n"); - printCurrentStreamConfiguration(fd); - dprintf(fd, " ----------------\n "); - dprintf(fd, " LE Audio Groups:\n"); - aseGroups_.Dump(fd, active_group_id_); - dprintf(fd, "\n Not grouped devices:\n"); - leAudioDevices_.Dump(fd, bluetooth::groups::kGroupUnknown); + stream << "\n"; + printCurrentStreamConfiguration(stream); + stream << "\n"; + aseGroups_.Dump(stream, active_group_id_); + stream << "\n "; + stream << " Not grouped devices:\n"; + leAudioDevices_.Dump(stream, bluetooth::groups::kGroupUnknown); + + dprintf(fd, "%s", stream.str().c_str()); if (leAudioHealthStatus_) { leAudioHealthStatus_->DebugDump(fd); @@ -4057,7 +4075,9 @@ public: disable_timer_, kAudioDisableTimeoutMs, [](void* data) { if (instance) { - instance->GroupSuspend(PTR_TO_INT(data)); + auto const group_id = PTR_TO_INT(data); + log::debug("No resume request received. Suspend the group ID: {}", group_id); + instance->GroupSuspend(group_id); } }, INT_TO_PTR(active_group_id_)); @@ -4612,6 +4632,7 @@ public: } StopSuspendTimeout(); + /* If group suspend is scheduled, cancel as we are stopping it anyway */ /* Need to reconfigure stream. At this point pre_configuration_context_type shall be set */ diff --git a/system/bta/le_audio/device_groups.cc b/system/bta/le_audio/device_groups.cc index 2eda1feee23..4770e412ff4 100644 --- a/system/bta/le_audio/device_groups.cc +++ b/system/bta/le_audio/device_groups.cc @@ -2101,7 +2101,7 @@ void LeAudioDeviceGroup::PrintDebugState(void) const { << bluetooth::common::ToString(GetSupportedContexts()) << ", \n group available contexts: " << bluetooth::common::ToString(GetAvailableContexts()) - << ", \n group allowed contexts: " + << ", \n group user allowed contexts: " << bluetooth::common::ToString(GetAllowedContextMask()) << ", \n configuration context type: " << bluetooth::common::ToString(GetConfigurationContextType()) @@ -2142,42 +2142,29 @@ void LeAudioDeviceGroup::PrintDebugState(void) const { } } -void LeAudioDeviceGroup::Dump(int fd, int active_group_id) const { +void LeAudioDeviceGroup::Dump(std::stringstream& stream, int active_group_id) const { bool is_active = (group_id_ == active_group_id); - std::stringstream stream, stream_pacs; auto active_conf = GetActiveConfiguration(); - stream << "\n == Group id: " << group_id_ << (is_enabled_ ? " enabled" : " disabled") - << " == " << (is_active ? ",\tActive\n" : ",\tInactive\n") << " state: " << GetState() + stream << " ■ Group id: " << group_id_ << ", " << (is_enabled_ ? "Enabled" : "Disabled") + << ", " << (is_active ? "Active\n" : "Inactive\n") << " Current state: " << GetState() << ",\ttarget state: " << GetTargetState() << ",\tcig state: " << cig.GetState() << "\n" - << " group supported contexts: " << GetSupportedContexts() << "\n" - << " group available contexts: " << GetAvailableContexts() << "\n" - << " group allowed contexts: " << GetAllowedContextMask() << "\n" - << " configuration context type: " + << " Group supported contexts: " << GetSupportedContexts() << "\n" + << " Group available contexts: " << GetAvailableContexts() << "\n" + << " Group user allowed contexts: " << GetAllowedContextMask() << "\n" + << " Configuration context type: " << bluetooth::common::ToString(GetConfigurationContextType()).c_str() << "\n" - << " active configuration name: " << (active_conf ? active_conf->name : " not set") + << " Active configuration name:\t" << (active_conf ? active_conf->name : "Not set") << "\n" - << " stream configuration: " - << (stream_conf.conf != nullptr ? stream_conf.conf->name : " unknown ") << "\n" - << " codec id: " << +(stream_conf.codec_id.coding_format) - << ",\tpending_configuration: " << stream_conf.pending_configuration << "\n" - << " num of devices(connected): " << Size() << "(" << NumOfConnected() << ")\n" - << ", num of sinks(connected): " << stream_conf.stream_params.sink.num_of_devices - << "(" << stream_conf.stream_params.sink.stream_locations.size() << ")\n" - << " num of sources(connected): " << stream_conf.stream_params.source.num_of_devices - << "(" << stream_conf.stream_params.source.stream_locations.size() << ")\n" - << " allocated CISes: " << static_cast(cig.cises.size()); - - if (cig.cises.size() > 0) { - stream << "\n\t == CISes == "; - for (auto cis : cig.cises) { - stream << "\n\t cis id: " << static_cast(cis.id) - << ",\ttype: " << static_cast(cis.type) - << ",\tconn_handle: " << static_cast(cis.conn_handle) - << ",\taddr: " << ADDRESS_TO_LOGGABLE_STR(cis.addr); - } - stream << "\n\t ===="; - } + << " Stream configuration:\t\t" + << (stream_conf.conf != nullptr ? stream_conf.conf->name : "Not set ") << "\n" + << " Codec ID: " << +(stream_conf.codec_id.coding_format) + << ",\tpending reconfiguration: " << stream_conf.pending_configuration << "\n" + << " Num of devices:\t" << Size() << " (" << NumOfConnected() << " connected)\n" + << " Num of sinks:\t" << stream_conf.stream_params.sink.num_of_devices << " (" + << stream_conf.stream_params.sink.stream_locations.size() << " connected)\n" + << " Num of sources:\t" << stream_conf.stream_params.source.num_of_devices << " (" + << stream_conf.stream_params.source.stream_locations.size() << " connected)"; if (GetFirstActiveDevice() != nullptr) { uint32_t sink_delay; @@ -2190,21 +2177,27 @@ void LeAudioDeviceGroup::Dump(int fd, int active_group_id) const { stream << "\n presentation_delay for source (microphone): " << source_delay << " us"; } } + stream << "\n"; - stream << "\n == devices: =="; - - dprintf(fd, "%s", stream.str().c_str()); + stream << " == CISes (" << static_cast(cig.cises.size()) << "):"; + if (cig.cises.size() > 0) { + for (auto cis : cig.cises) { + stream << "\n\t cis id: " << static_cast(cis.id) + << ",\ttype: " << static_cast(cis.type) + << ",\tconn_handle: " << static_cast(cis.conn_handle) + << ",\taddr: " << ADDRESS_TO_LOGGABLE_STR(cis.addr); + } + } + stream << "\n"; for (const auto& device_iter : leAudioDevices_) { - device_iter.lock()->Dump(fd); + device_iter.lock()->Dump(stream); } for (const auto& device_iter : leAudioDevices_) { - auto device = device_iter.lock(); - stream_pacs << "\n\taddress: " << device->address_; - device->DumpPacsDebugState(stream_pacs); + device_iter.lock()->DumpPacsDebugState(stream); } - dprintf(fd, "%s", stream_pacs.str().c_str()); + stream << "\n"; } LeAudioDeviceGroup* LeAudioDeviceGroups::Add(int group_id) { @@ -2244,19 +2237,21 @@ void LeAudioDeviceGroups::Cleanup(void) { groups_.clear(); } -void LeAudioDeviceGroups::Dump(int fd, int active_group_id) const { +void LeAudioDeviceGroups::Dump(std::stringstream& stream, int active_group_id) const { /* Dump first active group */ + stream << " == Active Groups:\n"; for (auto& g : groups_) { if (g->group_id_ == active_group_id) { - g->Dump(fd, active_group_id); + g->Dump(stream, active_group_id); break; } } /* Dump non active group */ + stream << " == Inactive Groups:\n"; for (auto& g : groups_) { if (g->group_id_ != active_group_id) { - g->Dump(fd, active_group_id); + g->Dump(stream, active_group_id); } } } diff --git a/system/bta/le_audio/device_groups.h b/system/bta/le_audio/device_groups.h index 74deb176945..ba11270aca3 100644 --- a/system/bta/le_audio/device_groups.h +++ b/system/bta/le_audio/device_groups.h @@ -407,7 +407,7 @@ public: bool IsReleasingOrIdle(void) const; void PrintDebugState(void) const; - void Dump(int fd, int active_group_id) const; + void Dump(std::stringstream& stream, int active_group_id) const; /* Codec configuration matcher supporting the legacy configuration provider * mechanism for the non-vendor and software codecs. Only if the codec @@ -499,7 +499,7 @@ public: size_t Size() const; bool IsAnyInTransition() const; void Cleanup(void); - void Dump(int fd, int active_group_id) const; + void Dump(std::stringstream& stream, int active_group_id) const; private: std::vector> groups_; diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc index c48518530e0..87fdd19a05a 100644 --- a/system/bta/le_audio/devices.cc +++ b/system/bta/le_audio/devices.cc @@ -922,14 +922,14 @@ uint8_t LeAudioDevice::GetPhyBitmask(void) const { void LeAudioDevice::PrintDebugState(void) { std::stringstream debug_str; - debug_str << " address: " << address_ << ", " << bluetooth::common::ToString(connection_state_) + debug_str << " Address: " << address_ << ", " << bluetooth::common::ToString(connection_state_) << ", conn_id: " << +conn_id_ << ", mtu: " << +mtu_ << ", num_of_ase: " << static_cast(ases_.size()); if (ases_.size() > 0) { debug_str << "\n == ASEs == "; for (auto& ase : ases_) { - debug_str << "\n id: " << +ase.id << ", active: " << ase.active + debug_str << " id: " << +ase.id << ", active: " << ase.active << ", dir: " << (ase.direction == types::kLeAudioDirectionSink ? "sink" : "source") << ", state: " << bluetooth::common::ToString(ase.state) << ", cis_id: " << +ase.cis_id << ", cis_handle: " << +ase.cis_conn_hdl @@ -942,7 +942,7 @@ void LeAudioDevice::PrintDebugState(void) { << ", presentation_delay: " << +ase.qos_config.presentation_delay << ", framing: " << +ase.qos_config.framing << ", phy: " << +ase.qos_config.phy << ", target latency: " << +ase.target_latency - << ", reconfigure: " << ase.reconfigure << "\n"; + << ", reconfigure: " << ase.reconfigure << "\n\n"; } } @@ -979,80 +979,81 @@ void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream, types::PublishedAudioCapabilities pacs) { if (pacs.size() > 0) { for (auto& pac : pacs) { - stream << "\n\t\tvalue handle: " << loghex(std::get<0>(pac).val_hdl) - << " / CCC handle: " << loghex(std::get<0>(pac).ccc_hdl); + stream << "\t • Value handle: " << loghex(std::get<0>(pac).val_hdl) + << ", CCC handle: " << loghex(std::get<0>(pac).ccc_hdl); for (auto& record : std::get<1>(pac)) { - stream << "\n\n\t\tCodecId(Coding format: " - << static_cast(record.codec_id.coding_format) - << ", Vendor company ID: " << static_cast(record.codec_id.vendor_company_id) - << ", Vendor codec ID: " << static_cast(record.codec_id.vendor_codec_id) << ")"; - stream << "\n\t\tCodec specific capabilities:\n"; + stream << "\n\t\t· CodecId (Coding format: " << loghex(record.codec_id.coding_format) + << ", Vendor company ID: " << loghex(record.codec_id.vendor_company_id) + << ", Vendor codec ID: " << loghex(record.codec_id.vendor_codec_id) << ")"; + stream << "\n\t\t Codec specific capabilities:\n"; if (utils::IsCodecUsingLtvFormat(record.codec_id)) { stream << record.codec_spec_caps.ToString("\t\t\t", types::CodecCapabilitiesLtvFormat); } else { stream << "\t\t\t" << base::HexEncode(record.codec_spec_caps_raw.data(), - record.codec_spec_caps_raw.size()); + record.codec_spec_caps_raw.size()) + << "\n"; } - stream << "\t\tMetadata: " + stream << "\t\t Metadata: " << base::HexEncode(record.metadata.data(), record.metadata.size()); } + stream << "\n"; } } } void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream) { - stream << "\n\tSink PACs"; + stream << " ● Device PACS, address: " << ADDRESS_TO_LOGGABLE_STR(address_) << "\n"; + stream << "\t == Sink PACs:\n"; DumpPacsDebugState(stream, snk_pacs_); - stream << "\n\tSource PACs"; + stream << "\t == Source PACs:\n"; DumpPacsDebugState(stream, src_pacs_); } static std::string locationToString(uint32_t location) { - std::string result_str = "unknown location"; - if (location & codec_spec_conf::kLeAudioLocationAnyLeft && location & codec_spec_conf::kLeAudioLocationAnyRight) { - std::string location_left_right = "left/right"; - result_str.swap(location_left_right); + return "left/right"; } else if (location & codec_spec_conf::kLeAudioLocationAnyLeft) { - std::string location_left = "left"; - result_str.swap(location_left); + return "left"; } else if (location & codec_spec_conf::kLeAudioLocationAnyRight) { - std::string location_right = "right"; - result_str.swap(location_right); + return "right"; + } else if (location == codec_spec_conf::kLeAudioLocationMonoAudio) { + return "mono"; } - - return result_str; + return "unknown location"; } -void LeAudioDevice::Dump(int fd) { +void LeAudioDevice::Dump(std::stringstream& stream) { uint16_t acl_handle = get_btm_client_interface().peer.BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE); std::string snk_location = locationToString(snk_audio_locations_.to_ulong()); std::string src_location = locationToString(src_audio_locations_.to_ulong()); - std::stringstream stream; - stream << "\n\taddress: " << ADDRESS_TO_LOGGABLE_STR(address_) << ": " << connection_state_ - << ": " << (conn_id_ == GATT_INVALID_CONN_ID ? "" : std::to_string(conn_id_)) + stream << " ● Device address: " << ADDRESS_TO_LOGGABLE_STR(address_) << ", " + << connection_state_ + << ", conn_id: " << (conn_id_ == GATT_INVALID_CONN_ID ? "-1" : std::to_string(conn_id_)) << ", acl_handle: " << std::to_string(acl_handle) << ", snk_location: " << snk_location - << ", src_location: " << src_location << ",\t" << (encrypted_ ? "Encrypted" : "Unecrypted") - << ",mtu: " << std::to_string(mtu_) - << "\n\tnumber of ases_: " << static_cast(ases_.size()); + << ", src_location: " << src_location << ", mtu: " << std::to_string(mtu_) << ", " + << (encrypted_ ? "Encrypted" : "Unecrypted") + << "\n\t Sink avail. contexts: " << common::ToString(avail_contexts_.sink) + << "\n\t Source avail. contexts: " << common::ToString(avail_contexts_.source) << "\n"; if (gmap_client_ != nullptr) { - gmap_client_->DebugDump(fd); + stream << "\t "; + gmap_client_->DebugDump(stream); } else { + stream << "\t "; stream << "GmapClient not initialized\n"; } if (ases_.size() > 0) { - stream << "\n\t== ASEs == \n\t"; - stream << "id active dir cis_id cis_handle sdu latency rtn " - "cis_state data_path_state"; + stream << "\t == ASEs (" << static_cast(ases_.size()) << "):\n"; + stream << "\t id active dir cis_id cis_handle sdu latency rtn " + "cis_state data_path_state\n"; for (auto& ase : ases_) { - stream << std::setfill('\x20') << "\n\t" << std::left << std::setw(4) + stream << std::setfill('\x20') << "\t " << std::left << std::setw(4) << static_cast(ase.id) << std::left << std::setw(7) << (ase.active ? "true" : "false") << std::left << std::setw(8) << (ase.direction == types::kLeAudioDirectionSink ? "sink" : "source") << std::left @@ -1060,14 +1061,10 @@ void LeAudioDevice::Dump(int fd) { << ase.cis_conn_hdl << std::left << std::setw(5) << ase.qos_config.max_sdu_size << std::left << std::setw(8) << ase.qos_config.max_transport_latency << std::left << std::setw(5) << static_cast(ase.qos_config.retrans_nb) << std::left - << std::setw(10) << bluetooth::common::ToString(ase.cis_state) << std::setw(12) - << bluetooth::common::ToString(ase.data_path_state); + << std::setw(21) << bluetooth::common::ToString(ase.cis_state) << std::setw(19) + << bluetooth::common::ToString(ase.data_path_state) << "\n"; } } - - stream << "\n\t===="; - - dprintf(fd, "%s", stream.str().c_str()); } void LeAudioDevice::DisconnectAcl(void) { @@ -1341,16 +1338,14 @@ void LeAudioDevices::SetInitialGroupAutoconnectState(int group_id, int gatt_if, size_t LeAudioDevices::Size() const { return leAudioDevices_.size(); } -void LeAudioDevices::Dump(int fd, int group_id) const { - std::stringstream stream, stream_pacs; - +void LeAudioDevices::Dump(std::stringstream& stream, int group_id) const { for (auto const& device : leAudioDevices_) { if (device->group_id_ == group_id) { - device->Dump(fd); + device->Dump(stream); - stream_pacs << "\n\taddress: " << device->address_; - device->DumpPacsDebugState(stream_pacs); - dprintf(fd, "%s", stream_pacs.str().c_str()); + stream << "\tAddress: " << device->address_ << "\n"; + device->DumpPacsDebugState(stream); + stream << "\n"; } } } diff --git a/system/bta/le_audio/devices.h b/system/bta/le_audio/devices.h index 0707bae4b4a..e7dcbee61a7 100644 --- a/system/bta/le_audio/devices.h +++ b/system/bta/le_audio/devices.h @@ -221,7 +221,7 @@ public: void PrintDebugState(void); void DumpPacsDebugState(std::stringstream& stream); - void Dump(int fd); + void Dump(std::stringstream& stream); void DisconnectAcl(void); std::vector GetMetadata(types::AudioContexts context_type, @@ -271,7 +271,7 @@ public: tBTM_BLE_CONN_TYPE reconnection_mode, bool current_dev_autoconnect_flag); size_t Size(void) const; - void Dump(int fd, int group_id) const; + void Dump(std::stringstream& stream, int group_id) const; void Cleanup(tGATT_IF client_if); private: diff --git a/system/bta/le_audio/gmap_client.h b/system/bta/le_audio/gmap_client.h index c1e8c320ca7..ec3d431afe3 100644 --- a/system/bta/le_audio/gmap_client.h +++ b/system/bta/le_audio/gmap_client.h @@ -20,6 +20,7 @@ #include #include +#include namespace bluetooth::le_audio { @@ -28,7 +29,7 @@ public: void AddFromStorage(const RawAddress& addr, const uint8_t role, const uint16_t role_handle, const uint8_t UGT_feature, const uint16_t UGT_feature_handle); - void DebugDump(int fd); + void DebugDump(std::stringstream& stream); static bool IsGmapClientEnabled(); diff --git a/system/bta/le_audio/le_audio_types.cc b/system/bta/le_audio/le_audio_types.cc index f14f490916f..4142251d24d 100644 --- a/system/bta/le_audio/le_audio_types.cc +++ b/system/bta/le_audio/le_audio_types.cc @@ -729,15 +729,20 @@ std::string ToHexString(const LeAudioContextType& value) { std::string AudioContexts::to_string() const { std::stringstream s; - for (auto ctx : bluetooth::le_audio::types::kLeAudioContextAllTypesArray) { - if (test(ctx)) { - if (s.tellp() != 0) { - s << " | "; + s << bluetooth::common::ToHexString(mValue); + if (mValue != 0) { + s << " ["; + auto initial_pos = s.tellp(); + for (auto ctx : bluetooth::le_audio::types::kLeAudioContextAllTypesArray) { + if (test(ctx)) { + if (s.tellp() != initial_pos) { + s << " | "; + } + s << ctx; } - s << ctx; } + s << "]"; } - s << " (" << bluetooth::common::ToHexString(mValue) << ")"; return s.str(); } diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 48d09a30b12..17c1c7e9eea 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -156,8 +156,8 @@ public: */ if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING || group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { - log::error("group {} no in correct streaming state: {} or target state: {}", group->group_id_, - ToString(group->GetState()), ToString(group->GetTargetState())); + log::error("Group {} is not streaming or is in transition, state: {}, target state: {}", + group->group_id_, ToString(group->GetState()), ToString(group->GetTargetState())); return false; } -- GitLab From 3f578a3fdbadc3f8d46358774a1fab2a7cdb2fbb Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 26 Sep 2024 11:05:38 +0000 Subject: [PATCH 473/875] LeAudio: Add names to audio set configurations from AIDL Since there is no name for the audio set configurations in the AIDL interface, generate a name based on the configuration parameters, e.g. "AIDL-2-1chan-SinkAse-CodecId_6_0_0-48000hz_120oct_10000us-TargetLatency_3" Bug: 374933885 Test: m -j Flag: EXEMPT; No functional change Change-Id: I822b96b82d79d18e6e46c0dd73a8f6becc343f68 --- .../aidl/le_audio_utils.cc | 68 +++++++++++++++++++ .../aidl/le_audio_utils_unittest.cc | 6 ++ 2 files changed, 74 insertions(+) diff --git a/system/audio_hal_interface/aidl/le_audio_utils.cc b/system/audio_hal_interface/aidl/le_audio_utils.cc index b24e89a3752..1a6a4f4e4c8 100644 --- a/system/audio_hal_interface/aidl/le_audio_utils.cc +++ b/system/audio_hal_interface/aidl/le_audio_utils.cc @@ -507,6 +507,73 @@ static ::bluetooth::le_audio::set_configurations::AseConfiguration GetStackAseCo return config; } +static std::string GenerateNameForConfig( + const ::bluetooth::le_audio::set_configurations::AudioSetConfiguration& config) { + auto namegen = [](const std::vector<::bluetooth::le_audio::set_configurations::AseConfiguration>& + configs, + const char* dir_str) { + std::stringstream cfg_str; + if (configs.size() > 0) { + auto current_config = configs.begin(); + while (current_config != configs.end()) { + uint8_t cfg_multiplier = 1; + auto last_equal_config = current_config; + auto current_codec = current_config->codec; + while (++last_equal_config != configs.end()) { + // For the purpose of name generation, ignore the audio channel allocation + auto current_codec_no_channels = current_codec; + auto last_codec_no_channels = last_equal_config->codec; + current_codec_no_channels.params.Add( + le_audio::codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, (uint32_t)0); + last_codec_no_channels.params.Add( + le_audio::codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, (uint32_t)0); + + if (current_codec_no_channels != last_codec_no_channels) { + break; + } + ++cfg_multiplier; + current_config = last_equal_config; + } + + // Channel configuration + cfg_str << +cfg_multiplier << "-" << +current_codec.GetChannelCountPerIsoStream() << "chan"; + cfg_str << "-" << dir_str << "Ase-"; + // Codec Id + cfg_str << "CodecId_" << +current_codec.id.coding_format << "_" + << +current_codec.id.vendor_company_id << "_" << +current_codec.id.vendor_codec_id + << "-"; + // Codec parameters + cfg_str << current_codec.GetSamplingFrequencyHz() << "hz"; + if (current_codec.id.coding_format == + ::bluetooth::le_audio::types::kLeAudioCodingFormatLC3) { + cfg_str << "_" << current_codec.GetOctetsPerFrame() << "oct"; + cfg_str << "_" << current_codec.GetDataIntervalUs() << "us"; + } + // QoS + cfg_str << "-TargetLatency_" << +current_config->qos.target_latency; + + if (last_equal_config == configs.end()) { + break; + } + + // Check if there are some different configs left + ++current_config; + } + } + return cfg_str.str(); + }; + + std::stringstream name; + name << "AIDL"; + if (!config.confs.sink.empty()) { + name << "-" << namegen(config.confs.sink, "Sink"); + } + if (!config.confs.source.empty()) { + name << "-" << namegen(config.confs.source, "Source"); + } + return name.str(); +} + static ::bluetooth::le_audio::set_configurations::AudioSetConfiguration GetStackConfigSettingFromAidl( ::bluetooth::le_audio::types::LeAudioContextType ctx_type, @@ -540,6 +607,7 @@ GetStackConfigSettingFromAidl( } } + cig_config.name = GenerateNameForConfig(cig_config); return cig_config; } diff --git a/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc b/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc index 4c9e52e904b..98fee01e5b2 100644 --- a/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc +++ b/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc @@ -918,6 +918,9 @@ TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFrom ASSERT_EQ(stack_config->confs.sink.size(), 2ul); ASSERT_EQ(stack_config->confs.source.size(), 2ul); ASSERT_EQ(*stack_config, expected_stack_config); + ASSERT_EQ(stack_config->name, + "AIDL-2-1chan-SinkAse-CodecId_6_0_0-48000hz_120oct_7500us-TargetLatency_2-" + "2-1chan-SourceAse-CodecId_6_0_0-24000hz_80oct_7500us-TargetLatency_1"); } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFromAidlFormatMonoLoc) { @@ -931,6 +934,9 @@ TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFrom ASSERT_EQ(stack_config->confs.sink.size(), 2ul); ASSERT_EQ(stack_config->confs.source.size(), 1ul); ASSERT_EQ(*stack_config, expected_stack_config); + ASSERT_EQ(stack_config->name, + "AIDL-2-1chan-SinkAse-CodecId_6_0_0-48000hz_120oct_7500us-TargetLatency_2-" + "1-1chan-SourceAse-CodecId_6_0_0-24000hz_80oct_7500us-TargetLatency_1"); } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackBisConfigFromAidlFormat) { -- GitLab From 8f33f462daaee6c906a6fcf26f28c4fca32425d1 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 25 Oct 2024 17:04:33 -0700 Subject: [PATCH 474/875] Remove libbluetooth-gdx ModuleMainloop, ModuleJniloop are thin wrappers on top of do_in_main_thread, do_in_jni_thread, and are only used in tests. Remove the associated tests libbluetooth-gdx-test for dumpsys and lifecylce due to lack of comment and documentation (only run in postsubmit). Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, dead code removal Change-Id: I84d810e3f5a371013e1cc3a17561ccaa66f65164 --- TEST_MAPPING | 3 - android/app/Android.bp | 1 - system/audio_hal_interface/Android.bp | 1 - system/audio_hal_interface/fuzzer/Android.bp | 1 - system/btif/Android.bp | 1 - system/btif/BUILD.gn | 1 - system/gd/Android.bp | 84 +-- system/gd/BUILD.gn | 11 - system/gd/module_gdx_unittest.cc | 623 ----------------- system/gd/module_gdx_unittest.h | 78 --- system/gd/module_jniloop.h | 53 -- system/gd/module_jniloop_unittest.cc | 244 ------- system/gd/module_jniloop_unittest.h | 57 -- system/gd/module_mainloop.h | 53 -- system/gd/module_mainloop_unittest.cc | 245 ------- system/gd/module_mainloop_unittest.h | 57 -- system/gd/module_state_dumper_unittest.cc | 161 ----- system/gd/module_state_dumper_unittest.h | 46 -- system/gd/rust/topshim/facade/Android.bp | 1 - system/main/Android.bp | 104 --- .../main/test/main_shim_stack_dumpsys_test.cc | 643 ------------------ .../test/main_shim_stack_lifecycle_test.cc | 619 ----------------- system/stack/Android.bp | 1 - system/stack/test/fuzzers/Android.bp | 1 - system/test/headless/Android.bp | 1 - system/test/suite/Android.bp | 1 - 26 files changed, 3 insertions(+), 3088 deletions(-) delete mode 100644 system/gd/module_gdx_unittest.cc delete mode 100644 system/gd/module_gdx_unittest.h delete mode 100644 system/gd/module_jniloop.h delete mode 100644 system/gd/module_jniloop_unittest.cc delete mode 100644 system/gd/module_jniloop_unittest.h delete mode 100644 system/gd/module_mainloop.h delete mode 100644 system/gd/module_mainloop_unittest.cc delete mode 100644 system/gd/module_mainloop_unittest.h delete mode 100644 system/gd/module_state_dumper_unittest.cc delete mode 100644 system/gd/module_state_dumper_unittest.h delete mode 100644 system/main/test/main_shim_stack_dumpsys_test.cc delete mode 100644 system/main/test/main_shim_stack_lifecycle_test.cc diff --git a/TEST_MAPPING b/TEST_MAPPING index 5da35c4dc00..bd98b7d91cf 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -307,9 +307,6 @@ { "name": "bluetooth-test-audio-hal-a2dp-provider-info" }, - { - "name": "bluetooth_test_gdx_unit" - }, { "name": "net_test_bta_jv" }, diff --git a/android/app/Android.bp b/android/app/Android.bp index f038a3f43b9..2bac3ba017a 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -106,7 +106,6 @@ cc_library_shared { "libbase", "libbluetooth", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_core_rs_bridge", diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index 1e5652c747d..987b8592146 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -228,7 +228,6 @@ cc_defaults { "libFraunhoferAAC", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-protos", "libbluetooth-types", "libbluetooth_core_rs", diff --git a/system/audio_hal_interface/fuzzer/Android.bp b/system/audio_hal_interface/fuzzer/Android.bp index e55a9d62add..93a734b02fa 100644 --- a/system/audio_hal_interface/fuzzer/Android.bp +++ b/system/audio_hal_interface/fuzzer/Android.bp @@ -60,7 +60,6 @@ cc_defaults { "libFraunhoferAAC", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-protos", "libbluetooth-types", "libbluetooth_core_rs", diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 2d3d40e3fd2..2402f95c070 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -298,7 +298,6 @@ cc_test { "libbase", "libbluetooth-dumpsys", "libbluetooth-for-tests", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn index 5129a1efb37..884dc60ba33 100644 --- a/system/btif/BUILD.gn +++ b/system/btif/BUILD.gn @@ -114,7 +114,6 @@ static_library("btif") { "//bt/system:libbt-platform-protos-lite", "//bt/system/common", "//bt/system/profile/avrcp:profile_avrcp", - "//bt/system/gd:libbluetooth-gdx", ] configs += [ diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 579aae7d441..c74cff9adb4 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -129,6 +129,7 @@ cc_defaults { ":BluetoothNeighborSources", ":BluetoothOsSources", ":BluetoothPacketSources", + ":BluetoothShimSources", ":BluetoothStorageSources", "module.cc", "module_dumper.cc", @@ -173,7 +174,7 @@ cc_defaults { ], } -cc_library { +cc_library_static { name: "libbluetooth_gd", defaults: [ "libbluetooth_gd_defaults", @@ -192,27 +193,6 @@ cc_library { } cc_library_static { - name: "libbluetooth-gdx", - defaults: [ - "libbluetooth_gd_defaults", - ], - srcs: [ - ":BluetoothShimSources", - ], - include_dirs: [ - "packages/modules/Bluetooth/system", - ], - apex_available: [ - "com.android.btservices", - ], - min_sdk_version: "31", - static_libs: [ - "bluetooth_flags_c_lib", - "libchrome", - ], -} - -cc_library { name: "libbluetooth_gd_fuzzing", defaults: [ "libbluetooth_gd_defaults", @@ -236,7 +216,7 @@ cc_library { ], } -cc_library { +cc_library_static { name: "libbluetooth_gd_unit_tests", defaults: [ "libbluetooth_gd_defaults", @@ -297,7 +277,6 @@ cc_binary { "breakpad_client", "libPlatformProperties", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-protos", "libbluetooth-types", "libbluetooth_crypto_toolbox", @@ -497,63 +476,6 @@ cc_test { min_sdk_version: "Tiramisu", } -cc_test { - name: "bluetooth_test_gdx_unit", - test_suites: ["device-tests"], - defaults: [ - "aconfig_lib_cc_shared_link.defaults", - "gd_defaults", - "mts_defaults", - ], - include_dirs: [ - "packages/modules/Bluetooth/system", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/stack/include", - "packages/modules/Bluetooth/system/types", - ], - host_supported: true, - srcs: [ - ":BluetoothDumpsysTestSources", - ":BluetoothShimTestSources", - ":TestCommonMockFunctions", - ":TestMockMainShimStack", - "module_gdx_unittest.cc", - "module_jniloop_unittest.cc", - "module_mainloop_unittest.cc", - "module_state_dumper_unittest.cc", - ], - generated_headers: [ - "BluetoothGeneratedBundlerSchema_h_bfbs", - "BluetoothGeneratedDumpsysDataSchema_h", - "BluetoothGeneratedDumpsysInternalTestData_h", - "BluetoothGeneratedDumpsysTestData_h", - ], - static_libs: [ - "bluetooth_flags_c_lib_for_test", - "libbase", - "libbluetooth-dumpsys", - "libbluetooth-dumpsys-test", - "libbluetooth-dumpsys-unittest", - "libbluetooth-gdx", - "libbluetooth_gd", - "libbluetooth_log", - "libbt-btu-main-thread", - "libbt-common", - "libbt-jni-thread", - "libchrome", - "libevent", - "libflatbuffers-cpp", - "libgmock", - "liblog", - "libosi", - "server_configurable_flags", - ], - sanitize: { - address: true, - }, - min_sdk_version: "Tiramisu", -} - cc_test { name: "bluetooth_packet_parser_test", test_suites: ["general-tests"], diff --git a/system/gd/BUILD.gn b/system/gd/BUILD.gn index 5786a5b7004..fa8a64fd258 100644 --- a/system/gd/BUILD.gn +++ b/system/gd/BUILD.gn @@ -53,17 +53,6 @@ group("gd_default_deps") { ] } -static_library("libbluetooth-gdx") { - include_dirs = [ - "packages/modules/Bluetooth/system", - ] - configs += [ ":gd_defaults" ] - deps = [ - "//bt/system/gd:gd_default_deps", - "//bt/system/gd/shim:BluetoothShimSources", - ] -} - static_library("libbluetooth_gd") { sources = [ "module.cc", diff --git a/system/gd/module_gdx_unittest.cc b/system/gd/module_gdx_unittest.cc deleted file mode 100644 index 9d9ee4c7c85..00000000000 --- a/system/gd/module_gdx_unittest.cc +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright 2023 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 "module_gdx_unittest.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "common/bind.h" -#include "common/contextual_callback.h" -#include "gtest/gtest.h" -#include "module.h" -#include "os/handler.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using namespace bluetooth; - -namespace { -constexpr int sync_timeout_in_ms = 3000; - -std::promise gdx_external_function_promise; -std::promise private_impl_promise; -std::promise protected_method_promise; - -} // namespace - -// Global function with C linkage -void external_function_gdx(int /* a */, double /* b */, char /* c */) { - gdx_external_function_promise.set_value(base::PlatformThread::CurrentId()); -} - -// Module private implementation that is inaccessible externally -struct TestGdxModule::PrivateImpl : public ModuleMainloop, public ModuleJniloop { - const int kMaxTestGdxModuleRecurseDepth = 10; - - void privateCallableMethod(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void repostMethodTest(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void privateCallableRepostOnMainMethod(std::shared_ptr ptr, int a, - double b, char c) { - PostMethodOnMain(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRepostOnJniMethod(std::shared_ptr ptr, int a, - double b, char c) { - PostMethodOnJni(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRecursiveOnMainMethod(std::shared_ptr ptr, - int depth, double b, char c) { - if (depth > kMaxTestGdxModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnMain(ptr, &PrivateImpl::privateCallableRecursiveOnMainMethod, ptr, depth + 1, b, c); - } - - void privateCallableRecursiveOnJniMethod(std::shared_ptr ptr, - int depth, double b, char c) { - if (depth > kMaxTestGdxModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnJni(ptr, &PrivateImpl::privateCallableRecursiveOnJniMethod, ptr, depth + 1, b, c); - } -}; - -// Protected module method executed on handler -void TestGdxModule::call_on_handler_protected_method(int loop_tid, int a, int b, int c) { - protected_method_promise = std::promise(); - auto future = protected_method_promise.get_future(); - CallOn(this, &TestGdxModule::protected_method, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on main loop -void TestGdxModule::call_on_main_external_function(int loop_tid, int a, double b, char c) { - gdx_external_function_promise = std::promise(); - auto future = gdx_external_function_promise.get_future(); - PostFunctionOnMain(&external_function_gdx, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestGdxModule::call_on_main(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestGdxModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop and reposted -void TestGdxModule::call_on_main_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRepostOnMainMethod, pimpl_, - a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop recursively -void TestGdxModule::call_on_main_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRecursiveOnMainMethod, - pimpl_, depth, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on main loop -void TestGdxModule::call_on_jni_external_function(int loop_tid, int a, double b, char c) { - gdx_external_function_promise = std::promise(); - auto future = gdx_external_function_promise.get_future(); - PostFunctionOnJni(&external_function_gdx, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestGdxModule::call_on_jni(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestGdxModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop and reposted -void TestGdxModule::call_on_jni_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRepostOnJniMethod, pimpl_, a, - b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop recursively -void TestGdxModule::call_on_jni_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRecursiveOnJniMethod, pimpl_, - depth, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} -void TestGdxModule::protected_method(int /* a */, int /* b */, int /* c */) { - protected_method_promise.set_value(base::PlatformThread::CurrentId()); -} - -bool TestGdxModule::IsStarted() const { return pimpl_ != nullptr; } - -void TestGdxModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared(); -} - -void TestGdxModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string TestGdxModule::ToString() const { return "TestGdxModule"; } - -const bluetooth::ModuleFactory TestGdxModule::Factory = - bluetooth::ModuleFactory([]() { return new TestGdxModule(); }); - -void TestGdxModule::set_callback(common::ContextualCallback callback) { - call_many_ = callback; -} - -void TestGdxModule::set_once_callback(common::ContextualOnceCallback callback) { - call_once_ = std::move(callback); -} - -void TestGdxModule::call_callback_on_handler(std::string message) { - GetHandler()->Post(common::BindOnce([](common::ContextualCallback callback, - std::string message) { callback(message); }, - call_many_, message)); -} - -void TestGdxModule::call_once_callback_on_handler(std::string message) { - GetHandler()->Post(common::BindOnce([](common::ContextualOnceCallback callback, - std::string message) { callback(message); }, - std::move(call_once_), message)); -} - -void TestGdxModule::call_callback_on_main(std::string message) { - post_on_bt_main([message, this]() { call_many_(message); }); -} - -void TestGdxModule::call_once_callback_on_main(std::string message) { - post_on_bt_main([message, this]() { call_once_(message); }); -} - -void TestGdxModule::call_callback_on_jni(std::string message) { - post_on_bt_jni([message, this]() { call_many_(message); }); -} - -void TestGdxModule::call_once_callback_on_jni(std::string message) { - post_on_bt_jni([message, this]() { call_once_(message); }); -} - -// -// Module GDx Testing Below -// -class ModuleGdxTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new TestGdxModule(); - main_thread_start_up(); - mainloop_tid_ = get_mainloop_tid(); - jni_thread_startup(); - jniloop_tid_ = get_jniloop_tid(); - } - - void TearDown() override { - sync_main_handler(); - main_thread_shut_down(); - jni_thread_shutdown(); - delete module_; - } - - void sync_main_handler() { - std::promise promise = std::promise(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - void sync_jni_handler() { - std::promise promise = std::promise(); - std::future future = promise.get_future(); - post_on_bt_jni([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_mainloop_tid() { - std::promise pid_promise = std::promise(); - auto future = pid_promise.get_future(); - post_on_bt_main([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - static pid_t get_jniloop_tid() { - std::promise pid_promise = std::promise(); - auto future = pid_promise.get_future(); - post_on_bt_jni([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t mainloop_tid_{-1}; - pid_t jniloop_tid_{-1}; - TestModuleRegistry module_registry_; - TestGdxModule* module_; -}; - -class ModuleGdxWithStackTest : public ModuleGdxTest { -protected: - void SetUp() override { - ModuleGdxTest::SetUp(); - module_registry_.InjectTestModule(&TestGdxModule::Factory, module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - handler_tid_ = get_handler_tid(module_registry_.GetTestModuleHandler(&TestGdxModule::Factory)); - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise handler_tid_promise = std::promise(); - std::future future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleGdxTest::TearDown(); - } - - TestGdxModule* Mod() { return module_registry_.GetModuleUnderTest(); } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleGdxTest, nop) {} - -TEST_F(ModuleGdxTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted()); - module_registry_.Start(thread); - ASSERT_TRUE(module_registry_.IsStarted()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted()); - delete thread; -} - -// internal handler -TEST_F(ModuleGdxWithStackTest, call_on_handler_protected_method) { - Mod()->call_on_handler_protected_method(handler_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_main) { Mod()->call_on_main(mainloop_tid_, 1, 2, 3); } - -TEST_F(ModuleGdxWithStackTest, test_call_gdx_external_function_on_main) { - Mod()->call_on_main_external_function(mainloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_main_repost) { - Mod()->call_on_main_repost(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_main_recurse) { - Mod()->call_on_main_recurse(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_jni) { Mod()->call_on_jni(jniloop_tid_, 1, 2, 3); } - -TEST_F(ModuleGdxWithStackTest, test_call_gdx_external_function_on_jni) { - Mod()->call_on_jni_external_function(jniloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_jni_repost) { - Mod()->call_on_jni_repost(jniloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_jni_recurse) { - Mod()->call_on_jni_recurse(jniloop_tid_, 1, 2, 3); -} - -class ModuleGdxWithInstrumentedCallback : public ModuleGdxWithStackTest { -protected: - void SetUp() override { ModuleGdxWithStackTest::SetUp(); } - - void TearDown() override { ModuleGdxWithStackTest::TearDown(); } - - // A helper class to promise/future for synchronization - class Promises { - public: - std::promise result; - std::future result_future = result.get_future(); - std::promise blocking; - std::future blocking_future = blocking.get_future(); - std::promise unblock; - std::future unblock_future = unblock.get_future(); - }; - - class InstrumentedCallback { - public: - Promises promises; - common::ContextualCallback callback; - }; - - class InstrumentedOnceCallback { - public: - Promises promises; - common::ContextualOnceCallback callback; - }; - - std::unique_ptr GetNewCallbackOnMain() { - auto to_return = std::make_unique(); - to_return->callback = get_main()->Bind( - [](std::promise* promise_ptr, std::promise* blocking, - std::future* unblock, std::string result) { - // Tell the test that this callback is running (and blocking) - blocking->set_value(); - // Block until the test is ready to continue - ASSERT_EQ(std::future_status::ready, unblock->wait_for(std::chrono::seconds(1))); - // Send the result back to the test - promise_ptr->set_value(result); - log::info("set_value {}", result); - }, - &to_return->promises.result, &to_return->promises.blocking, - &to_return->promises.unblock_future); - - return to_return; - } - - std::unique_ptr GetNewOnceCallbackOnMain() { - auto to_return = std::make_unique(); - to_return->callback = get_main()->BindOnce( - [](std::promise* promise_ptr, std::promise* blocking, - std::future* unblock, std::string result) { - blocking->set_value(); - ASSERT_EQ(std::future_status::ready, unblock->wait_for(std::chrono::seconds(1))); - promise_ptr->set_value(result); - log::info("set_value {}", result); - }, - &to_return->promises.result, &to_return->promises.blocking, - &to_return->promises.unblock_future); - - return to_return; - } -}; - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_callback_on_handler) { - auto instrumented = GetNewCallbackOnMain(); - Mod()->set_callback(instrumented->callback); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the handler"; - Mod()->call_callback_on_handler(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_once_callback_on_handler) { - auto instrumented = GetNewOnceCallbackOnMain(); - Mod()->set_once_callback(std::move(instrumented->callback)); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the handler"; - Mod()->call_once_callback_on_handler(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_callback_on_main) { - auto instrumented = GetNewCallbackOnMain(); - Mod()->set_callback(instrumented->callback); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the main"; - Mod()->call_callback_on_main(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_once_callback_on_main) { - auto instrumented = GetNewOnceCallbackOnMain(); - Mod()->set_once_callback(std::move(instrumented->callback)); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the main"; - Mod()->call_once_callback_on_main(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_callback_on_jni) { - auto instrumented = GetNewCallbackOnMain(); - Mod()->set_callback(instrumented->callback); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the jni"; - Mod()->call_callback_on_jni(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_once_callback_on_jni) { - auto instrumented = GetNewOnceCallbackOnMain(); - Mod()->set_once_callback(std::move(instrumented->callback)); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the jni"; - Mod()->call_once_callback_on_jni(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} diff --git a/system/gd/module_gdx_unittest.h b/system/gd/module_gdx_unittest.h deleted file mode 100644 index 6765be025e5..00000000000 --- a/system/gd/module_gdx_unittest.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2023 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 -#include -#include - -#include - -#include "common/contextual_callback.h" -#include "module.h" -#include "module_jniloop.h" -#include "module_mainloop.h" - -using namespace bluetooth; - -void external_function(int /* a */, double /* b */, char /* c */); - -class TestGdxModule : public Module, public ModuleMainloop, public ModuleJniloop { -public: - void call_on_handler_protected_method(pid_t tid, int a, int b, int c); - void call_on_main_external_function(pid_t tid, int a, double b, char c); - void call_on_main(pid_t tid, int a, int b, int c); - void call_on_main_repost(pid_t tid, int a, int b, int c); - void call_on_main_recurse(pid_t tid, int a, int b, int c); - - void call_on_jni_external_function(pid_t tid, int a, double b, char c); - void call_on_jni(pid_t tid, int a, int b, int c); - void call_on_jni_repost(pid_t tid, int a, int b, int c); - void call_on_jni_recurse(pid_t tid, int a, int b, int c); - - void set_callback(common::ContextualCallback one_message_callback); - void set_once_callback(common::ContextualOnceCallback one_message_callback); - - void call_callback_on_handler(std::string message); - void call_once_callback_on_handler(std::string message); - void call_callback_on_jni(std::string message); - void call_once_callback_on_jni(std::string message); - void call_callback_on_main(std::string message); - void call_once_callback_on_main(std::string message); - - static const bluetooth::ModuleFactory Factory; - -protected: - void protected_method(int a, int b, int c); - void call_on_main_internal(int a, int b, int c); - void call_on_jni_internal(int a, int b, int c); - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - -private: - struct PrivateImpl; - std::shared_ptr pimpl_; - - common::ContextualOnceCallback call_once_; - common::ContextualCallback call_many_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/module_jniloop.h b/system/gd/module_jniloop.h deleted file mode 100644 index b77aa6e322a..00000000000 --- a/system/gd/module_jniloop.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023 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 -#include -#include - -#include "btif/include/btif_jni_task.h" - -namespace bluetooth { - -class ModuleJniloop { -protected: - ModuleJniloop() noexcept = default; - virtual ~ModuleJniloop() = default; - ModuleJniloop(const ModuleJniloop& mod) = delete; - - // Threadsafe post onto jni loop a function with copyable arguments - template - void PostFunctionOnJni(Functor&& functor, Args&&... args) const { - do_in_jni_thread(base::BindOnce(std::forward(functor), std::forward(args)...)); - } - - // Threadsafe post onto jni loop a method and context with copyable arguments - template - void PostMethodOnJni(std::shared_ptr ref, Functor&& functor, Args... args) const { - do_in_jni_thread(base::BindOnce( - [](std::weak_ptr ref, Functor&& functor, Args&&... args) { - if (std::shared_ptr spt = ref.lock()) { - base::BindOnce(std::forward(functor), spt, std::forward(args)...) - .Run(); - } - }, - std::weak_ptr(ref), std::forward(functor), std::forward(args)...)); - } -}; - -} // namespace bluetooth diff --git a/system/gd/module_jniloop_unittest.cc b/system/gd/module_jniloop_unittest.cc deleted file mode 100644 index 98c6b7e09d0..00000000000 --- a/system/gd/module_jniloop_unittest.cc +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 2023 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 "module_jniloop_unittest.h" - -#include -#include -#include -#include -#include - -#include - -#include "btif/include/btif_jni_task.h" -#include "gtest/gtest.h" -#include "module.h" -#include "os/handler.h" -#include "os/thread.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using namespace bluetooth; - -namespace { -constexpr int sync_timeout_in_ms = 3000; - -std::promise external_function_promise; -std::promise private_impl_promise; -std::promise protected_method_promise; - -} // namespace - -// Global function with C linkage -void external_function_jni(int /* a */, double /* b */, char /* c */) { - external_function_promise.set_value(base::PlatformThread::CurrentId()); -} - -// Module private implementation that is inaccessible externally -struct TestJniModule::PrivateImpl : public ModuleJniloop { - const int kMaxTestModuleRecurseDepth = 10; - - void privateCallableMethod(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void repostMethodTest(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void privateCallableRepostMethod(std::shared_ptr ptr, int a, double b, - char c) { - PostMethodOnJni(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRecursiveMethod(std::shared_ptr ptr, int depth, - double b, char c) { - if (depth > kMaxTestModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnJni(ptr, &PrivateImpl::privateCallableRecursiveMethod, ptr, depth + 1, b, c); - } -}; - -// Protected module method executed on handler -void TestJniModule::call_on_handler_protected_method(int loop_tid, int a, int b, int c) { - protected_method_promise = std::promise(); - auto future = protected_method_promise.get_future(); - CallOn(this, &TestJniModule::protected_method, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on jni loop -void TestJniModule::call_on_jni_external_function(int loop_tid, int a, double b, char c) { - external_function_promise = std::promise(); - auto future = external_function_promise.get_future(); - PostFunctionOnJni(&external_function_jni, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestJniModule::call_on_jni(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestJniModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on jni loop and reposted -void TestJniModule::call_on_jni_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestJniModule::PrivateImpl::privateCallableRepostMethod, pimpl_, a, b, - c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on jni loop recursively -void TestJniModule::call_on_jni_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestJniModule::PrivateImpl::privateCallableRecursiveMethod, pimpl_, - depth, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -void TestJniModule::protected_method(int /* a */, int /* b */, int /* c */) { - protected_method_promise.set_value(base::PlatformThread::CurrentId()); -} - -bool TestJniModule::IsStarted() const { return pimpl_ != nullptr; } - -void TestJniModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared(); -} - -void TestJniModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string TestJniModule::ToString() const { return std::string(__func__); } - -const bluetooth::ModuleFactory TestJniModule::Factory = - bluetooth::ModuleFactory([]() { return new TestJniModule(); }); - -// -// Module GDx Testing Below -// -class ModuleGdxJniTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new TestJniModule(); - jni_thread_startup(); - jniloop_tid_ = get_jniloop_tid(); - } - - void TearDown() override { - sync_jni_handler(); - jni_thread_shutdown(); - delete module_; - } - - void sync_jni_handler() { - std::promise promise = std::promise(); - std::future future = promise.get_future(); - post_on_bt_jni([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_jniloop_tid() { - std::promise pid_promise = std::promise(); - auto future = pid_promise.get_future(); - post_on_bt_jni([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t jniloop_tid_{-1}; - TestModuleRegistry module_registry_; - TestJniModule* module_; -}; - -class ModuleGdxWithJniStackTest : public ModuleGdxJniTest { -protected: - void SetUp() override { - ModuleGdxJniTest::SetUp(); - module_registry_.InjectTestModule(&TestJniModule::Factory, module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - handler_tid_ = get_handler_tid(module_registry_.GetTestModuleHandler(&TestJniModule::Factory)); - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise handler_tid_promise = std::promise(); - std::future future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleGdxJniTest::TearDown(); - } - - TestJniModule* Mod() { return module_registry_.GetModuleUnderTest(); } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleGdxJniTest, nop) {} - -TEST_F(ModuleGdxJniTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted()); - module_registry_.Start(thread); - ASSERT_TRUE(module_registry_.IsStarted()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted()); - delete thread; -} - -TEST_F(ModuleGdxWithJniStackTest, call_on_handler_protected_method) { - Mod()->call_on_handler_protected_method(handler_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithJniStackTest, test_call_on_jni) { Mod()->call_on_jni(jniloop_tid_, 1, 2, 3); } - -TEST_F(ModuleGdxWithJniStackTest, test_call_external_function) { - Mod()->call_on_jni_external_function(jniloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleGdxWithJniStackTest, test_call_on_jni_repost) { - Mod()->call_on_jni_repost(jniloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithJniStackTest, test_call_on_jni_recurse) { - Mod()->call_on_jni_recurse(jniloop_tid_, 1, 2, 3); -} diff --git a/system/gd/module_jniloop_unittest.h b/system/gd/module_jniloop_unittest.h deleted file mode 100644 index 032606251e1..00000000000 --- a/system/gd/module_jniloop_unittest.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2023 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 -#include -#include - -#include - -#include "module.h" -#include "module_jniloop.h" - -using namespace bluetooth; - -void external_function(int /* a */, double /* b */, char /* c */); - -class TestJniModule : public Module, public ModuleJniloop { -public: - void call_on_handler_protected_method(pid_t tid, int a, int b, int c); - void call_on_jni_external_function(pid_t tid, int a, double b, char c); - void call_on_jni(pid_t tid, int a, int b, int c); - void call_on_jni_repost(pid_t tid, int a, int b, int c); - void call_on_jni_recurse(pid_t tid, int a, int b, int c); - - static const bluetooth::ModuleFactory Factory; - -protected: - void protected_method(int a, int b, int c); - void call_on_jni_internal(int a, int b, int c); - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - -private: - struct PrivateImpl; - std::shared_ptr pimpl_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/module_mainloop.h b/system/gd/module_mainloop.h deleted file mode 100644 index 9f07e89ef64..00000000000 --- a/system/gd/module_mainloop.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023 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 -#include -#include - -#include "stack/include/main_thread.h" - -namespace bluetooth { - -class ModuleMainloop { -protected: - ModuleMainloop() noexcept = default; - virtual ~ModuleMainloop() = default; - ModuleMainloop(const ModuleMainloop& mod) = delete; - - // Threadsafe post onto mainloop a function with copyable arguments - template - void PostFunctionOnMain(Functor&& functor, Args&&... args) const { - do_in_main_thread(base::BindOnce(std::forward(functor), std::forward(args)...)); - } - - // Threadsafe post onto mainloop a method and context with copyable arguments - template - void PostMethodOnMain(std::shared_ptr ref, Functor&& functor, Args... args) const { - do_in_main_thread(base::BindOnce( - [](std::weak_ptr ref, Functor&& functor, Args&&... args) { - if (std::shared_ptr spt = ref.lock()) { - base::BindOnce(std::forward(functor), spt, std::forward(args)...) - .Run(); - } - }, - std::weak_ptr(ref), std::forward(functor), std::forward(args)...)); - } -}; - -} // namespace bluetooth diff --git a/system/gd/module_mainloop_unittest.cc b/system/gd/module_mainloop_unittest.cc deleted file mode 100644 index cac37f83fea..00000000000 --- a/system/gd/module_mainloop_unittest.cc +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2023 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 "module_mainloop_unittest.h" - -#include -#include -#include -#include -#include - -#include - -#include "gtest/gtest.h" -#include "module.h" -#include "os/handler.h" -#include "os/thread.h" -#include "stack/include/main_thread.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using namespace bluetooth; - -namespace { -constexpr int sync_timeout_in_ms = 3000; - -std::promise external_function_promise; -std::promise private_impl_promise; -std::promise protected_method_promise; - -} // namespace - -// Global function with C linkage -void external_function_main(int /* a */, double /* b */, char /* c */) { - external_function_promise.set_value(base::PlatformThread::CurrentId()); -} - -// Module private implementation that is inaccessible externally -struct TestModule::PrivateImpl : public ModuleMainloop { - const int kMaxTestModuleRecurseDepth = 10; - - void privateCallableMethod(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void repostMethodTest(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void privateCallableRepostMethod(std::shared_ptr ptr, int a, double b, - char c) { - PostMethodOnMain(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRecursiveMethod(std::shared_ptr ptr, int depth, - double b, char c) { - if (depth > kMaxTestModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnMain(ptr, &PrivateImpl::privateCallableRecursiveMethod, ptr, depth + 1, b, c); - } -}; - -// Protected module method executed on handler -void TestModule::call_on_handler_protected_method(int loop_tid, int a, int b, int c) { - protected_method_promise = std::promise(); - auto future = protected_method_promise.get_future(); - CallOn(this, &TestModule::protected_method, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on main loop -void TestModule::call_on_main_external_function(int loop_tid, int a, double b, char c) { - external_function_promise = std::promise(); - auto future = external_function_promise.get_future(); - PostFunctionOnMain(&external_function_main, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestModule::call_on_main(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop and reposted -void TestModule::call_on_main_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestModule::PrivateImpl::privateCallableRepostMethod, pimpl_, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop recursively -void TestModule::call_on_main_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestModule::PrivateImpl::privateCallableRecursiveMethod, pimpl_, depth, - b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -void TestModule::protected_method(int /* a */, int /* b */, int /* c */) { - protected_method_promise.set_value(base::PlatformThread::CurrentId()); -} - -bool TestModule::IsStarted() const { return pimpl_ != nullptr; } - -void TestModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared(); -} - -void TestModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string TestModule::ToString() const { return std::string(__func__); } - -const bluetooth::ModuleFactory TestModule::Factory = - bluetooth::ModuleFactory([]() { return new TestModule(); }); - -// -// Module GDx Testing Below -// -class ModuleMainGdxTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new TestModule(); - main_thread_start_up(); - mainloop_tid_ = get_mainloop_tid(); - } - - void TearDown() override { - sync_main_handler(); - main_thread_shut_down(); - delete module_; - } - - void sync_main_handler() { - std::promise promise = std::promise(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_mainloop_tid() { - std::promise pid_promise = std::promise(); - auto future = pid_promise.get_future(); - post_on_bt_main([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t mainloop_tid_{-1}; - TestModuleRegistry module_registry_; - TestModule* module_; -}; - -class ModuleMainGdxWithStackTest : public ModuleMainGdxTest { -protected: - void SetUp() override { - ModuleMainGdxTest::SetUp(); - module_registry_.InjectTestModule(&TestModule::Factory, module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - handler_tid_ = get_handler_tid(module_registry_.GetTestModuleHandler(&TestModule::Factory)); - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise handler_tid_promise = std::promise(); - std::future future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleMainGdxTest::TearDown(); - } - - TestModule* Mod() { return module_registry_.GetModuleUnderTest(); } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleMainGdxTest, nop) {} - -TEST_F(ModuleMainGdxTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted()); - module_registry_.Start(thread); - ASSERT_TRUE(module_registry_.IsStarted()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted()); - delete thread; -} - -TEST_F(ModuleMainGdxWithStackTest, call_on_handler_protected_method) { - Mod()->call_on_handler_protected_method(handler_tid_, 1, 2, 3); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_on_main) { - Mod()->call_on_main(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_external_function) { - Mod()->call_on_main_external_function(mainloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_on_main_repost) { - Mod()->call_on_main_repost(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_on_main_recurse) { - Mod()->call_on_main_recurse(mainloop_tid_, 1, 2, 3); -} diff --git a/system/gd/module_mainloop_unittest.h b/system/gd/module_mainloop_unittest.h deleted file mode 100644 index 8e864f33d75..00000000000 --- a/system/gd/module_mainloop_unittest.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2023 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 -#include -#include - -#include - -#include "module.h" -#include "module_mainloop.h" - -using namespace bluetooth; - -void external_function(int /* a */, double /* b */, char /* c */); - -class TestModule : public Module, public ModuleMainloop { -public: - void call_on_handler_protected_method(pid_t tid, int a, int b, int c); - void call_on_main_external_function(pid_t tid, int a, double b, char c); - void call_on_main(pid_t tid, int a, int b, int c); - void call_on_main_repost(pid_t tid, int a, int b, int c); - void call_on_main_recurse(pid_t tid, int a, int b, int c); - - static const bluetooth::ModuleFactory Factory; - -protected: - void protected_method(int a, int b, int c); - void call_on_main_internal(int a, int b, int c); - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - -private: - struct PrivateImpl; - std::shared_ptr pimpl_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/module_state_dumper_unittest.cc b/system/gd/module_state_dumper_unittest.cc deleted file mode 100644 index 2bb3e92addf..00000000000 --- a/system/gd/module_state_dumper_unittest.cc +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2023 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 "module_state_dumper_unittest.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gtest/gtest.h" -#include "module_dumper.h" -#include "os/handler.h" -#include "os/thread.h" -#include "stack/include/main_thread.h" - -using namespace bluetooth; - -namespace { - -constexpr int sync_timeout_in_ms = 3000; -constexpr char title[] = "module_state_dumper_test"; - -} // namespace - -// Module private implementation that is inaccessible externally -struct StateDumperTestModule::PrivateImpl : public ModuleMainloop {}; - -bool StateDumperTestModule::IsStarted() const { return pimpl_ != nullptr; } - -void StateDumperTestModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared(); -} - -void StateDumperTestModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string StateDumperTestModule::ToString() const { return std::string(__func__); } - -const bluetooth::ModuleFactory StateDumperTestModule::Factory = - bluetooth::ModuleFactory([]() { return new StateDumperTestModule(); }); - -DumpsysDataFinisher StateDumperTestModule::GetDumpsysData( - flatbuffers::FlatBufferBuilder* /* builder */) const { - log::info("flatbuffers"); - return EmptyDumpsysDataFinisher; -} - -// -// Module GDx Testing Below -// -class ModuleStateDumperTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new StateDumperTestModule(); - main_thread_start_up(); - mainloop_tid_ = get_mainloop_tid(); - } - - void TearDown() override { - sync_main_handler(); - main_thread_shut_down(); - delete module_; - } - - void sync_main_handler() { - std::promise promise = std::promise(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_mainloop_tid() { - std::promise pid_promise = std::promise(); - auto future = pid_promise.get_future(); - post_on_bt_main([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t mainloop_tid_{-1}; - TestModuleRegistry module_registry_; - StateDumperTestModule* module_; -}; - -class ModuleStateDumperWithStackTest : public ModuleStateDumperTest { -protected: - void SetUp() override { - ModuleStateDumperTest::SetUp(); - module_registry_.InjectTestModule(&StateDumperTestModule::Factory, - module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise handler_tid_promise = std::promise(); - std::future future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleStateDumperTest::TearDown(); - } - - StateDumperTestModule* Mod() { - return module_registry_.GetModuleUnderTest(); - } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleStateDumperTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted()); - module_registry_.Start(thread); - ASSERT_TRUE(module_registry_.IsStarted()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted()); - delete thread; -} - -TEST_F(ModuleStateDumperWithStackTest, dump_state) { - ModuleDumper dumper(STDOUT_FILENO, module_registry_, title); - - std::string output; - std::ostringstream oss; - dumper.DumpState(&output, oss); - - log::info("DUMP STATE"); - log::info("{}", oss.str()); - log::info("{}", output); -} diff --git a/system/gd/module_state_dumper_unittest.h b/system/gd/module_state_dumper_unittest.h deleted file mode 100644 index 7c2a1e6f1c6..00000000000 --- a/system/gd/module_state_dumper_unittest.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2023 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 -#include - -#include "module.h" -#include "module_mainloop.h" - -using namespace bluetooth; - -class StateDumperTestModule : public Module, public ModuleMainloop { -public: - static const bluetooth::ModuleFactory Factory; - -protected: - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - - DumpsysDataFinisher GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const override; - -private: - struct PrivateImpl; - std::shared_ptr pimpl_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/rust/topshim/facade/Android.bp b/system/gd/rust/topshim/facade/Android.bp index cfecd4465b4..725ddaa355d 100644 --- a/system/gd/rust/topshim/facade/Android.bp +++ b/system/gd/rust/topshim/facade/Android.bp @@ -38,7 +38,6 @@ rust_defaults { "lib-bt-packets-base", "libFraunhoferAAC", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", // Gabeldorsche diff --git a/system/main/Android.bp b/system/main/Android.bp index 454dd794008..cfa85eea7ea 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -192,14 +192,12 @@ cc_test { "shim/utils.cc", "test/common_stack_test.cc", "test/main_shim_dumpsys_test.cc", - "test/main_shim_stack_lifecycle_test.cc", "test/main_shim_test.cc", ], static_libs: [ "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", @@ -241,105 +239,3 @@ cc_test { min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], } - -cc_test { - name: "net_test_main_dumpsys", - test_suites: ["general-tests"], - host_supported: true, - test_options: { - unit_test: true, - }, - defaults: [ - "fluoride_defaults", - "mts_defaults", - ], - include_dirs: [ - "packages/modules/Bluetooth/system", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/stack/btm", - "packages/modules/Bluetooth/system/stack/include", - ], - generated_headers: [ - "BluetoothGeneratedBundlerSchema_h_bfbs", - "BluetoothGeneratedDumpsysDataSchema_h", - ], - srcs: [ - ":BluetoothOsSources_host", - ":BluetoothStackManagerSources", - ":LibBluetoothShimSources", - ":TestCommonMainHandler", - ":TestCommonMockFunctions", - ":TestMockBta", - ":TestMockBtif", - ":TestMockBtu", - ":TestMockJni", - ":TestMockLegacyHciCommands", - ":TestMockLegacyHciInterface", - ":TestMockStack", - ":TestMockStackRnr", - "test/main_shim_stack_dumpsys_test.cc", - ], - static_libs: [ - "bluetooth_flags_c_lib_for_test", - "libbase", - "libbluetooth-dumpsys", - "libbluetooth-gdx", - "libbluetooth-types", - "libbluetooth_core_rs_bridge", - "libbluetooth_crypto_toolbox", - "libbluetooth_gd", - "libbluetooth_hci_pdl", - "libbluetooth_log", - "libbt-common", - "libbt-platform-protos-lite", - "libbtdevice", - "libchrome", - "libcom.android.sysprop.bluetooth.wrapped", - "libevent", - "libflatbuffers-cpp", - "libgmock", - "liblog", - "libosi", - ], - shared_libs: [ - "libPlatformProperties", - "libaconfig_storage_read_api_cc", - "libcrypto", - "server_configurable_flags", - ], - target: { - linux: { - srcs: [ - ":BluetoothOsSources_fake_timer", - ], - }, - android: { - static_libs: [ - "android.hardware.bluetooth@1.0", - "android.hardware.bluetooth@1.1", - "android.system.suspend-V1-ndk", - "android.system.suspend.control-V1-ndk", - "libstatslog_bt", - ], - shared_libs: [ - "libbinder_ndk", - "libcutils", - "libhidlbase", - "libstatssocket", - "libutils", - ], - }, - }, - sanitize: { - address: true, - all_undefined: true, - cfi: true, - integer_overflow: true, - scs: true, - diag: { - undefined: true, - }, - }, - min_sdk_version: "Tiramisu", - header_libs: ["libbluetooth_headers"], -} diff --git a/system/main/test/main_shim_stack_dumpsys_test.cc b/system/main/test/main_shim_stack_dumpsys_test.cc deleted file mode 100644 index 30e6df12250..00000000000 --- a/system/main/test/main_shim_stack_dumpsys_test.cc +++ /dev/null @@ -1,643 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include -#include - -#include -#include - -#include "common/circular_buffer.h" -#include "common/strings.h" -#include "gd/module_jniloop.h" -#include "gd/module_mainloop.h" -#include "hci/include/packet_fragmenter.h" -#include "main/shim/dumpsys.h" -#include "main/shim/entry.h" -#include "main/shim/stack.h" -#include "module.h" -#include "os/thread.h" -#include "shim/dumpsys.h" -#include "stack/btm/btm_int_types.h" -#include "stack/btm/btm_sec_cb.h" -#include "stack/include/main_thread.h" -#include "test/mock/mock_main_shim_entry.h" - -using ::testing::_; - -using namespace bluetooth; -using namespace testing; - -tBTM_CB btm_cb{}; // main::shim::le_scanning_manager -tBTM_SEC_CB btm_sec_cb{}; // main::shim::acl - -const packet_fragmenter_t* packet_fragmenter_get_interface() { - return nullptr; -} // main::shim::hci_layer -bluetooth::common::TimestamperInMilliseconds - timestamper_in_milliseconds; // main::shim::le_scanning_manager - -namespace { -constexpr char kLogTagStopped[] = "STOPPED"; -constexpr char kLogTagStarting[] = "STARTING"; -constexpr char kLogTagStarted[] = "STARTED"; -constexpr char kLogTagQuiescing[] = "QUIESCING"; -constexpr char kLogTagQuiesced[] = "QUIESCED"; - -constexpr char kTestStackThreadName[] = "test_stack_thread"; -constexpr int kSyncMainLoopTimeoutMs = 3000; -constexpr int kWaitUntilHandlerStoppedMs = 2000; -constexpr size_t kNumTestClients = 10; - -constexpr size_t kTagLength = 48 + sizeof(' ') + sizeof(' '); -inline void log_tag(std::string tag) { - std::string prepend(kTagLength / 2 - tag.size() / 2, '='); - std::string append(kTagLength / 2 - tag.size() / 2, '='); - log::info("{} {} {}", prepend, tag, append); -} - -class MainThread { -public: - MainThread() { - main_thread_start_up(); - post_on_bt_main([]() { log::info("<=== tid Main loop started"); }); - } - - ~MainThread() { - sync_main_handler(); - main_thread_shut_down(); - } - -private: - void sync_main_handler() { - std::promise promise = std::promise(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } -}; - -class TestStackManager { -public: - TestStackManager() { - // Stack manager is started in the test after each test uses the default - // or adds their own modules - } - - ~TestStackManager() { - log::debug("Deleting stack manager"); - Stop(); - } - - TestStackManager(const TestStackManager&) = delete; - - template - void AddModule() { - modules_.add(); - } - - void Start() { - if (stack_started_) { - return; - } - log::info("Starting up stack manager"); - stack_started_ = true; - bluetooth::os::Thread* stack_thread = new bluetooth::os::Thread( - kTestStackThreadName, bluetooth::os::Thread::Priority::NORMAL); - bluetooth::shim::Stack::GetInstance()->StartModuleStack(&modules_, stack_thread); - bluetooth::shim::Stack::GetInstance()->GetHandler()->Call( - []() { log::info("<=== tid GD Event loop started"); }); - } - - void Stop() { - if (!stack_started_) { - return; - } - stack_started_ = false; - bluetooth::shim::Stack::GetInstance()->Stop(); - } - - // NOTE: Stack manager *must* be active else method returns nullptr - // if stack manager has not started or shutdown - template - static T* GetUnsafeModule() { - return bluetooth::shim::Stack::GetInstance()->GetStackManager()->GetInstance(); - } - - size_t NumModules() const { return modules_.NumModules(); } - -private: - bluetooth::ModuleList modules_; - bool stack_started_{false}; -}; - -// Data returned via callback from a stack managed module -struct TestCallbackData { - int iter; - std::string tag; -}; - -// Data sent to a stack managed module via a module API -struct TestData { - int iter; - std::string tag; - std::function callback; -}; - -} // namespace - -class TestStackDumpsysBase : public bluetooth::Module, public ModuleMainloop, public ModuleJniloop { -public: - TestStackDumpsysBase(const TestStackDumpsysBase&) = delete; - TestStackDumpsysBase& operator=(const TestStackDumpsysBase&) = delete; - - virtual ~TestStackDumpsysBase() {} - static const ModuleFactory Factory; - - virtual void TestMethod(TestData test_data) const { - log::info("Test base class iter:{} tag:{}", test_data.iter, test_data.tag); - } - -protected: - void ListDependencies(ModuleList* /* list */) const override {} - void Start() override { log::error("Started TestStackDumpsysBase"); } - void Stop() override { log::error("Stopped TestStackDumpsysBase"); } - std::string ToString() const override { return std::string("TestFunction"); } - - TestStackDumpsysBase() = default; -}; - -struct StackRunningData { - std::function cb; -}; - -class TestStackDumpsys1 : public TestStackDumpsysBase { -public: - TestStackDumpsys1(const TestStackDumpsys1&) = delete; - TestStackDumpsys1& operator=(const TestStackDumpsys1&) = delete; - virtual ~TestStackDumpsys1() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - void IsStackRunning(StackRunningData stack_running_data) const; - -private: - struct impl; - std::shared_ptr impl_; - TestStackDumpsys1(); -}; - -struct TestStackDumpsys1::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } - void is_stack_running(StackRunningData stack_running_data) const { - bool is_running = bluetooth::shim::Stack::GetInstance()->IsRunning(); - if (stack_running_data.cb) { - stack_running_data.cb(is_running); - } - } -}; - -TestStackDumpsys1::TestStackDumpsys1() : TestStackDumpsysBase() { - impl_ = std::make_shared(); -} - -void TestStackDumpsys1::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -void TestStackDumpsys1::IsStackRunning(StackRunningData stack_running_data) const { - GetHandler()->CallOn(impl_.get(), &impl::is_stack_running, stack_running_data); -} - -class TestStackDumpsys2 : public TestStackDumpsysBase { -public: - TestStackDumpsys2(const TestStackDumpsys2&) = delete; - TestStackDumpsys2& operator=(const TestStackDumpsys2&) = delete; - virtual ~TestStackDumpsys2() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr impl_; - TestStackDumpsys2(); -}; - -struct TestStackDumpsys2::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackDumpsys2::TestStackDumpsys2() : TestStackDumpsysBase() { - impl_ = std::make_shared(); -} - -void TestStackDumpsys2::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackDumpsys3 : public TestStackDumpsysBase { -public: - TestStackDumpsys3(const TestStackDumpsys3&) = delete; - TestStackDumpsys3& operator=(const TestStackDumpsys3&) = delete; - virtual ~TestStackDumpsys3() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr impl_; - TestStackDumpsys3(); -}; - -struct TestStackDumpsys3::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackDumpsys3::TestStackDumpsys3() : TestStackDumpsysBase() { - impl_ = std::make_shared(); -} - -void TestStackDumpsys3::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackDumpsys4 : public TestStackDumpsysBase { -public: - TestStackDumpsys4(const TestStackDumpsys4&) = delete; - TestStackDumpsys4& operator=(const TestStackDumpsys3&) = delete; - virtual ~TestStackDumpsys4() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override { - log::info("mod:{} iter:{} tag:{}", __func__, test_data.iter, test_data.tag); - } - -private: - struct impl; - std::shared_ptr impl_; - TestStackDumpsys4() : TestStackDumpsysBase() {} -}; - -struct TestStackDumpsys4::impl : public ModuleMainloop, public ModuleJniloop {}; - -const ModuleFactory TestStackDumpsysBase::Factory = - ModuleFactory([]() { return new TestStackDumpsysBase(); }); - -const ModuleFactory TestStackDumpsys1::Factory = - ModuleFactory([]() { return new TestStackDumpsys1(); }); -const ModuleFactory TestStackDumpsys2::Factory = - ModuleFactory([]() { return new TestStackDumpsys2(); }); -const ModuleFactory TestStackDumpsys3::Factory = - ModuleFactory([]() { return new TestStackDumpsys3(); }); -const ModuleFactory TestStackDumpsys4::Factory = - ModuleFactory([]() { return new TestStackDumpsys4(); }); - -class StackWithMainThreadUnitTest : public ::testing::Test { -protected: - void SetUp() override { main_thread_ = std::make_unique(); } - void TearDown() override { main_thread_.reset(); } - -private: - std::unique_ptr main_thread_; -}; - -class StackLifecycleUnitTest : public StackWithMainThreadUnitTest { -public: - std::shared_ptr StackManager() const { return stack_manager_; } - -protected: - void SetUp() override { - StackWithMainThreadUnitTest::SetUp(); - stack_manager_ = std::make_shared(); - } - - void TearDown() override { - stack_manager_.reset(); - StackWithMainThreadUnitTest::TearDown(); - } - -private: - std::shared_ptr stack_manager_; -}; - -class MainShimStackDumpsysTest : public StackLifecycleUnitTest { -protected: - void SetUp() override { - StackLifecycleUnitTest::SetUp(); - StackManager()->AddModule(); - StackManager()->AddModule(); - StackManager()->AddModule(); - StackManager()->AddModule(); - StackManager()->Start(); - ASSERT_EQ(4U, StackManager()->NumModules()); - - bluetooth::shim::RegisterDumpsysFunction( - (void*)this, [](int fd) { log::info("Callback to dump legacy data fd:{}", fd); }); - } - - void TearDown() override { - bluetooth::shim::UnregisterDumpsysFunction((void*)this); - StackLifecycleUnitTest::TearDown(); - } -}; - -struct CallablePostCnt { - size_t success{0}; - size_t misses{0}; - CallablePostCnt operator+=(const CallablePostCnt& post_cnt) { - return CallablePostCnt({success += post_cnt.success, misses += post_cnt.misses}); - } -}; - -// Provide a client user of the stack manager module services -class Client { -public: - Client(int id) : id_(id) {} - Client(const Client&) = default; - virtual ~Client() = default; - - // Start up the client a thread and handler - void Start() { - thread_ = new os::Thread(common::StringFormat("ClientThread%d", id_), - os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - handler_->Post( - common::BindOnce([](int id) { log::info("<=== tid Started client id:{}", id); }, id_)); - } - - // Ensure all the client handlers are running - void Await() { - std::promise promise; - std::future future = promise.get_future(); - handler_->Post(base::BindOnce([](std::promise promise) { promise.set_value(); }, - std::move(promise))); - future.wait(); - } - - // Post a work task on behalf of this client - void Post(common::OnceClosure closure) { - if (quiesced_) { - post_cnt_.misses++; - } else { - post_cnt_.success++; - handler_->Post(std::move(closure)); - } - } - - // Safely prevent new work tasks from being posted - void Quiesce() { - if (quiesced_) { - return; - } - quiesced_ = true; - std::promise promise = std::promise(); - std::future future = promise.get_future(); - handler_->Post(common::BindOnce( - [](std::promise promise, int id) { - promise.set_value(); - log::info("<=== tid Quiesced client id:{}", id); - }, - std::move(promise), id_)); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } - - // Queisces if needed and stops the client then releases associated resources - void Stop() { - if (!quiesced_) { - Quiesce(); - } - handler_->Clear(); - handler_->WaitUntilStopped(std::chrono::milliseconds(kWaitUntilHandlerStoppedMs)); - delete handler_; - delete thread_; - } - - int Id() const { return id_; } - - CallablePostCnt GetCallablePostCnt() const { return post_cnt_; } - - std::string Name() const { return common::StringFormat("%s%d", __func__, id_); } - -private: - int id_{0}; - CallablePostCnt post_cnt_{}; - bool quiesced_{false}; - os::Handler* handler_{nullptr}; - os::Thread* thread_{nullptr}; -}; - -// Convenience object to handle multiple clients with logging -class ClientGroup { -public: - explicit ClientGroup(size_t num_clients) { - for (size_t i = 0; i < num_clients; i++) { - clients_.emplace_back(std::make_unique(i)); - } - } - - void Start() { - log_tag(kLogTagStarting); - for (auto& c : clients_) { - c->Start(); - } - } - - void Await() { - for (auto& c : clients_) { - c->Await(); - } - log_tag(kLogTagStarted); - } - - void Quiesce() { - log_tag(kLogTagQuiescing); - for (auto& c : clients_) { - c->Quiesce(); - } - log_tag(kLogTagQuiesced); - } - - void Stop() { - for (auto& c : clients_) { - c->Stop(); - } - log_tag(kLogTagStopped); - } - - void Dump() const { - for (auto& c : clients_) { - log::info("Callable post cnt client_id:{} success:{} misses:{}", c->Id(), - c->GetCallablePostCnt().success, c->GetCallablePostCnt().misses); - } - } - - CallablePostCnt GetCallablePostCnt() const { - CallablePostCnt post_cnt{}; - for (auto& c : clients_) { - post_cnt += c->GetCallablePostCnt(); - } - return post_cnt; - } - - size_t NumClients() const { return clients_.size(); } - - std::vector> clients_; -}; - -class MainShimStackDumpsysWithClientsTest : public MainShimStackDumpsysTest { -protected: - void SetUp() override { - MainShimStackDumpsysTest::SetUp(); - client_group_.Start(); - client_group_.Await(); - } - - void TearDown() override { - client_group_.Quiesce(); - client_group_.Stop(); - MainShimStackDumpsysTest::TearDown(); - } - ClientGroup client_group_ = ClientGroup(kNumTestClients); -}; - -TEST_F(MainShimStackDumpsysWithClientsTest, all_clients_check_stack_running) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Stack is running:{}", (is_stack_running) ? 'T' : 'F'); - }, - }; - - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - for (auto& c : client_group_.clients_) { - c->Post(base::BindOnce( - [](StackRunningData stack_running_data) { - bluetooth::shim::Stack::GetInstance() - ->GetStackManager() - ->GetInstance() - ->IsStackRunning(stack_running_data); - }, - stack_running_data)); - } -} - -TEST_F(MainShimStackDumpsysWithClientsTest, all_clients_check_stack_running_with_iterations) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Run on mainloop: Stack is running:{}", - (is_stack_running) ? 'T' : 'F'); - }, - }; - - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - for (int i = 0; i < 2; i++) { - log::info("Iteration:{}", i); - for (auto& c : client_group_.clients_) { - c->Post(base::BindOnce( - [](StackRunningData stack_running_data) { - bluetooth::shim::Stack::GetInstance() - ->GetStackManager() - ->GetInstance() - ->IsStackRunning(stack_running_data); - }, - stack_running_data)); - } - } -} - -TEST_F(MainShimStackDumpsysWithClientsTest, dumpsys_single_client) { - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - const int fd = 1; - client_group_.clients_[0]->Post( - base::BindOnce([](int fd) { bluetooth::shim::Dump(fd, nullptr); }, fd)); -} - -TEST_F(MainShimStackDumpsysWithClientsTest, dumpsys_single_client_with_running_check) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Stack is running:{}", (is_stack_running) ? 'T' : 'F'); - }, - }; - - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - const int fd = 1; - client_group_.clients_[0]->Post(base::BindOnce( - [](StackRunningData stack_running_data) { - bluetooth::shim::Stack::GetInstance() - ->GetStackManager() - ->GetInstance() - ->IsStackRunning(stack_running_data); - }, - stack_running_data)); - client_group_.clients_[0]->Post( - base::BindOnce([](int fd) { bluetooth::shim::Dump(fd, nullptr); }, fd)); -} - -TEST_F(MainShimStackDumpsysWithClientsTest, dumpsys_many_clients) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Stack is running:{}", (is_stack_running) ? 'T' : 'F'); - }, - }; - - const int fd = 1; - for (auto& c : client_group_.clients_) { - c->Post(base::BindOnce([](int fd) { bluetooth::shim::Dump(fd, nullptr); }, fd)); - } -} diff --git a/system/main/test/main_shim_stack_lifecycle_test.cc b/system/main/test/main_shim_stack_lifecycle_test.cc deleted file mode 100644 index 17205742180..00000000000 --- a/system/main/test/main_shim_stack_lifecycle_test.cc +++ /dev/null @@ -1,619 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "common/strings.h" -#include "gd/module_jniloop.h" -#include "gd/module_mainloop.h" -#include "main/shim/stack.h" -#include "module.h" -#include "os/thread.h" -#include "stack/include/main_thread.h" -#include "test/mock/mock_main_shim_entry.h" - -using ::testing::_; - -using namespace bluetooth; -using namespace testing; - -namespace { -constexpr int kSyncMainLoopTimeoutMs = 3000; -constexpr int kWaitUntilHandlerStoppedMs = 2000; -constexpr size_t kNumTestClients = 3; -constexpr size_t kNumTestModules = 3; -constexpr int kNumIters = 100; -constexpr int kAbruptStackShutdownIter = kNumIters * 3 / 4; -constexpr char kTestStackThreadName[] = "test_stack_thread"; -constexpr char kTestDataTag[] = "This is a test"; - -inline void maybe_yield() { - if (std::rand() & 1) { - std::this_thread::yield(); - } -} - -constexpr size_t kTagLength = 48 + sizeof(' ') + sizeof(' '); -inline void log_tag(std::string tag) { - std::string prepend(kTagLength / 2 - tag.size() / 2, '='); - std::string append(kTagLength / 2 - tag.size() / 2, '='); - log::info("{} {} {}", prepend, tag, append); -} - -class MainThread { -public: - MainThread() { main_thread_start_up(); } - - ~MainThread() { - sync_main_handler(); - main_thread_shut_down(); - } - -private: - void sync_main_handler() { - std::promise promise = std::promise(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } -}; - -class TestStackManager { -public: - TestStackManager() { - // Start is executed by the test after each test adds the default - // or their own modules - } - - ~TestStackManager() { - log::debug("Deleting stack manager"); - Stop(); - } - - TestStackManager(const TestStackManager&) = delete; - - template - void AddModule() { - modules_.add(); - } - - void Start() { - if (stack_started_) { - return; - } - log::info("Started stack manager"); - stack_started_ = true; - bluetooth::os::Thread* stack_thread = new bluetooth::os::Thread( - kTestStackThreadName, bluetooth::os::Thread::Priority::NORMAL); - bluetooth::shim::Stack::GetInstance()->StartModuleStack(&modules_, stack_thread); - } - - void Stop() { - if (!stack_started_) { - return; - } - stack_started_ = false; - bluetooth::shim::Stack::GetInstance()->Stop(); - } - - // NOTE: Stack manager *must* be active else method returns nullptr - // if stack manager has not started or shutdown - template - static T* GetUnsafeModule() { - return bluetooth::shim::Stack::GetInstance()->GetStackManager()->GetInstance(); - } - - size_t NumModules() const { return modules_.NumModules(); } - -private: - bluetooth::ModuleList modules_; - bool stack_started_{false}; -}; - -// Data returned via callback from a stack managed module -struct TestCallbackData { - int iter; - std::string tag; -}; - -// Data sent to a stack managed module via a module API -struct TestData { - int iter; - std::string tag; - std::function callback; -}; - -class TestStackModuleBase : public bluetooth::Module, public ModuleMainloop, public ModuleJniloop { -public: - TestStackModuleBase(const TestStackModuleBase&) = delete; - TestStackModuleBase& operator=(const TestStackModuleBase&) = delete; - - virtual ~TestStackModuleBase() {} - static const ModuleFactory Factory; - - virtual void TestMethod(TestData test_data) const { - log::info("Test base class iter:{} tag:{}", test_data.iter, test_data.tag); - } - -protected: - void ListDependencies(ModuleList* /*list*/) const override {} - void Start() override { log::error("Started TestStackModuleBase"); } - void Stop() override { log::error("Stopped TestStackModuleBase"); } - std::string ToString() const override { return std::string("TestFunction"); } - - TestStackModuleBase() = default; -}; - -class TestStackModule1 : public TestStackModuleBase { -public: - TestStackModule1(const TestStackModule1&) = delete; - TestStackModule1& operator=(const TestStackModule1&) = delete; - virtual ~TestStackModule1() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr impl_; - TestStackModule1(); -}; - -struct TestStackModule1::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackModule1::TestStackModule1() : TestStackModuleBase() { impl_ = std::make_shared(); } - -void TestStackModule1::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackModule2 : public TestStackModuleBase { -public: - TestStackModule2(const TestStackModule2&) = delete; - TestStackModule2& operator=(const TestStackModule2&) = delete; - virtual ~TestStackModule2() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr impl_; - TestStackModule2(); -}; - -struct TestStackModule2::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackModule2::TestStackModule2() : TestStackModuleBase() { impl_ = std::make_shared(); } - -void TestStackModule2::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackModule3 : public TestStackModuleBase { -public: - TestStackModule3(const TestStackModule3&) = delete; - TestStackModule3& operator=(const TestStackModule3&) = delete; - virtual ~TestStackModule3() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr impl_; - TestStackModule3(); -}; - -struct TestStackModule3::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackModule3::TestStackModule3() : TestStackModuleBase() { impl_ = std::make_shared(); } - -void TestStackModule3::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackModule4 : public TestStackModuleBase { -public: - TestStackModule4(const TestStackModule4&) = delete; - TestStackModule4& operator=(const TestStackModule3&) = delete; - virtual ~TestStackModule4() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override { - log::info("mod:{} iter:{} tag:{}", __func__, test_data.iter, test_data.tag); - } - -private: - struct impl; - std::shared_ptr impl_; - TestStackModule4() : TestStackModuleBase() {} -}; - -struct TestStackModule4::impl : public ModuleMainloop, public ModuleJniloop {}; - -} // namespace - -const ModuleFactory TestStackModuleBase::Factory = - ModuleFactory([]() { return new TestStackModuleBase(); }); - -const ModuleFactory TestStackModule1::Factory = - ModuleFactory([]() { return new TestStackModule1(); }); -const ModuleFactory TestStackModule2::Factory = - ModuleFactory([]() { return new TestStackModule2(); }); -const ModuleFactory TestStackModule3::Factory = - ModuleFactory([]() { return new TestStackModule3(); }); -const ModuleFactory TestStackModule4::Factory = - ModuleFactory([]() { return new TestStackModule4(); }); - -class StackWithMainThreadUnitTest : public ::testing::Test { -protected: - void SetUp() override { main_thread_ = std::make_unique(); } - void TearDown() override { main_thread_.reset(); } - -private: - std::unique_ptr main_thread_; -}; - -class StackLifecycleUnitTest : public StackWithMainThreadUnitTest { -public: - std::shared_ptr StackManager() const { return stack_manager_; } - -protected: - void SetUp() override { - StackWithMainThreadUnitTest::SetUp(); - stack_manager_ = std::make_shared(); - } - - void TearDown() override { - stack_manager_.reset(); - StackWithMainThreadUnitTest::TearDown(); - } - -private: - std::shared_ptr stack_manager_; -}; - -TEST_F(StackLifecycleUnitTest, no_modules_in_stack) { ASSERT_EQ(0U, StackManager()->NumModules()); } - -class StackLifecycleWithDefaultModulesUnitTest : public StackLifecycleUnitTest { -protected: - void SetUp() override { - StackLifecycleUnitTest::SetUp(); - StackManager()->AddModule(); - StackManager()->AddModule(); - StackManager()->AddModule(); - StackManager()->Start(); - ASSERT_EQ(3U, StackManager()->NumModules()); - } - - void TearDown() override { StackLifecycleUnitTest::TearDown(); } -}; - -struct CallablePostCnt { - size_t success{0}; - size_t misses{0}; - CallablePostCnt operator+=(const CallablePostCnt& post_cnt) { - return CallablePostCnt({success += post_cnt.success, misses += post_cnt.misses}); - } -}; - -// Provide a client user of the stack manager module services -class Client { -public: - Client(int id) : id_(id) {} - Client(const Client&) = default; - virtual ~Client() = default; - - // Start up the client a thread and handler - void Start() { - log::info("Started client {}", id_); - thread_ = new os::Thread(common::StringFormat("ClientThread%d", id_), - os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - handler_->Post(common::BindOnce([](int id) { log::info("Started client {}", id); }, id_)); - } - - // Ensure all the client handlers are running - void Await() { - std::promise promise; - std::future future = promise.get_future(); - handler_->Post(base::BindOnce([](std::promise promise) { promise.set_value(); }, - std::move(promise))); - future.wait(); - } - - // Post a work task on behalf of this client - void Post(common::OnceClosure closure) { - if (quiesced_) { - post_cnt_.misses++; - maybe_yield(); - } else { - post_cnt_.success++; - handler_->Post(std::move(closure)); - maybe_yield(); - } - } - - // Safely prevent new work tasks from being posted - void Quiesce() { - if (quiesced_) { - return; - } - quiesced_ = true; - std::promise promise = std::promise(); - std::future future = promise.get_future(); - handler_->Post(common::BindOnce([](std::promise promise) { promise.set_value(); }, - std::move(promise))); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } - - // Stops the client and associated resources - void Stop() { - if (!quiesced_) { - Quiesce(); - } - handler_->Clear(); - handler_->WaitUntilStopped(std::chrono::milliseconds(kWaitUntilHandlerStoppedMs)); - delete handler_; - delete thread_; - } - - int Id() const { return id_; } - - CallablePostCnt GetCallablePostCnt() const { return post_cnt_; } - - std::string Name() const { return common::StringFormat("%s%d", __func__, id_); } - -private: - int id_{0}; - CallablePostCnt post_cnt_{}; - bool quiesced_{false}; - os::Handler* handler_{nullptr}; - os::Thread* thread_{nullptr}; -}; - -// Convenience object to handle multiple clients with logging -class ClientGroup { -public: - ClientGroup() {} - - void Start() { - for (auto& c : clients_) { - c->Start(); - } - log_tag("STARTING"); - } - - void Await() { - for (auto& c : clients_) { - c->Await(); - } - log_tag("STARTED"); - } - - void Quiesce() { - log_tag("QUIESCING"); - for (auto& c : clients_) { - c->Quiesce(); - } - log_tag("QUIESCED"); - } - - void Stop() { - for (auto& c : clients_) { - c->Stop(); - } - log_tag("STOPPED"); - } - - void Dump() const { - for (auto& c : clients_) { - log::info("Callable post cnt client_id:{} success:{} misses:{}", c->Id(), - c->GetCallablePostCnt().success, c->GetCallablePostCnt().misses); - } - } - - CallablePostCnt GetCallablePostCnt() const { - CallablePostCnt post_cnt{}; - for (auto& c : clients_) { - post_cnt += c->GetCallablePostCnt(); - } - return post_cnt; - } - - size_t NumClients() const { return kNumTestClients; } - - std::unique_ptr clients_[kNumTestClients] = { - std::make_unique(1), std::make_unique(2), std::make_unique(3)}; -}; - -TEST_F(StackLifecycleWithDefaultModulesUnitTest, clients_start) { - ClientGroup client_group; - - client_group.Start(); - client_group.Await(); - - // Clients are operational - - client_group.Quiesce(); - client_group.Stop(); -} - -TEST_F(StackLifecycleWithDefaultModulesUnitTest, client_using_stack_manager) { - ClientGroup client_group; - client_group.Start(); - client_group.Await(); - - for (int i = 0; i < kNumIters; i++) { - for (auto& c : client_group.clients_) { - c->Post(base::BindOnce( - [](int /*id*/, int iter, std::shared_ptr stack_manager) { - stack_manager->GetUnsafeModule()->TestMethod({ - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }); - }, - c->Id(), i, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, std::shared_ptr stack_manager) { - stack_manager->GetUnsafeModule()->TestMethod({ - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }); - }, - c->Id(), i, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, std::shared_ptr stack_manager) { - stack_manager->GetUnsafeModule()->TestMethod({ - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }); - }, - c->Id(), i, StackManager())); - } - } - - client_group.Quiesce(); - client_group.Stop(); - client_group.Dump(); - - ASSERT_EQ(client_group.NumClients() * kNumIters * kNumTestModules, - client_group.GetCallablePostCnt().success + client_group.GetCallablePostCnt().misses); -} - -TEST_F(StackLifecycleWithDefaultModulesUnitTest, client_using_stack_manager_when_shutdown) { - struct Counters { - struct { - std::atomic_size_t cnt{0}; - } up, down; - } counters; - - ClientGroup client_group; - client_group.Start(); - client_group.Await(); - - for (int i = 0; i < kNumIters; i++) { - for (auto& c : client_group.clients_) { - c->Post(base::BindOnce( - [](int /*id*/, int iter, Counters* counters, - std::shared_ptr /*stack_manager*/) { - TestData test_data = { - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }; - if (bluetooth::shim::Stack::GetInstance()->CallOnModule( - [test_data](TestStackModule1* mod) { mod->TestMethod(test_data); })) { - counters->up.cnt++; - } else { - counters->down.cnt++; - } - }, - c->Id(), i, &counters, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, Counters* counters, - std::shared_ptr /*stack_manager*/) { - TestData test_data = { - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }; - if (bluetooth::shim::Stack::GetInstance()->CallOnModule( - [test_data](TestStackModule2* mod) { mod->TestMethod(test_data); })) { - counters->up.cnt++; - } else { - counters->down.cnt++; - } - }, - c->Id(), i, &counters, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, Counters* counters, - std::shared_ptr /*stack_manager*/) { - TestData test_data = { - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }; - if (bluetooth::shim::Stack::GetInstance()->CallOnModule( - [test_data](TestStackModule3* mod) { mod->TestMethod(test_data); })) { - counters->up.cnt++; - } else { - counters->down.cnt++; - } - }, - c->Id(), i, &counters, StackManager())); - } - // Abruptly shutdown stack at some point through the iterations - if (i == kAbruptStackShutdownIter) { - log_tag("SHUTTING DOWN STACK"); - StackManager()->Stop(); - } - } - - client_group.Quiesce(); - client_group.Stop(); - log::info("Execution stack availability counters up:{} down:{}", counters.up.cnt, - counters.down.cnt); - - ASSERT_EQ(client_group.NumClients() * kNumIters * kNumTestModules, - client_group.GetCallablePostCnt().success + client_group.GetCallablePostCnt().misses); -} diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 25cf3c5a5db..cb987debfc1 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -813,7 +813,6 @@ cc_test { "libbase", "libbluetooth-dumpsys", "libbluetooth-for-tests", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/stack/test/fuzzers/Android.bp b/system/stack/test/fuzzers/Android.bp index 8d146834d61..3c74de632df 100644 --- a/system/stack/test/fuzzers/Android.bp +++ b/system/stack/test/fuzzers/Android.bp @@ -40,7 +40,6 @@ cc_defaults { "bluetooth_flags_c_lib", "libFraunhoferAAC", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp index 9e0a234742c..846f9ec4ccc 100644 --- a/system/test/headless/Android.bp +++ b/system/test/headless/Android.bp @@ -82,7 +82,6 @@ cc_binary { "libFraunhoferAAC", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp index 4ce6367d5b4..09e8fda4135 100644 --- a/system/test/suite/Android.bp +++ b/system/test/suite/Android.bp @@ -121,7 +121,6 @@ cc_test { ], static_libs: [ "bluetooth_flags_c_lib_for_test", - "libbluetooth-gdx", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_hci_pdl", -- GitLab From 9663f3e1a71dbdcc4d9a346c1177b9db1e6affb5 Mon Sep 17 00:00:00 2001 From: Bhakthavatsala Raghavendra Date: Tue, 29 Oct 2024 17:48:30 +0000 Subject: [PATCH 475/875] Flag to trigger security procedure on incoming access req Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.trigger_sec_proc_on_inc_access_req Bug: 376278485 Bug: 315241296 Change-Id: Id70df5af118c1a3b17a90114900f7d62aefef602 --- flags/pairing.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig index 66ab03984c2..b3e2095e675 100644 --- a/flags/pairing.aconfig +++ b/flags/pairing.aconfig @@ -180,3 +180,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "trigger_sec_proc_on_inc_access_req" + namespace: "bluetooth" + description: "Trigger security procedure as acceptor as needed" + bug: "376278485" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From b22e0087fb5ee9f506a38512f23a461f60c6c1f6 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Tue, 29 Oct 2024 18:00:48 +0000 Subject: [PATCH 476/875] Flag for using LE as default GATT transport Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.default_gatt_transport Bug: 376276742 Bug: 315241296 Change-Id: Ide5c93935d1802c470868e0dc854421737df7bff --- flags/Android.bp | 1 + flags/BUILD.gn | 1 + flags/gatt.aconfig | 12 ++++++++++++ 3 files changed, 14 insertions(+) create mode 100644 flags/gatt.aconfig diff --git a/flags/Android.bp b/flags/Android.bp index f08db2fb78c..d5f0c1f3374 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -27,6 +27,7 @@ aconfig_declarations { "dis.aconfig", "framework.aconfig", "gap.aconfig", + "gatt.aconfig", "hal.aconfig", "hap.aconfig", "hci.aconfig", diff --git a/flags/BUILD.gn b/flags/BUILD.gn index 97ad76af503..ba233689acc 100644 --- a/flags/BUILD.gn +++ b/flags/BUILD.gn @@ -18,6 +18,7 @@ aconfig("bluetooth_flags_c_lib") { "dis.aconfig", "framework.aconfig", "gap.aconfig", + "gatt.aconfig", "hal.aconfig", "hap.aconfig", "hci.aconfig", diff --git a/flags/gatt.aconfig b/flags/gatt.aconfig new file mode 100644 index 00000000000..99b03052911 --- /dev/null +++ b/flags/gatt.aconfig @@ -0,0 +1,12 @@ +package: "com.android.bluetooth.flags" +container: "com.android.btservices" + +flag { + name: "default_gatt_transport" + namespace: "bluetooth" + description: "Use LE as the default transport for GATT connections" + bug: "376276742" + metadata { + purpose: PURPOSE_BUGFIX + } +} -- GitLab From bd318db3cdd7622ea26724cbcc0d0652838f88fd Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Mon, 28 Oct 2024 14:35:18 -0700 Subject: [PATCH 477/875] stack::avct cleanup Remove link and browse functions Bug: 375741222 Test: m . Flag: EXEMPT, Code cleanup Change-Id: I56759d2e5aec7fcfdaa0ad017113d3c75b34dd86 --- system/stack/avct/avct_api.cc | 48 ++++++++++++++++------------------- system/stack/avct/avct_lcb.cc | 25 +++++++++++++----- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index d4a6aab45eb..7e1e7a99ad0 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -197,27 +197,25 @@ uint16_t AVCT_CreateConn(uint8_t* p_handle, tAVCT_CC* p_cc, const RawAddress& pe * ******************************************************************************/ uint16_t AVCT_RemoveConn(uint8_t handle) { - uint16_t result = AVCT_SUCCESS; - tAVCT_CCB* p_ccb; - log::verbose("AVCT_RemoveConn"); /* map handle to ccb */ - p_ccb = avct_ccb_by_idx(handle); - if (p_ccb == NULL) { - result = AVCT_BAD_HANDLE; + tAVCT_CCB* p_ccb = avct_ccb_by_idx(handle); + if (p_ccb == nullptr) { + return AVCT_BAD_HANDLE; } + /* if connection not bound to lcb, dealloc */ - else if (p_ccb->p_lcb == NULL) { + if (p_ccb->p_lcb == nullptr) { avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL); - } - /* send unbind event to lcb */ - else { - tAVCT_LCB_EVT avct_lcb_evt; - avct_lcb_evt.p_ccb = p_ccb; + } else { + /* send unbind event to lcb */ + tAVCT_LCB_EVT avct_lcb_evt = { + .p_ccb = p_ccb, + }; avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt); } - return result; + return AVCT_SUCCESS; } /******************************************************************************* @@ -301,24 +299,22 @@ uint16_t AVCT_CreateBrowse(uint8_t handle, tAVCT_ROLE role) { * ******************************************************************************/ uint16_t AVCT_RemoveBrowse(uint8_t handle) { - uint16_t result = AVCT_SUCCESS; - tAVCT_CCB* p_ccb; - log::verbose("AVCT_RemoveBrowse"); /* map handle to ccb */ - p_ccb = avct_ccb_by_idx(handle); - if (p_ccb == NULL) { - result = AVCT_BAD_HANDLE; - } else if (p_ccb->p_bcb != NULL) - /* send unbind event to bcb */ - { - tAVCT_LCB_EVT avct_lcb_evt; - avct_lcb_evt.p_ccb = p_ccb; - avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt); + tAVCT_CCB* p_ccb = avct_ccb_by_idx(handle); + if (p_ccb == nullptr) { + return AVCT_BAD_HANDLE; } - return result; + if (p_ccb->p_bcb != nullptr) { + /* send unbind event to bcb */ + tAVCT_LCB_EVT avct_lcb_evt = { + .p_ccb = p_ccb, + }; + avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt); + } + return AVCT_SUCCESS; } /******************************************************************************* diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc index 26d4a731605..ac4519c11c0 100644 --- a/system/stack/avct/avct_lcb.cc +++ b/system/stack/avct/avct_lcb.cc @@ -90,10 +90,23 @@ typedef void (*tAVCT_LCB_ACTION)(tAVCT_LCB* p_ccb, tAVCT_LCB_EVT* p_data); /* action function list */ const tAVCT_LCB_ACTION avct_lcb_action[] = { - avct_lcb_chnl_open, avct_lcb_chnl_disc, avct_lcb_send_msg, avct_lcb_open_ind, - avct_lcb_open_fail, avct_lcb_close_ind, avct_lcb_close_cfm, avct_lcb_msg_ind, - avct_lcb_cong_ind, avct_lcb_bind_conn, avct_lcb_bind_fail, avct_lcb_unbind_disc, - avct_lcb_chk_disc, avct_lcb_discard_msg, avct_lcb_dealloc, avct_lcb_free_msg_ind}; + avct_lcb_chnl_open, // AVCT_LCB_CHNL_OPEN + avct_lcb_chnl_disc, // AVCT_LCB_CHNL_DISC + avct_lcb_send_msg, // AVCT_LCB_SEND_MSG + avct_lcb_open_ind, // AVCT_LCB_OPEN_IND + avct_lcb_open_fail, // AVCT_LCB_OPEN_FAIL + avct_lcb_close_ind, // AVCT_LCB_CLOSE_IND + avct_lcb_close_cfm, // AVCT_LCB_CLOSE_CFM + avct_lcb_msg_ind, // AVCT_LCB_MSG_IND + avct_lcb_cong_ind, // AVCT_LCB_CONG_IND + avct_lcb_bind_conn, // AVCT_LCB_BIND_CONN + avct_lcb_bind_fail, // AVCT_LCB_BIND_FAIL + avct_lcb_unbind_disc, // AVCT_LCB_UNBIND_DISC + avct_lcb_chk_disc, // AVCT_LCB_CHK_DISC + avct_lcb_discard_msg, // AVCT_LCB_DISCARD_MSG + avct_lcb_dealloc, // AVCT_LCB_DEALLOC + avct_lcb_free_msg_ind // AVCT_LCB_FREE_MSG_IND +}; /* state table information */ #define AVCT_LCB_ACTIONS 2 /* number of actions */ @@ -341,8 +354,8 @@ tAVCT_LCB* avct_lcb_by_lcid(uint16_t lcid) { if (i == AVCT_NUM_LINKS) { /* out of lcbs */ - p_lcb = NULL; - log::warn("No lcb for lcid {:x}", lcid); + p_lcb = nullptr; + log::warn("No lcb for lcid 0x{:04x}", lcid); } return p_lcb; -- GitLab From 663d3b5e41a26dfc221167e89792c4d1caafbd84 Mon Sep 17 00:00:00 2001 From: Katherine Lai Date: Tue, 29 Oct 2024 21:13:34 +0000 Subject: [PATCH 478/875] gd: Move mgmt files from gd/hal to gd/os Since mgmt provides a way to interact with linux kernel, move related files to gd/os. Also spell out Mgmt fully to Management and create singleton methods. Bug: 372926952 Test: m -j Flag: Exempt, no change to default behavior Change-Id: Ia077af553bcbd15026a275140e4bc86bfbb03a11 --- system/gd/Android.bp | 6 ++--- system/gd/hal/Android.bp | 14 ---------- system/gd/hal/BUILD.gn | 2 -- system/gd/hal/hci_hal_android.cc | 6 +++-- system/gd/hal/hci_hal_host.cc | 6 +++-- system/gd/os/Android.bp | 14 ++++++++++ system/gd/os/BUILD.gn | 1 + system/gd/{hal => os/linux_generic}/mgmt.cc | 10 +++---- system/gd/{hal => os}/mgmt.h | 29 ++++++++++++++++++--- system/gd/{hal => os}/mgmt_stub.cc | 8 +++--- 10 files changed, 60 insertions(+), 36 deletions(-) rename system/gd/{hal => os/linux_generic}/mgmt.cc (96%) rename system/gd/{hal => os}/mgmt.h (76%) rename system/gd/{hal => os}/mgmt_stub.cc (88%) diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 579aae7d441..5484cd0ee5d 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -58,13 +58,13 @@ mgmt_cc_defaults { soong_config_variables: { vertical: { android_desktop: { - srcs: [":BluetoothHalSources_mgmt"], + srcs: [":BluetoothOsSources_mgmt_linux"], }, android_default: { - srcs: [":BluetoothHalSources_mgmt_stub"], + srcs: [":BluetoothOsSources_mgmt"], }, conditions_default: { - srcs: [":BluetoothHalSources_mgmt_stub"], + srcs: [":BluetoothOsSources_mgmt"], }, }, }, diff --git a/system/gd/hal/Android.bp b/system/gd/hal/Android.bp index 1086c318735..91e1573c0e8 100644 --- a/system/gd/hal/Android.bp +++ b/system/gd/hal/Android.bp @@ -51,20 +51,6 @@ filegroup { ], } -filegroup { - name: "BluetoothHalSources_mgmt_stub", - srcs: [ - "mgmt_stub.cc", - ], -} - -filegroup { - name: "BluetoothHalSources_mgmt", - srcs: [ - "mgmt.cc", - ], -} - filegroup { name: "BluetoothHalSources_ranging_android", srcs: [ diff --git a/system/gd/hal/BUILD.gn b/system/gd/hal/BUILD.gn index f0a2f9d159b..46be6e9d8aa 100644 --- a/system/gd/hal/BUILD.gn +++ b/system/gd/hal/BUILD.gn @@ -34,12 +34,10 @@ source_set("BluetoothHalSources_hci_host") { if (use.floss_rootcanal) { sources = [ "hci_hal_host_rootcanal.cc", - "mgmt.cc", ] } else { sources = [ "hci_hal_host.cc", - "mgmt.cc", ] } diff --git a/system/gd/hal/hci_hal_android.cc b/system/gd/hal/hci_hal_android.cc index 3e66f981825..51bc789cc8d 100644 --- a/system/gd/hal/hci_hal_android.cc +++ b/system/gd/hal/hci_hal_android.cc @@ -24,8 +24,8 @@ #include "hal/hci_backend.h" #include "hal/hci_hal.h" #include "hal/link_clocker.h" -#include "hal/mgmt.h" #include "hal/snoop_logger.h" +#include "os/mgmt.h" namespace bluetooth::hal { @@ -158,7 +158,9 @@ public: backend_->sendIsoData(packet); } - uint16_t getMsftOpcode() override { return Mgmt().get_vs_opcode(MGMT_VS_OPCODE_MSFT); } + uint16_t getMsftOpcode() override { + return os::Management::getInstance().getVendorSpecificCode(MGMT_VS_OPCODE_MSFT); + } protected: void ListDependencies(ModuleList* list) const override { diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc index 79e1cabd859..e00554c9236 100644 --- a/system/gd/hal/hci_hal_host.cc +++ b/system/gd/hal/hci_hal_host.cc @@ -34,9 +34,9 @@ #include "hal/hci_hal.h" #include "hal/link_clocker.h" -#include "hal/mgmt.h" #include "hal/snoop_logger.h" #include "metrics/counter_metrics.h" +#include "os/mgmt.h" #include "os/reactor.h" #include "os/thread.h" @@ -312,7 +312,9 @@ public: write_to_fd(packet); } - uint16_t getMsftOpcode() override { return Mgmt().get_vs_opcode(MGMT_VS_OPCODE_MSFT); } + uint16_t getMsftOpcode() override { + return os::Management::getInstance().getVendorSpecificCode(MGMT_VS_OPCODE_MSFT); + } void markControllerBroken() override { std::lock_guard lock(api_mutex_); diff --git a/system/gd/os/Android.bp b/system/gd/os/Android.bp index a71697336ab..1f4f4b44914 100644 --- a/system/gd/os/Android.bp +++ b/system/gd/os/Android.bp @@ -126,3 +126,17 @@ filegroup { "system_properties_common.cc", ], } + +filegroup { + name: "BluetoothOsSources_mgmt", + srcs: [ + "mgmt_stub.cc", + ], +} + +filegroup { + name: "BluetoothOsSources_mgmt_linux", + srcs: [ + "linux_generic/mgmt.cc", + ], +} diff --git a/system/gd/os/BUILD.gn b/system/gd/os/BUILD.gn index 6824184ad01..7bd3c7ce2b8 100644 --- a/system/gd/os/BUILD.gn +++ b/system/gd/os/BUILD.gn @@ -53,6 +53,7 @@ source_set("BluetoothOsSources_linux_generic") { "handler.cc", "linux_generic/alarm.cc", "linux_generic/files.cc", + "linux_generic/mgmt.cc", "linux_generic/reactive_semaphore.cc", "linux_generic/reactor.cc", "linux_generic/repeating_alarm.cc", diff --git a/system/gd/hal/mgmt.cc b/system/gd/os/linux_generic/mgmt.cc similarity index 96% rename from system/gd/hal/mgmt.cc rename to system/gd/os/linux_generic/mgmt.cc index c5de32c3f78..8f2fbd0a17e 100644 --- a/system/gd/hal/mgmt.cc +++ b/system/gd/os/linux_generic/mgmt.cc @@ -21,7 +21,7 @@ * This file will be replaced such that it is not optimized for now. */ -#include "hal/mgmt.h" +#include "os/mgmt.h" #include #include @@ -33,7 +33,7 @@ extern int GetAdapterIndex(); namespace bluetooth { -namespace hal { +namespace os { #define RETRY_ON_INTR(fn) \ do { \ @@ -80,7 +80,7 @@ static int btsocket_open_mgmt() { * or failures in writing/reading the MGMT socket, the return opcode would * be HCI_OP_NOP (0x0000). */ -uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) { +uint16_t Management::getVendorSpecificCode(uint16_t vendor_specification) { int hci = GetAdapterIndex(); int fd = btsocket_open_mgmt(); uint16_t ret_opcode = HCI_OP_NOP; @@ -140,7 +140,7 @@ uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) { log::error("Failed to read mgmt socket: {}", -errno); close(fd); return ret_opcode; - } else if (ret == 0) { // unlikely to happen, just a safeguard. + } else if (ret == 0) { // unlikely to happen, just a safeguard. log::error("Failed to read mgmt socket: EOF"); close(fd); return ret_opcode; @@ -173,5 +173,5 @@ uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) { return ret_opcode; } -} // namespace hal +} // namespace os } // namespace bluetooth diff --git a/system/gd/hal/mgmt.h b/system/gd/os/mgmt.h similarity index 76% rename from system/gd/hal/mgmt.h rename to system/gd/os/mgmt.h index 35b22ccdc00..3b039b6ad8a 100644 --- a/system/gd/hal/mgmt.h +++ b/system/gd/os/mgmt.h @@ -21,7 +21,7 @@ #include namespace bluetooth { -namespace hal { +namespace os { #define HCI_OP_NOP 0x0000 @@ -56,10 +56,31 @@ struct mgmt_rp_get_vs_opcode { #define MGMT_POLL_TIMEOUT_MS 2000 // This class provides an interface to interact with the kernel. -class Mgmt { +class Management { public: - uint16_t get_vs_opcode(uint16_t vendor_specification); + ~Management() = default; + + /** + * Get the instance of singleton + * + * @return Management& + */ + static Management& getInstance() { + static Management mgmt; + return mgmt; + } + + uint16_t getVendorSpecificCode(uint16_t vendor_specification); + +protected: + // Singleton + Management() = default; + +private: + // delete copy constructor for singleton + Management(Management const&) = delete; + Management& operator=(Management const&) = delete; }; -} // namespace hal +} // namespace os } // namespace bluetooth diff --git a/system/gd/hal/mgmt_stub.cc b/system/gd/os/mgmt_stub.cc similarity index 88% rename from system/gd/hal/mgmt_stub.cc rename to system/gd/os/mgmt_stub.cc index 19a3a968de2..308838818b8 100644 --- a/system/gd/hal/mgmt_stub.cc +++ b/system/gd/os/mgmt_stub.cc @@ -22,15 +22,15 @@ #include -#include "hal/mgmt.h" +#include "os/mgmt.h" namespace bluetooth { -namespace hal { +namespace os { -uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) { +uint16_t Management::getVendorSpecificCode(uint16_t vendor_specification) { log::debug("Using stub for vendor opcode 0x{:04x}", vendor_specification); return 0; } -} // namespace hal +} // namespace os } // namespace bluetooth -- GitLab From dcaace5e6f5654def071654de8ee75ba613d7df7 Mon Sep 17 00:00:00 2001 From: Bhakthavatsala Raghavendra Date: Fri, 25 Oct 2024 22:29:01 +0000 Subject: [PATCH 479/875] Remove suppress lint from Socket Apis Remove suppress lint from socket APIs and related changes Bug: 375832990 Flag: EXEMPT, Refactor Test: atest BumbleBluetoothTests:android.bluetooth.RfcommTest Test: atest BumbleBluetoothTests:android.bluetooth.DckL2capTest Change-Id: I48081f652a96f828edd7b7d016824e8d0abafd05 --- framework/api/current.txt | 8 +- .../android/bluetooth/BluetoothDevice.java | 48 ++------ .../bluetooth/BluetoothServerSocket.java | 10 +- .../android/bluetooth/BluetoothSocket.java | 110 ++++++++++++++---- 4 files changed, 109 insertions(+), 67 deletions(-) diff --git a/framework/api/current.txt b/framework/api/current.txt index c92d72252c4..4347504e24e 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -527,10 +527,10 @@ package android.bluetooth { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; + method @NonNull public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException; + method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; + method @NonNull public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException; + method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; method public int describeContents(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean fetchUuidsWithSdp(); method public String getAddress(); diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 9bd547d33a9..a76704bf034 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -1361,8 +1361,7 @@ public final class BluetoothDevice implements Parcelable, Attributable { * * @hide */ - @SystemApi - public static final int ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT = 0; + @SystemApi public static final int ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT = 0; /** * Indicates all profiles active audio device policy is applied to this device @@ -2739,15 +2738,12 @@ public final class BluetoothDevice implements Parcelable, Attributable { */ @UnsupportedAppUsage @RequiresLegacyBluetoothPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public BluetoothSocket createRfcommSocket(int channel) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } - return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, true, true, this, channel, null); + return new BluetoothSocket(this, BluetoothSocket.TYPE_RFCOMM, true, true, channel, null); } /** @@ -2775,11 +2771,8 @@ public final class BluetoothDevice implements Parcelable, Attributable { * @hide */ @RequiresLegacyBluetoothPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public BluetoothSocket createL2capSocket(int channel) throws IOException { - return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, true, true, this, channel, null); + return new BluetoothSocket(this, BluetoothSocket.TYPE_L2CAP, true, true, channel, null); } /** @@ -2800,11 +2793,8 @@ public final class BluetoothDevice implements Parcelable, Attributable { * @hide */ @RequiresLegacyBluetoothPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException { - return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, false, false, this, channel, null); + return new BluetoothSocket(this, BluetoothSocket.TYPE_L2CAP, false, false, channel, null); } /** @@ -2838,9 +2828,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * permissions */ @RequiresLegacyBluetoothPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); @@ -2848,7 +2835,7 @@ public final class BluetoothDevice implements Parcelable, Attributable { } return new BluetoothSocket( - BluetoothSocket.TYPE_RFCOMM, true, true, this, -1, new ParcelUuid(uuid)); + this, BluetoothSocket.TYPE_RFCOMM, true, true, -1, new ParcelUuid(uuid)); } /** @@ -2881,16 +2868,13 @@ public final class BluetoothDevice implements Parcelable, Attributable { * permissions */ @RequiresLegacyBluetoothPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } return new BluetoothSocket( - BluetoothSocket.TYPE_RFCOMM, false, false, this, -1, new ParcelUuid(uuid)); + this, BluetoothSocket.TYPE_RFCOMM, false, false, -1, new ParcelUuid(uuid)); } /** @@ -2908,15 +2892,12 @@ public final class BluetoothDevice implements Parcelable, Attributable { publicAlternatives = "Use " + "{@link #createInsecureRfcommSocketToServiceRecord} instead.") @RequiresLegacyBluetoothAdminPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } - return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, false, false, this, port, null); + return new BluetoothSocket(this, BluetoothSocket.TYPE_RFCOMM, false, false, port, null); } /** @@ -2930,15 +2911,12 @@ public final class BluetoothDevice implements Parcelable, Attributable { */ @UnsupportedAppUsage @RequiresLegacyBluetoothAdminPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public BluetoothSocket createScoSocket() throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } - return new BluetoothSocket(BluetoothSocket.TYPE_SCO, true, true, this, -1, null); + return new BluetoothSocket(this, BluetoothSocket.TYPE_SCO, true, true, -1, null); } /** @@ -3142,16 +3120,13 @@ public final class BluetoothDevice implements Parcelable, Attributable { * permissions */ @RequiresLegacyBluetoothPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "createL2capChannel: Bluetooth is not enabled"); throw new IOException(); } if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm); - return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true, this, psm, null); + return new BluetoothSocket(this, BluetoothSocket.TYPE_L2CAP_LE, true, true, psm, null); } /** @@ -3176,9 +3151,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { * permissions */ @RequiresLegacyBluetoothPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(BLUETOOTH_CONNECT) - @SuppressLint("AndroidFrameworkRequiresPermission") public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled"); @@ -3187,7 +3159,7 @@ public final class BluetoothDevice implements Parcelable, Attributable { if (DBG) { Log.d(TAG, "createInsecureL2capChannel: psm=" + psm); } - return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false, this, psm, null); + return new BluetoothSocket(this, BluetoothSocket.TYPE_L2CAP_LE, false, false, psm, null); } /** diff --git a/framework/java/android/bluetooth/BluetoothServerSocket.java b/framework/java/android/bluetooth/BluetoothServerSocket.java index 3eb4e0df4bf..b1a01886266 100644 --- a/framework/java/android/bluetooth/BluetoothServerSocket.java +++ b/framework/java/android/bluetooth/BluetoothServerSocket.java @@ -103,7 +103,7 @@ public final class BluetoothServerSocket implements Closeable { mSocketCreationTimeMillis = System.currentTimeMillis(); mType = type; mChannel = port; - mSocket = new BluetoothSocket(type, auth, encrypt, null, port, null); + mSocket = new BluetoothSocket(type, auth, encrypt, port, null); if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { mSocket.setExcludeSdp(true); } @@ -117,17 +117,17 @@ public final class BluetoothServerSocket implements Closeable { * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted * @param port remote port - * @param mitm enforce person-in-the-middle protection for authentication. + * @param pitm enforce person-in-the-middle protection for authentication. * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection * @throws IOException On error, for example Bluetooth not available, or insufficient privileges */ /*package*/ BluetoothServerSocket( - int type, boolean auth, boolean encrypt, int port, boolean mitm, boolean min16DigitPin) + int type, boolean auth, boolean encrypt, int port, boolean pitm, boolean min16DigitPin) throws IOException { mSocketCreationTimeMillis = System.currentTimeMillis(); mType = type; mChannel = port; - mSocket = new BluetoothSocket(type, auth, encrypt, null, port, null, mitm, min16DigitPin); + mSocket = new BluetoothSocket(type, auth, encrypt, port, null, pitm, min16DigitPin); if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { mSocket.setExcludeSdp(true); } @@ -147,7 +147,7 @@ public final class BluetoothServerSocket implements Closeable { throws IOException { mSocketCreationTimeMillis = System.currentTimeMillis(); mType = type; - mSocket = new BluetoothSocket(type, auth, encrypt, null, -1, uuid); + mSocket = new BluetoothSocket(type, auth, encrypt, -1, uuid); // TODO: This is the same as mChannel = -1 - is this intentional? mChannel = mSocket.getPort(); mSocketCreationLatencyMillis = System.currentTimeMillis() - mSocketCreationTimeMillis; diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index c31adcd9670..a104101f120 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.LOCAL_MAC_ADDRESS; import android.annotation.FlaggedApi; +import android.annotation.NonNull; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -130,7 +131,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int SEC_FLAG_ENCRYPT = 1; /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; - /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3; + /*package*/ static final int SEC_FLAG_AUTH_PITM = 1 << 3; /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4; private final int mType; /* one of TYPE_RFCOMM etc */ @@ -146,7 +147,7 @@ public final class BluetoothSocket implements Closeable { private boolean mExcludeSdp = false; /** when true Person-in-the-middle protection will be enabled */ - private boolean mAuthMitm = false; + private boolean mAuthPitm = false; /** Minimum 16 digit pin for sec mode 2 connections */ private boolean mMin16DigitPin = false; @@ -189,7 +190,6 @@ public final class BluetoothSocket implements Closeable { * @param type type of socket * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param device remote device that this socket can connect to * @param port remote port * @param uuid SDP uuid * @throws IOException On error, for example Bluetooth not available, or insufficient privileges @@ -199,11 +199,10 @@ public final class BluetoothSocket implements Closeable { int type, boolean auth, boolean encrypt, - BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { - this(type, auth, encrypt, device, port, uuid, false, false); + this(type, auth, encrypt, port, uuid, false, false); } /** @@ -212,10 +211,9 @@ public final class BluetoothSocket implements Closeable { * @param type type of socket * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param device remote device that this socket can connect to * @param port remote port * @param uuid SDP uuid - * @param mitm enforce person-in-the-middle protection. + * @param pitm enforce person-in-the-middle protection. * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection * @throws IOException On error, for example Bluetooth not available, or insufficient privileges */ @@ -224,10 +222,9 @@ public final class BluetoothSocket implements Closeable { int type, boolean auth, boolean encrypt, - BluetoothDevice device, int port, ParcelUuid uuid, - boolean mitm, + boolean pitm, boolean min16DigitPin) throws IOException { if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type); @@ -246,21 +243,94 @@ public final class BluetoothSocket implements Closeable { } mType = type; mAuth = auth; - mAuthMitm = mitm; + mAuthPitm = pitm; mMin16DigitPin = min16DigitPin; mEncrypt = encrypt; - mDevice = device; mPort = port; + // this constructor to be called only from BluetoothServerSocket + mDevice = null; mSocketState = SocketState.INIT; - if (device == null) { - // Server socket - mAddress = BluetoothAdapter.getDefaultAdapter().getAddress(); + mAddress = BluetoothAdapter.getDefaultAdapter().getAddress(); + + mInputStream = new BluetoothInputStream(this); + mOutputStream = new BluetoothOutputStream(this); + mSocketCreationLatencyNanos = System.nanoTime() - mSocketCreationTimeNanos; + } + + /** + * Construct a BluetoothSocket. + * + * @param device remote device that this socket can connect to + * @param type type of socket + * @param auth require the remote device to be authenticated + * @param encrypt require the connection to be encrypted + * @param port remote port + * @param uuid SDP uuid + * @throws IOException On error, for example Bluetooth not available, or insufficient privileges + */ + /*package*/ BluetoothSocket( + BluetoothDevice device, + int type, + boolean auth, + boolean encrypt, + int port, + ParcelUuid uuid) + throws IOException { + this(device, type, auth, encrypt, port, uuid, false, false); + } + + /** + * Construct a BluetoothSocket. + * + * @param device remote device that this socket can connect to + * @param type type of socket + * @param auth require the remote device to be authenticated + * @param encrypt require the connection to be encrypted + * @param port remote port + * @param uuid SDP uuid + * @param pitm enforce person-in-the-middle protection. + * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection + * @throws IOException On error, for example Bluetooth not available, or insufficient privileges + */ + /*package*/ BluetoothSocket( + @NonNull BluetoothDevice device, + int type, + boolean auth, + boolean encrypt, + int port, + ParcelUuid uuid, + boolean pitm, + boolean min16DigitPin) + throws IOException { + if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type); + mSocketCreationTimeNanos = System.nanoTime(); + if (type == BluetoothSocket.TYPE_RFCOMM + && uuid == null + && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { + if (port < 1 || port > MAX_RFCOMM_CHANNEL) { + throw new IOException("Invalid RFCOMM channel: " + port); + } + } + if (uuid != null) { + mUuid = uuid; } else { - // Remote socket - mAddress = device.getAddress(); + mUuid = new ParcelUuid(new UUID(0, 0)); } + mType = type; + mAuth = auth; + mAuthPitm = pitm; + mMin16DigitPin = min16DigitPin; + mEncrypt = encrypt; + mDevice = device; + mPort = port; + + mSocketState = SocketState.INIT; + + // Remote socket + mAddress = device.getAddress(); + mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); mSocketCreationLatencyNanos = System.nanoTime() - mSocketCreationTimeNanos; @@ -282,7 +352,7 @@ public final class BluetoothSocket implements Closeable { /*package*/ static BluetoothSocket createSocketFromOpenFd( ParcelFileDescriptor pfd, BluetoothDevice device, ParcelUuid uuid) throws IOException { BluetoothSocket bluetoothSocket = - new BluetoothSocket(TYPE_RFCOMM, true, true, device, -1, uuid); + new BluetoothSocket(device, TYPE_RFCOMM, true, true, -1, uuid); bluetoothSocket.mPfd = pfd; bluetoothSocket.mSocket = new LocalSocket(pfd.getFileDescriptor()); @@ -308,7 +378,7 @@ public final class BluetoothSocket implements Closeable { mServiceName = s.mServiceName; mExcludeSdp = s.mExcludeSdp; - mAuthMitm = s.mAuthMitm; + mAuthPitm = s.mAuthPitm; mMin16DigitPin = s.mMin16DigitPin; mSocketCreationTimeNanos = s.mSocketCreationTimeNanos; mSocketCreationLatencyNanos = s.mSocketCreationLatencyNanos; @@ -356,8 +426,8 @@ public final class BluetoothSocket implements Closeable { if (mExcludeSdp) { flags |= BTSOCK_FLAG_NO_SDP; } - if (mAuthMitm) { - flags |= SEC_FLAG_AUTH_MITM; + if (mAuthPitm) { + flags |= SEC_FLAG_AUTH_PITM; } if (mMin16DigitPin) { flags |= SEC_FLAG_AUTH_16_DIGIT; -- GitLab From 66c5ff4998cf9174aea1918a79c74b763abefb6e Mon Sep 17 00:00:00 2001 From: Palash Ahuja Date: Fri, 25 Oct 2024 12:28:16 -0700 Subject: [PATCH 480/875] Adding profile breakdown when logging profile connection success/fail Test: m statsd_testdrive Bug: 375437118 Flag: EXEMPT, metrics changes Change-Id: I32a3ce994f933697f6b3ac7275b148399b9c9010 --- .../btservice/AdapterProperties.java | 29 +------ .../bluetooth/btservice/MetricsLogger.java | 76 +++++++++++++++++++ 2 files changed, 78 insertions(+), 27 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index 43752e6faf3..9c3118bea3a 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -651,7 +651,8 @@ class AdapterProperties { BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, prevAdapterState) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - logProfileConnectionStateChange(device, newState, prevState); + MetricsLogger.getInstance() + .logProfileConnectionStateChange(device, profile, newState, prevState); Log.d(TAG, "updateOnProfileConnectionChanged: " + logInfo); mService.sendBroadcastAsUser( intent, @@ -662,33 +663,7 @@ class AdapterProperties { } } - private void logProfileConnectionStateChange(BluetoothDevice device, int state, int prevState) { - switch (state) { - case BluetoothAdapter.STATE_CONNECTED: - MetricsLogger.getInstance() - .logBluetoothEvent( - device, - BluetoothStatsLog - .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION, - BluetoothStatsLog - .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS, - 0); - break; - case BluetoothAdapter.STATE_DISCONNECTED: - if (prevState == BluetoothAdapter.STATE_CONNECTING) { - MetricsLogger.getInstance() - .logBluetoothEvent( - device, - BluetoothStatsLog - .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION, - BluetoothStatsLog - .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__FAIL, - 0); - } - break; - } - } private boolean validateProfileConnectionState(int state) { return (state == BluetoothProfile.STATE_DISCONNECTED diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java index 6031e3be24b..98040486dbd 100644 --- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java @@ -15,11 +15,28 @@ */ package com.android.bluetooth.btservice; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP_SINK; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_BATTERY; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_CSIP_SET_COORDINATOR; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HAP_CLIENT; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET_CLIENT; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEARING_AID; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HID_HOST; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO_BROADCAST_ASSISTANT; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_MAP_CLIENT; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PAN; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PBAP_CLIENT; +import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_VOLUME_CONTROL; import static com.android.bluetooth.BtRestrictedStatsLog.RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED; import android.app.AlarmManager; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothA2dpSink; +import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAvrcpController; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; @@ -714,6 +731,65 @@ public class MetricsLogger { return digest.digest(name.getBytes(StandardCharsets.UTF_8)); } + private int getProfileEnumFromProfileId(int profile) { + return switch (profile) { + case BluetoothProfile.A2DP -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP; + case BluetoothProfile.A2DP_SINK -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP_SINK; + case BluetoothProfile.HEADSET -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET; + case BluetoothProfile.HEADSET_CLIENT -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET_CLIENT; + case BluetoothProfile.MAP_CLIENT -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_MAP_CLIENT; + case BluetoothProfile.HID_HOST -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HID_HOST; + case BluetoothProfile.PAN -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PAN; + case BluetoothProfile.PBAP_CLIENT -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PBAP_CLIENT; + case BluetoothProfile.HEARING_AID -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEARING_AID; + case BluetoothProfile.HAP_CLIENT -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HAP_CLIENT; + case BluetoothProfile.VOLUME_CONTROL -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_VOLUME_CONTROL; + case BluetoothProfile.CSIP_SET_COORDINATOR -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_CSIP_SET_COORDINATOR; + case BluetoothProfile.LE_AUDIO -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO; + case BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO_BROADCAST_ASSISTANT; + case BluetoothProfile.BATTERY -> + BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_BATTERY; + default -> BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION; + }; + } + + public void logProfileConnectionStateChange( + BluetoothDevice device, int profileId, int state, int prevState) { + + switch (state) { + case BluetoothAdapter.STATE_CONNECTED: + logBluetoothEvent( + device, + getProfileEnumFromProfileId(profileId), + BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS, + 0); + break; + case BluetoothAdapter.STATE_DISCONNECTED: + if (prevState == BluetoothAdapter.STATE_CONNECTING) { + logBluetoothEvent( + device, + getProfileEnumFromProfileId(profileId), + BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__FAIL, + 0); + } + break; + } + } + /** Logs LE Audio Broadcast audio session. */ public void logLeAudioBroadcastAudioSession( int broadcastId, -- GitLab From 15ea8e7239628dfbb0123f98c8060887b0d39935 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 29 Oct 2024 14:17:14 -0700 Subject: [PATCH 481/875] Adapter: prevent race condition around sServiceLock Since get_profile_use_lock, the onServiceConnected callback is running on the binder thread instead of bloating the main thread (use to block main app thread for ~200 ms which is not great). But because it doesn't post the event, it tries to complete its execution while holding some other lock, including sServiceLock during the onBluetoothOn. This lock is also use when getting the adapterService from BluetoothDevice. Prior to this change, both call are mutually exclusive, but both are only trying to access to the service value in read mode and they shouldn't be blocked. In an optimal world, no lock would be necessary, and BluetoothDevice wouldn't need to fetch a static adapterService binder. But this is a too big refactor, using a read/write lock is simple enough for this issue and doesn't change the behavior that much Bug: 373533897 Bug: 370815283 Flag: com.android.bluetooth.flags.get_profile_use_lock Test: m Bluetooth -- There is no race condition test written for Bt Change-Id: Id9bb4aea1a9f1ee4f282cff9fde703646e886585 --- .../android/bluetooth/BluetoothAdapter.java | 112 +++++++++++++++++- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 61f8ba3455e..3477bed73f4 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -871,6 +871,7 @@ public final class BluetoothAdapter { @GuardedBy("mServiceLock") private IBluetooth mService; + private static final ReentrantReadWriteLock sServiceLock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); @GuardedBy("sServiceLock") @@ -879,8 +880,6 @@ public final class BluetoothAdapter { @GuardedBy("sServiceLock") private static IBluetooth sService; - private static final Object sServiceLock = new Object(); - private final Object mLock = new Object(); private final Map mLeScanClients = new HashMap<>(); private final Map>> @@ -3698,12 +3697,32 @@ public final class BluetoothAdapter { private static final IBluetoothManagerCallback sManagerCallback = new IBluetoothManagerCallback.Stub() { + private void onBluetoothServiceUpFlagged(IBinder bluetoothService) { + sServiceLock.writeLock().lock(); + try { + sService = IBluetooth.Stub.asInterface(bluetoothService); + for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { + try { + cb.onBluetoothServiceUp(bluetoothService); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + } + } finally { + sServiceLock.writeLock().unlock(); + } + } + @RequiresNoPermission public void onBluetoothServiceUp(IBinder bluetoothService) { if (DBG) { Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); } + if (Flags.getProfileUseLock()) { + onBluetoothServiceUpFlagged(bluetoothService); + return; + } synchronized (sServiceLock) { sService = IBluetooth.Stub.asInterface(bluetoothService); for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { @@ -3720,12 +3739,33 @@ public final class BluetoothAdapter { } } + private void onBluetoothServiceDownFlagged() { + sServiceLock.writeLock().lock(); + try { + sService = null; + for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { + try { + cb.onBluetoothServiceDown(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + } + } finally { + sServiceLock.writeLock().unlock(); + } + } + @RequiresNoPermission public void onBluetoothServiceDown() { if (DBG) { Log.d(TAG, "onBluetoothServiceDown"); } + if (Flags.getProfileUseLock()) { + onBluetoothServiceDownFlagged(); + return; + } + synchronized (sServiceLock) { sService = null; for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { @@ -3742,12 +3782,31 @@ public final class BluetoothAdapter { } } + private void onBluetoothOnFlagged() { + sServiceLock.readLock().lock(); + try { + for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { + try { + cb.onBluetoothOn(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + } + } finally { + sServiceLock.readLock().unlock(); + } + } + @RequiresNoPermission public void onBluetoothOn() { if (DBG) { Log.d(TAG, "onBluetoothOn"); } + if (Flags.getProfileUseLock()) { + onBluetoothOnFlagged(); + return; + } synchronized (sServiceLock) { for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { try { @@ -3763,12 +3822,31 @@ public final class BluetoothAdapter { } } + private void onBluetoothOffFlagged() { + sServiceLock.readLock().lock(); + try { + for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { + try { + cb.onBluetoothOff(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + } + } finally { + sServiceLock.readLock().unlock(); + } + } + @RequiresNoPermission public void onBluetoothOff() { if (DBG) { Log.d(TAG, "onBluetoothOff"); } + if (Flags.getProfileUseLock()) { + onBluetoothOffFlagged(); + return; + } synchronized (sServiceLock) { for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { try { @@ -4120,6 +4198,14 @@ public final class BluetoothAdapter { new WeakHashMap<>(); /*package*/ IBluetooth getBluetoothService() { + if (Flags.getProfileUseLock()) { + sServiceLock.readLock().lock(); + try { + return sService; + } finally { + sServiceLock.readLock().unlock(); + } + } synchronized (sServiceLock) { return sService; } @@ -4135,6 +4221,16 @@ public final class BluetoothAdapter { */ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) { requireNonNull(cb); + if (Flags.getProfileUseLock()) { + sServiceLock.writeLock().lock(); + try { + sProxyServiceStateCallbacks.put(cb, null); + registerOrUnregisterAdapterLocked(); + return sService; + } finally { + sServiceLock.writeLock().unlock(); + } + } synchronized (sServiceLock) { sProxyServiceStateCallbacks.put(cb, null); registerOrUnregisterAdapterLocked(); @@ -4200,6 +4296,16 @@ public final class BluetoothAdapter { /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) { requireNonNull(cb); + if (Flags.getProfileUseLock()) { + sServiceLock.writeLock().lock(); + try { + sProxyServiceStateCallbacks.remove(cb); + registerOrUnregisterAdapterLocked(); + } finally { + sServiceLock.writeLock().unlock(); + } + return; + } synchronized (sServiceLock) { sProxyServiceStateCallbacks.remove(cb); registerOrUnregisterAdapterLocked(); @@ -4210,7 +4316,7 @@ public final class BluetoothAdapter { * Handle registering (or unregistering) a single process-wide {@link IBluetoothManagerCallback} * based on the presence of local {@link #sProxyServiceStateCallbacks} clients. */ - @GuardedBy("sServiceLock") + @GuardedBy("sServiceLock") // with write lock private void registerOrUnregisterAdapterLocked() { final boolean isRegistered = sServiceRegistered; final boolean wantRegistered = !sProxyServiceStateCallbacks.isEmpty(); -- GitLab From 0bfbee16bafefb934ed5f85ae125cce64b8a14df Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Tue, 29 Oct 2024 05:39:26 +0000 Subject: [PATCH 482/875] CS: Parsing the CS procedure data of mode 1 Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 376172766 Test: m com.android.btservice Change-Id: I0c0d8a9b7a536647ce588934fdbcf73c73e4b0b6 --- system/gd/hal/ranging_hal.h | 4 + system/gd/hal/ranging_hal_android.cc | 14 ++ system/gd/hci/distance_measurement_manager.cc | 134 +++++++++++++++++- system/pdl/hci/hci_packets.pdl | 52 +++++++ 4 files changed, 203 insertions(+), 1 deletion(-) diff --git a/system/gd/hal/ranging_hal.h b/system/gd/hal/ranging_hal.h index 803f326c99e..981f16b00b4 100644 --- a/system/gd/hal/ranging_hal.h +++ b/system/gd/hal/ranging_hal.h @@ -35,6 +35,10 @@ struct ChannelSoundingRawData { std::vector>> tone_pct_reflector_; std::vector> tone_quality_indicator_initiator_; std::vector> tone_quality_indicator_reflector_; + std::vector packet_quality_initiator; + std::vector packet_quality_reflector; + std::vector toa_tod_initiators_; + std::vector tod_toa_reflectors_; }; struct RangingResult { diff --git a/system/gd/hal/ranging_hal_android.cc b/system/gd/hal/ranging_hal_android.cc index 893a25fd106..99daf2c0877 100644 --- a/system/gd/hal/ranging_hal_android.cc +++ b/system/gd/hal/ranging_hal_android.cc @@ -195,6 +195,7 @@ public: hal_raw_data.stepChannels = raw_data.step_channel_; hal_raw_data.initiatorData.stepTonePcts.emplace(std::vector>{}); hal_raw_data.reflectorData.stepTonePcts.emplace(std::vector>{}); + // Add tone data for mode 2 for (uint8_t i = 0; i < raw_data.tone_pct_initiator_.size(); i++) { StepTonePct step_tone_pct; for (uint8_t j = 0; j < raw_data.tone_pct_initiator_[i].size(); j++) { @@ -217,6 +218,19 @@ public: step_tone_pct.toneQualityIndicator = raw_data.tone_quality_indicator_reflector_[i]; hal_raw_data.reflectorData.stepTonePcts.value().emplace_back(step_tone_pct); } + // Add RTT data for mode 1 + if (!raw_data.toa_tod_initiators_.empty()) { + hal_raw_data.toaTodInitiator = std::vector(raw_data.toa_tod_initiators_.begin(), + raw_data.toa_tod_initiators_.end()); + hal_raw_data.initiatorData.packetQuality = std::vector( + raw_data.packet_quality_initiator.begin(), raw_data.packet_quality_initiator.end()); + } + if (!raw_data.tod_toa_reflectors_.empty()) { + hal_raw_data.todToaReflector = std::vector(raw_data.tod_toa_reflectors_.begin(), + raw_data.tod_toa_reflectors_.end()); + hal_raw_data.reflectorData.packetQuality = std::vector( + raw_data.packet_quality_reflector.begin(), raw_data.packet_quality_reflector.end()); + } session_trackers_[connection_handle]->GetSession()->writeRawData(hal_raw_data); } diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index b5d84af8045..0ee50eceab8 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -119,6 +119,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { std::vector>> tone_pct_reflector; std::vector> tone_quality_indicator_initiator; std::vector> tone_quality_indicator_reflector; + std::vector packet_quality_initiator; + std::vector packet_quality_reflector; + std::vector toa_tod_initiators; + std::vector tod_toa_reflectors; + std::vector rssi_initiator; + std::vector rssi_reflector; + bool contains_sounding_sequence_local_; + bool contains_sounding_sequence_remote_; CsProcedureDoneStatus local_status; CsProcedureDoneStatus remote_status; // If the procedure is aborted by either the local or remote side. @@ -742,6 +750,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } cs_subfeature_supported_ = complete_view.GetOptionalSubfeaturesSupported(); num_antennas_supported_ = complete_view.GetNumAntennasSupported(); + local_support_phase_based_ranging_ = cs_subfeature_supported_.phase_based_ranging_ == 0x01; } void on_cs_read_remote_supported_capabilities_complete( @@ -1334,6 +1343,57 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } parse_index = after; } break; + case 1: { + if (remote_role == CsRole::INITIATOR) { + if (procedure_data->contains_sounding_sequence_remote_) { + LeCsMode1InitatorDataWithPacketPct tone_data; + after = LeCsMode1InitatorDataWithPacketPct::Parse(&tone_data, parse_index); + if (after == parse_index) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index = after; + procedure_data->toa_tod_initiators.emplace_back(tone_data.toa_tod_initiator_); + procedure_data->packet_quality_initiator.emplace_back(tone_data.packet_quality_); + } else { + LeCsMode1InitatorData tone_data; + after = LeCsMode1InitatorData::Parse(&tone_data, parse_index); + if (after == parse_index) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index = after; + procedure_data->toa_tod_initiators.emplace_back(tone_data.toa_tod_initiator_); + procedure_data->packet_quality_initiator.emplace_back(tone_data.packet_quality_); + } + } else { + if (procedure_data->contains_sounding_sequence_remote_) { + LeCsMode1ReflectorDataWithPacketPct tone_data; + after = LeCsMode1ReflectorDataWithPacketPct::Parse(&tone_data, parse_index); + if (after == parse_index) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index = after; + procedure_data->tod_toa_reflectors.emplace_back(tone_data.tod_toa_reflector_); + procedure_data->packet_quality_reflector.emplace_back(tone_data.packet_quality_); + } else { + LeCsMode1ReflectorData tone_data; + after = LeCsMode1ReflectorData::Parse(&tone_data, parse_index); + if (after == parse_index) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index = after; + procedure_data->tod_toa_reflectors.emplace_back(tone_data.tod_toa_reflector_); + procedure_data->packet_quality_reflector.emplace_back(tone_data.packet_quality_); + } + } + } break; case 2: { uint8_t num_tone_data = num_antenna_paths + 1; uint8_t data_len = 1 + (4 * num_tone_data); @@ -1415,6 +1475,18 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { data_list.emplace_back(procedure_counter, num_antenna_paths, live_tracker->config_id, live_tracker->selected_tx_power); + // Check if sounding phase-based ranging is supported, and RTT type contains a sounding + // sequence + bool rtt_contains_sounding_sequence = false; + if (live_tracker->rtt_type == CsRttType::RTT_WITH_32_BIT_SOUNDING_SEQUENCE || + live_tracker->rtt_type == CsRttType::RTT_WITH_96_BIT_SOUNDING_SEQUENCE) { + rtt_contains_sounding_sequence = true; + } + data_list.back().contains_sounding_sequence_local_ = + local_support_phase_based_ranging_ && rtt_contains_sounding_sequence; + data_list.back().contains_sounding_sequence_remote_ = + live_tracker->remote_support_phase_based_ranging && rtt_contains_sounding_sequence; + // Append ranging header raw data std::vector ranging_header_raw = {}; BitInserter bi(ranging_header_raw); @@ -1482,6 +1554,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { raw_data.tone_pct_reflector_ = procedure_data->tone_pct_reflector; raw_data.tone_quality_indicator_reflector_ = procedure_data->tone_quality_indicator_reflector; + raw_data.toa_tod_initiators_ = procedure_data->toa_tod_initiators; + raw_data.tod_toa_reflectors_ = procedure_data->tod_toa_reflectors; + raw_data.packet_quality_initiator = procedure_data->packet_quality_initiator; + raw_data.packet_quality_reflector = procedure_data->packet_quality_reflector; ranging_hal_->WriteRawData(connection_handle, raw_data); return; } @@ -1552,6 +1628,62 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::verbose("step_data: {}", tone_data_view.ToString()); } } break; + case 1: { + if (role == CsRole::INITIATOR) { + if (procedure_data.contains_sounding_sequence_local_) { + LeCsMode1InitatorDataWithPacketPct tone_data_view; + auto after = LeCsMode1InitatorDataWithPacketPct::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + procedure_data.rssi_initiator.emplace_back(tone_data_view.packet_rssi_); + procedure_data.toa_tod_initiators.emplace_back(tone_data_view.toa_tod_initiator_); + procedure_data.packet_quality_initiator.emplace_back(tone_data_view.packet_quality_); + } else { + LeCsMode1InitatorData tone_data_view; + auto after = LeCsMode1InitatorData::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + procedure_data.rssi_initiator.emplace_back(tone_data_view.packet_rssi_); + procedure_data.toa_tod_initiators.emplace_back(tone_data_view.toa_tod_initiator_); + procedure_data.packet_quality_initiator.emplace_back(tone_data_view.packet_quality_); + } + procedure_data.step_channel.push_back(step_channel); + } else { + if (procedure_data.contains_sounding_sequence_local_) { + LeCsMode1ReflectorDataWithPacketPct tone_data_view; + auto after = LeCsMode1ReflectorDataWithPacketPct::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + procedure_data.rssi_reflector.emplace_back(tone_data_view.packet_rssi_); + procedure_data.tod_toa_reflectors.emplace_back(tone_data_view.tod_toa_reflector_); + procedure_data.packet_quality_reflector.emplace_back(tone_data_view.packet_quality_); + } else { + LeCsMode1ReflectorData tone_data_view; + auto after = LeCsMode1ReflectorData::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + procedure_data.rssi_reflector.emplace_back(tone_data_view.packet_rssi_); + procedure_data.tod_toa_reflectors.emplace_back(tone_data_view.tod_toa_reflector_); + procedure_data.packet_quality_reflector.emplace_back(tone_data_view.packet_quality_); + } + } + } break; case 2: { LeCsMode2Data tone_data_view; auto after = LeCsMode2Data::Parse(&tone_data_view, iterator); @@ -1589,7 +1721,6 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } } break; - case 1: case 3: log::debug("Unsupported mode: {}", mode); break; @@ -1780,6 +1911,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { DistanceMeasurementCallbacks* distance_measurement_callbacks_; CsOptionalSubfeaturesSupported cs_subfeature_supported_; uint8_t num_antennas_supported_ = 0x01; + bool local_support_phase_based_ranging_ = false; // A table that maps num_antennas_supported and remote_num_antennas_supported to Antenna // Configuration Index. uint8_t cs_tone_antenna_config_mapping_table_[4][4] = { diff --git a/system/pdl/hci/hci_packets.pdl b/system/pdl/hci/hci_packets.pdl index df7c47db2a2..7e1ec33dbb3 100644 --- a/system/pdl/hci/hci_packets.pdl +++ b/system/pdl/hci/hci_packets.pdl @@ -6895,6 +6895,58 @@ struct LeCsMode0ReflectorData { packet_antenna : 8, } +enum CsPacketNadm : 8 { + ATTACK_IS_EXTREMELY_UNLIKELY = 0x00, + ATTACK_IS_VERY_UNLIKELY = 0x01, + ATTACK_IS_UNLIKELY = 0x02, + ATTACK_IS_POSSIBLE = 0x03, + ATTACK_IS_LIKELY = 0x04, + ATTACK_IS_VERY_LIKELY = 0x05, + ATTACK_IS_EXTREMELY_LIKELY = 0x06, + UNKNOWN_NADM = 0xFF, +} + +struct LeCsToneData { + i_sample : 12, + q_sample : 12, +} + +struct LeCsMode1InitatorData { + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + toa_tod_initiator : 16, + packet_antenna : 8, +} + +struct LeCsMode1InitatorDataWithPacketPct { + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + toa_tod_initiator : 16, + packet_antenna : 8, + packet_pct1 : LeCsToneData, + packet_pct2 : LeCsToneData, +} + +struct LeCsMode1ReflectorData { + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + tod_toa_reflector : 16, + packet_antenna : 8, +} + +struct LeCsMode1ReflectorDataWithPacketPct { + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + tod_toa_reflector : 16, + packet_antenna : 8, + packet_pct1 : LeCsToneData, + packet_pct2 : LeCsToneData, +} + struct LeCsToneDataWithQuality { i_sample : 12, q_sample : 12, -- GitLab From 4770781981a66dbe09175a760e944fdedcd0556a Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Tue, 29 Oct 2024 06:42:23 +0000 Subject: [PATCH 483/875] CS: Parsing the CS procedure data of mode 3 Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 376172766 Test: m com.android.btservice Change-Id: If2f4e0c389595d91eaf3313786bef319e4a4c040 --- system/gd/hal/ranging_hal_android.cc | 4 +- system/gd/hci/distance_measurement_manager.cc | 224 +++++++++++++++++- system/pdl/hci/hci_packets.pdl | 48 ++++ 3 files changed, 271 insertions(+), 5 deletions(-) diff --git a/system/gd/hal/ranging_hal_android.cc b/system/gd/hal/ranging_hal_android.cc index 99daf2c0877..c50ee18c76f 100644 --- a/system/gd/hal/ranging_hal_android.cc +++ b/system/gd/hal/ranging_hal_android.cc @@ -195,7 +195,7 @@ public: hal_raw_data.stepChannels = raw_data.step_channel_; hal_raw_data.initiatorData.stepTonePcts.emplace(std::vector>{}); hal_raw_data.reflectorData.stepTonePcts.emplace(std::vector>{}); - // Add tone data for mode 2 + // Add tone data for mode 2, mode 3 for (uint8_t i = 0; i < raw_data.tone_pct_initiator_.size(); i++) { StepTonePct step_tone_pct; for (uint8_t j = 0; j < raw_data.tone_pct_initiator_[i].size(); j++) { @@ -218,7 +218,7 @@ public: step_tone_pct.toneQualityIndicator = raw_data.tone_quality_indicator_reflector_[i]; hal_raw_data.reflectorData.stepTonePcts.value().emplace_back(step_tone_pct); } - // Add RTT data for mode 1 + // Add RTT data for mode 1, mode 3 if (!raw_data.toa_tod_initiators_.empty()) { hal_raw_data.toaTodInitiator = std::vector(raw_data.toa_tod_initiators_.begin(), raw_data.toa_tod_initiators_.end()); diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 0ee50eceab8..5dcd379647c 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -1445,6 +1445,131 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } } break; + case 3: { + uint8_t num_tone_data = num_antenna_paths + 1; + uint8_t data_len = 7 + (4 * num_tone_data); + if (procedure_data->contains_sounding_sequence_local_) { + data_len += 3; // 3 bytes for packet_pct1, packet_pct2 + } + remaining_data_size = std::distance(parse_index, segment_data.end()); + if (remaining_data_size < data_len) { + log::warn( + "insufficient length for LeCsMode2Data, num_tone_data {}, " + "remaining_data_size {}", + num_tone_data, remaining_data_size); + return; + } + std::vector vector_for_num_tone_data = {num_tone_data}; + PacketView packet_view_for_num_tone_data( + std::make_shared>(vector_for_num_tone_data)); + PacketViewForRecombination packet_bytes_view = + PacketViewForRecombination(packet_view_for_num_tone_data); + auto subview_begin = std::distance(segment_data.begin(), parse_index); + packet_bytes_view.AppendPacketView( + segment_data.GetLittleEndianSubview(subview_begin, subview_begin + data_len)); + uint8_t permutation_index = 0; + std::vector view_tone_data = {}; + if (remote_role == CsRole::INITIATOR) { + if (procedure_data->contains_sounding_sequence_local_) { + LeCsMode3InitatorDataWithPacketPct tone_data_view; + after = LeCsMode3InitatorDataWithPacketPct::Parse(&tone_data_view, + packet_bytes_view.begin()); + if (after == packet_bytes_view.begin()) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index += data_len; + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data->rssi_initiator.emplace_back(tone_data_view.packet_rssi_); + procedure_data->toa_tod_initiators.emplace_back(tone_data_view.toa_tod_initiator_); + procedure_data->packet_quality_initiator.emplace_back( + tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } else { + LeCsMode3InitatorData tone_data_view; + after = LeCsMode3InitatorData::Parse(&tone_data_view, packet_bytes_view.begin()); + if (after == packet_bytes_view.begin()) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index += data_len; + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data->rssi_initiator.emplace_back(tone_data_view.packet_rssi_); + procedure_data->toa_tod_initiators.emplace_back(tone_data_view.toa_tod_initiator_); + procedure_data->packet_quality_initiator.emplace_back( + tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } + } else { + if (procedure_data->contains_sounding_sequence_local_) { + LeCsMode3ReflectorDataWithPacketPct tone_data_view; + after = LeCsMode3ReflectorDataWithPacketPct::Parse(&tone_data_view, + packet_bytes_view.begin()); + if (after == packet_bytes_view.begin()) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index += data_len; + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data->rssi_reflector.emplace_back(tone_data_view.packet_rssi_); + procedure_data->tod_toa_reflectors.emplace_back(tone_data_view.tod_toa_reflector_); + procedure_data->packet_quality_reflector.emplace_back( + tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } else { + LeCsMode3ReflectorData tone_data_view; + after = LeCsMode3ReflectorData::Parse(&tone_data_view, packet_bytes_view.begin()); + if (after == packet_bytes_view.begin()) { + log::warn("Error invalid mode {} data, role:{}", step_mode.mode_type_, + CsRoleText(remote_role)); + return; + } + parse_index += data_len; + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data->rssi_reflector.emplace_back(tone_data_view.packet_rssi_); + procedure_data->tod_toa_reflectors.emplace_back(tone_data_view.tod_toa_reflector_); + procedure_data->packet_quality_reflector.emplace_back( + tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } + } + // Parse in ascending order of antenna position with tone extension data at the end + for (uint16_t k = 0; k < num_tone_data; k++) { + uint8_t antenna_path = + k == num_antenna_paths + ? num_antenna_paths + : cs_antenna_permutation_array_[permutation_index][k] - 1; + double i_value = get_iq_value(view_tone_data[k].i_sample_); + double q_value = get_iq_value(view_tone_data[k].q_sample_); + uint8_t tone_quality_indicator = view_tone_data[k].tone_quality_indicator_; + log::verbose("antenna_path {}, {:f}, {:f}", (uint16_t)(antenna_path + 1), i_value, + q_value); + if (remote_role == CsRole::INITIATOR) { + procedure_data->tone_pct_initiator[antenna_path].emplace_back(i_value, q_value); + procedure_data->tone_quality_indicator_initiator[antenna_path].emplace_back( + tone_quality_indicator); + } else { + procedure_data->tone_pct_reflector[antenna_path].emplace_back(i_value, q_value); + procedure_data->tone_quality_indicator_reflector[antenna_path].emplace_back( + tone_quality_indicator); + } + } + } break; default: log::error("Unexpect mode: {}", step_mode.mode_type_); return; @@ -1721,9 +1846,102 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } } break; - case 3: - log::debug("Unsupported mode: {}", mode); - break; + case 3: { + uint8_t permutation_index = 0; + std::vector view_tone_data = {}; + if (role == CsRole::INITIATOR) { + if (procedure_data.contains_sounding_sequence_local_) { + LeCsMode3InitatorDataWithPacketPct tone_data_view; + auto after = LeCsMode3InitatorDataWithPacketPct::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data.rssi_initiator.emplace_back(tone_data_view.packet_rssi_); + procedure_data.toa_tod_initiators.emplace_back(tone_data_view.toa_tod_initiator_); + procedure_data.packet_quality_initiator.emplace_back(tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } else { + LeCsMode3InitatorData tone_data_view; + auto after = LeCsMode3InitatorData::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data.rssi_initiator.emplace_back(tone_data_view.packet_rssi_); + procedure_data.toa_tod_initiators.emplace_back(tone_data_view.toa_tod_initiator_); + procedure_data.packet_quality_initiator.emplace_back(tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } + procedure_data.step_channel.push_back(step_channel); + } else { + if (procedure_data.contains_sounding_sequence_local_) { + LeCsMode3ReflectorDataWithPacketPct tone_data_view; + auto after = LeCsMode3ReflectorDataWithPacketPct::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data.rssi_reflector.emplace_back(tone_data_view.packet_rssi_); + procedure_data.tod_toa_reflectors.emplace_back(tone_data_view.tod_toa_reflector_); + procedure_data.packet_quality_reflector.emplace_back(tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } else { + LeCsMode3ReflectorData tone_data_view; + auto after = LeCsMode3ReflectorData::Parse(&tone_data_view, iterator); + if (after == iterator) { + log::warn("Received invalid mode {} data, role:{}", mode, CsRoleText(role)); + print_raw_data(result_data_structure.step_data_); + continue; + } + log::verbose("step_data: {}", tone_data_view.ToString()); + permutation_index = tone_data_view.antenna_permutation_index_; + procedure_data.rssi_reflector.emplace_back(tone_data_view.packet_rssi_); + procedure_data.tod_toa_reflectors.emplace_back(tone_data_view.tod_toa_reflector_); + procedure_data.packet_quality_reflector.emplace_back(tone_data_view.packet_quality_); + auto tone_data = tone_data_view.tone_data_; + view_tone_data.reserve(tone_data.size()); + view_tone_data.insert(view_tone_data.end(), tone_data.begin(), tone_data.end()); + } + } + // Parse in ascending order of antenna position with tone extension data at the end + uint16_t num_tone_data = num_antenna_paths + 1; + for (uint16_t k = 0; k < num_tone_data; k++) { + uint8_t antenna_path = + k == num_antenna_paths + ? num_antenna_paths + : cs_antenna_permutation_array_[permutation_index][k] - 1; + double i_value = get_iq_value(view_tone_data[k].i_sample_); + double q_value = get_iq_value(view_tone_data[k].q_sample_); + uint8_t tone_quality_indicator = view_tone_data[k].tone_quality_indicator_; + log::verbose("antenna_path {}, {:f}, {:f}", (uint16_t)(antenna_path + 1), i_value, + q_value); + if (role == CsRole::INITIATOR) { + procedure_data.tone_pct_initiator[antenna_path].emplace_back(i_value, q_value); + procedure_data.tone_quality_indicator_initiator[antenna_path].emplace_back( + tone_quality_indicator); + } else { + procedure_data.tone_pct_reflector[antenna_path].emplace_back(i_value, q_value); + procedure_data.tone_quality_indicator_reflector[antenna_path].emplace_back( + tone_quality_indicator); + } + } + } break; default: { log::warn("Invalid mode {}", mode); } diff --git a/system/pdl/hci/hci_packets.pdl b/system/pdl/hci/hci_packets.pdl index 7e1ec33dbb3..deabcd6930f 100644 --- a/system/pdl/hci/hci_packets.pdl +++ b/system/pdl/hci/hci_packets.pdl @@ -6959,6 +6959,54 @@ struct LeCsMode2Data { tone_data : LeCsToneDataWithQuality[], } +struct LeCsMode3InitatorData { + _count_(tone_data) : 8, + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + packet_antenna : 8, + toa_tod_initiator : 16, + antenna_permutation_index : 8, + tone_data : LeCsToneDataWithQuality[], +} + +struct LeCsMode3InitatorDataWithPacketPct { + _count_(tone_data) : 8, + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + packet_antenna : 8, + packet_pct1 : LeCsToneData, + packet_pct2 : LeCsToneData, + toa_tod_initiator : 16, + antenna_permutation_index : 8, + tone_data : LeCsToneDataWithQuality[], +} + +struct LeCsMode3ReflectorData { + _count_(tone_data) : 8, + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + packet_antenna : 8, + tod_toa_reflector : 16, + antenna_permutation_index : 8, + tone_data : LeCsToneDataWithQuality[], +} + +struct LeCsMode3ReflectorDataWithPacketPct { + _count_(tone_data) : 8, + packet_quality : 8, + packet_nadm : CsPacketNadm, + packet_rssi : 8, + packet_antenna : 8, + packet_pct1 : LeCsToneData, + packet_pct2 : LeCsToneData, + tod_toa_reflector : 16, + antenna_permutation_index : 8, + tone_data : LeCsToneDataWithQuality[], +} + enum CsProcedureDoneStatus : 4 { ALL_RESULTS_COMPLETE = 0x0, PARTIAL_RESULTS = 0x1, -- GitLab From e63ab5d3b37a664ab7c0edaeea998d5357d88e41 Mon Sep 17 00:00:00 2001 From: Gopi Sakshihally Bhuthaiah Date: Wed, 21 Aug 2024 09:33:50 +0000 Subject: [PATCH 484/875] Bumble Java Pairing Test cases Create Pairing by Remote with Local OOB data Bug: 333734042 Test: atest -v OobPairingTest Flag: TEST_ONLY Change-Id: Ie516b71e8562366b5663b98ec73d1efcbbe558d2 --- .../bluetooth/pairing/OobPairingTest.java | 97 ++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java index 64c196bc5e5..b1e1e23f4e3 100644 --- a/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java +++ b/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java @@ -31,6 +31,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.bluetooth.OobData; import android.bluetooth.PandoraDevice; +import android.bluetooth.StreamObserverSpliterator; import android.bluetooth.Utils; import android.bluetooth.cts.EnableBluetoothRule; import android.content.BroadcastReceiver; @@ -47,6 +48,8 @@ import com.android.compatibility.common.util.AdoptShellPermissionsRule; import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; +import io.grpc.Deadline; + import org.hamcrest.Matcher; import org.hamcrest.core.AllOf; import org.junit.After; @@ -61,23 +64,36 @@ import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.stubbing.Answer; import pandora.HostProto.AdvertiseRequest; +import pandora.HostProto.ConnectLERequest; +import pandora.HostProto.ConnectLEResponse; import pandora.HostProto.OwnAddressType; +import pandora.HostProto.ScanRequest; +import pandora.HostProto.ScanningResponse; import pandora.OobProto.OobDataRequest; import pandora.OobProto.OobDataResponse; +import pandora.SecurityProto.LESecurityLevel; +import pandora.SecurityProto.SecureRequest; +import pandora.SecurityProto.SecureResponse; import java.time.Duration; import java.util.Arrays; +import java.util.Iterator; +import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) public class OobPairingTest { private static final String TAG = OobPairingTest.class.getSimpleName(); private static final Duration INTENT_TIMEOUT = Duration.ofSeconds(10); + private static final String CF_NAME = "Cuttlefish"; + private BluetoothDevice mDevice; private final Context mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); private final BluetoothAdapter mAdapter = mContext.getSystemService(BluetoothManager.class).getAdapter(); private OobDataResponse mRemoteOobData; + private boolean mRemoteInitiator = false; + private static final int TIMEOUT_ADVERTISING_MS = 1000; private static final int HASH_START_POSITION = 0; private static final int HASH_END_POSITION = 16; @@ -162,6 +178,44 @@ public class OobPairingTest { mBumble.hostBlocking().advertise(request); } + private void initiatePairingFromRemote() { + ByteString deviceAddr; + StreamObserverSpliterator scanningResponseObserver = + new StreamObserverSpliterator<>(); + Deadline deadline = Deadline.after(TIMEOUT_ADVERTISING_MS, TimeUnit.MILLISECONDS); + mBumble.host() + .withDeadline(deadline) + .scan(ScanRequest.newBuilder().build(), scanningResponseObserver); + Iterator scanningResponseIterator = scanningResponseObserver.iterator(); + + while (true) { + if (scanningResponseIterator.hasNext()) { + ScanningResponse scanningResponse = scanningResponseIterator.next(); + // select first available device + deviceAddr = scanningResponse.getRandom(); + break; + } + } + + ConnectLEResponse leConn = + mBumble.hostBlocking() + .connectLE( + ConnectLERequest.newBuilder() + .setOwnAddressType(OwnAddressType.RANDOM) + .setRandom(deviceAddr) + .build()); + // Start pairing from Bumble + StreamObserverSpliterator responseObserver = + new StreamObserverSpliterator<>(); + mBumble.security() + .secure( + SecureRequest.newBuilder() + .setConnection(leConn.getConnection()) + .setLe(LESecurityLevel.LE_LEVEL4) + .build(), + responseObserver); + } + private final OobDataCallback mGenerateOobDataCallback = new OobDataCallback() { @Override @@ -182,7 +236,11 @@ public class OobPairingTest { .build(); mRemoteOobData = mBumble.oobBlocking().shareOobData(localOobData); OobData p256 = buildOobData(); - mDevice.createBondOutOfBand(BluetoothDevice.TRANSPORT_LE, null, p256); + if (mRemoteInitiator) { + initiatePairingFromRemote(); + } else { + mDevice.createBondOutOfBand(BluetoothDevice.TRANSPORT_LE, null, p256); + } } }; @@ -218,7 +276,7 @@ public class OobPairingTest { *

      *
    1. 1. Android gets OOB Data from Bumble. *
    2. 2. Android creates bond with remote OOB data - *
    3. 5. Android verifies bonded intent + *
    4. 3. Android verifies bonded intent *
    */ @Test @@ -247,7 +305,7 @@ public class OobPairingTest { *
      *
    1. 1. Android gets OOB Data from Bumble. *
    2. 2. Android creates bond with remote OOB data - *
    3. 5. Android verifies bonded intent + *
    4. 3. Android verifies bonded intent *
    */ @Test @@ -266,6 +324,39 @@ public class OobPairingTest { hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); } + /** + * Test OOB pairing: Configuration: Initiator: Remote, Local OOB: yes , Remote OOB: No, Secure + * Connections: Yes + * + *
      + *
    1. 1. Android generates OOB Data and share with Bumble. + *
    2. 2. Bumble creates bond + *
    3. 3. Android verifies bonded intent + *
    + */ + @Test + public void createBondByRemoteDevicWithLocalOob() throws Exception { + + mRemoteInitiator = true; + String deviceName = mAdapter.getName(); + // set adapter name for verification + mAdapter.setName(CF_NAME); + + mAdapter.generateLocalOobData( + BluetoothDevice.TRANSPORT_LE, mContext.getMainExecutor(), mGenerateOobDataCallback); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + mRemoteInitiator = false; + // revert adapter name + mAdapter.setName(deviceName); + } + @SafeVarargs private void verifyIntentReceived(Matcher... matchers) { mInOrder.verify(mReceiver, timeout(INTENT_TIMEOUT.toMillis())) -- GitLab From fc8e680af7d226e79fb4a10218ceca9c53e8b802 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 24 Oct 2024 02:16:25 -0700 Subject: [PATCH 485/875] A2dpSinkService: merge "start" into constructor Test: atest BluetoothInstrumentationTests Flag: Exempt refactor no-op Bug: 311772251 Change-Id: Ia4f2bbffc689310ac55b974c8627a039af373b9e --- .../bluetooth/a2dpsink/A2dpSinkService.java | 123 +++------- .../a2dpsink/A2dpSinkStateMachine.java | 164 ++++++------- .../a2dpsink/A2dpSinkStreamHandler.java | 7 +- .../bluetooth/a2dpsink/StackEvent.java | 6 - .../a2dpsink/A2dpSinkServiceTest.java | 228 ++++++++---------- .../a2dpsink/A2dpSinkStateMachineTest.java | 141 +++++------ .../bluetooth/a2dpsink/StackEventTest.java | 9 +- .../android/bluetooth/BluetoothA2dpSink.java | 30 +-- 8 files changed, 295 insertions(+), 413 deletions(-) diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java index b94a76001e5..5c8344bba3b 100644 --- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java +++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java @@ -27,8 +27,6 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetoothA2dpSink; import android.content.AttributionSource; -import android.content.Context; -import android.media.AudioManager; import android.os.Looper; import android.sysprop.BluetoothProperties; import android.util.Log; @@ -51,62 +49,43 @@ import java.util.concurrent.ConcurrentHashMap; public class A2dpSinkService extends ProfileService { private static final String TAG = A2dpSinkService.class.getSimpleName(); + private static A2dpSinkService sService; + // This is also used as a lock for shared data in {@link A2dpSinkService} @GuardedBy("mDeviceStateMap") private final Map mDeviceStateMap = new ConcurrentHashMap<>(1); + private final Object mActiveDeviceLock = new Object(); + private final Object mStreamHandlerLock = new Object(); + + private final AdapterService mAdapterService; + private final DatabaseManager mDatabaseManager; private final A2dpSinkNativeInterface mNativeInterface; private final Looper mLooper; + private final int mMaxConnectedAudioDevices; - private final Object mActiveDeviceLock = new Object(); + @GuardedBy("mStreamHandlerLock") + private final A2dpSinkStreamHandler mA2dpSinkStreamHandler; @GuardedBy("mActiveDeviceLock") private BluetoothDevice mActiveDevice = null; - private final Object mStreamHandlerLock = new Object(); - - @GuardedBy("mStreamHandlerLock") - private A2dpSinkStreamHandler mA2dpSinkStreamHandler; - - private static A2dpSinkService sService; - - private int mMaxConnectedAudioDevices; - - private AdapterService mAdapterService; - private DatabaseManager mDatabaseManager; - - public A2dpSinkService(Context ctx) { - super(ctx); - mNativeInterface = requireNonNull(A2dpSinkNativeInterface.getInstance()); - mLooper = Looper.getMainLooper(); + public A2dpSinkService(AdapterService adapterService) { + this(adapterService, A2dpSinkNativeInterface.getInstance(), Looper.getMainLooper()); } @VisibleForTesting - A2dpSinkService(Context ctx, A2dpSinkNativeInterface nativeInterface, Looper looper) { - super(ctx); + A2dpSinkService( + AdapterService adapterService, A2dpSinkNativeInterface nativeInterface, Looper looper) { + super(requireNonNull(adapterService)); + mAdapterService = adapterService; + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); mNativeInterface = requireNonNull(nativeInterface); mLooper = looper; - } - - public static boolean isEnabled() { - return BluetoothProperties.isProfileA2dpSinkEnabled().orElse(false); - } - - @Override - public void start() { - mAdapterService = - requireNonNull( - AdapterService.getAdapterService(), - "AdapterService cannot be null when A2dpSinkService starts"); - mDatabaseManager = - requireNonNull( - AdapterService.getAdapterService().getDatabase(), - "DatabaseManager cannot be null when A2dpSinkService starts"); mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices(); mNativeInterface.init(mMaxConnectedAudioDevices); - synchronized (mStreamHandlerLock) { mA2dpSinkStreamHandler = new A2dpSinkStreamHandler(this, mNativeInterface); } @@ -114,6 +93,10 @@ public class A2dpSinkService extends ProfileService { setA2dpSinkService(this); } + public static boolean isEnabled() { + return BluetoothProperties.isProfileA2dpSinkEnabled().orElse(false); + } + @Override public void stop() { setA2dpSinkService(null); @@ -125,10 +108,7 @@ public class A2dpSinkService extends ProfileService { mDeviceStateMap.clear(); } synchronized (mStreamHandlerLock) { - if (mA2dpSinkStreamHandler != null) { - mA2dpSinkStreamHandler.cleanup(); - mA2dpSinkStreamHandler = null; - } + mA2dpSinkStreamHandler.cleanup(); } } @@ -164,7 +144,6 @@ public class A2dpSinkService extends ProfileService { /** Request audio focus such that the designated device can stream audio */ public void requestAudioFocus(BluetoothDevice device, boolean request) { synchronized (mStreamHandlerLock) { - if (mA2dpSinkStreamHandler == null) return; mA2dpSinkStreamHandler.requestAudioFocus(request); } } @@ -176,17 +155,12 @@ public class A2dpSinkService extends ProfileService { */ public int getFocusState() { synchronized (mStreamHandlerLock) { - if (mA2dpSinkStreamHandler == null) return AudioManager.ERROR; return mA2dpSinkStreamHandler.getFocusState(); } } - @RequiresPermission(BLUETOOTH_PRIVILEGED) boolean isA2dpPlaying(BluetoothDevice device) { - enforceCallingOrSelfPermission( - BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); synchronized (mStreamHandlerLock) { - if (mA2dpSinkStreamHandler == null) return false; return mA2dpSinkStreamHandler.isPlaying(); } } @@ -309,6 +283,9 @@ public class A2dpSinkService extends ProfileService { if (service == null) { return false; } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.isA2dpPlaying(device); } @@ -407,19 +384,14 @@ public class A2dpSinkService extends ProfileService { } protected A2dpSinkStateMachine getOrCreateStateMachine(BluetoothDevice device) { - A2dpSinkStateMachine newStateMachine = - new A2dpSinkStateMachine(mLooper, device, this, mNativeInterface); synchronized (mDeviceStateMap) { - A2dpSinkStateMachine existingStateMachine = - mDeviceStateMap.putIfAbsent(device, newStateMachine); - // Given null is not a valid value in our map, ConcurrentHashMap will return null if the - // key was absent and our new value was added. We should then start and return it. Else - // we quit the new one so we don't leak a thread - if (existingStateMachine == null) { - newStateMachine.start(); - return newStateMachine; + A2dpSinkStateMachine sm = mDeviceStateMap.get(device); + if (sm != null) { + return sm; } - return existingStateMachine; + sm = new A2dpSinkStateMachine(this, device, mLooper, mNativeInterface); + mDeviceStateMap.put(device, sm); + return sm; } } @@ -469,8 +441,8 @@ public class A2dpSinkService extends ProfileService { stateMachine = mDeviceStateMap.get(device); } return (stateMachine == null) - ? BluetoothProfile.STATE_DISCONNECTED - : stateMachine.getState(); + ? BluetoothProfile.STATE_DISCONNECTED + : stateMachine.getState(); } /** @@ -543,18 +515,10 @@ public class A2dpSinkService extends ProfileService { /** Receive and route a stack event from the JNI */ protected void messageFromNative(StackEvent event) { switch (event.mType) { - case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - onConnectionStateChanged(event); - return; - case StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - onAudioStateChanged(event); - return; - case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED: - onAudioConfigChanged(event); - return; - default: - Log.e(TAG, "Received unknown stack event of type " + event.mType); - return; + case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> onConnectionStateChanged(event); + case StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED -> onAudioStateChanged(event); + case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED -> onAudioConfigChanged(event); + default -> Log.e(TAG, "Received unknown stack event of type " + event.mType); } } @@ -570,18 +534,11 @@ public class A2dpSinkService extends ProfileService { private void onAudioStateChanged(StackEvent event) { int state = event.mState; synchronized (mStreamHandlerLock) { - if (mA2dpSinkStreamHandler == null) { - Log.e(TAG, "Received audio state change before we've been started"); - return; - } else if (state == StackEvent.AUDIO_STATE_STARTED) { - mA2dpSinkStreamHandler - .obtainMessage(A2dpSinkStreamHandler.SRC_STR_START) - .sendToTarget(); + if (state == StackEvent.AUDIO_STATE_STARTED) { + mA2dpSinkStreamHandler.sendEmptyMessage(A2dpSinkStreamHandler.SRC_STR_START); } else if (state == StackEvent.AUDIO_STATE_STOPPED || state == StackEvent.AUDIO_STATE_REMOTE_SUSPEND) { - mA2dpSinkStreamHandler - .obtainMessage(A2dpSinkStreamHandler.SRC_STR_STOP) - .sendToTarget(); + mA2dpSinkStreamHandler.sendEmptyMessage(A2dpSinkStreamHandler.SRC_STR_STOP); } else { Log.w(TAG, "Unhandled audio state change, state=" + state); } diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java index 48cb1bb080c..18d956b594b 100644 --- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java +++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java @@ -17,6 +17,11 @@ 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_FORBIDDEN; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; import android.annotation.RequiresPermission; import android.bluetooth.BluetoothA2dpSink; @@ -41,15 +46,15 @@ class A2dpSinkStateMachine extends StateMachine { private static final String TAG = A2dpSinkStateMachine.class.getSimpleName(); // 0->99 Events from Outside - @VisibleForTesting static final int CONNECT = 1; - @VisibleForTesting static final int DISCONNECT = 2; + @VisibleForTesting static final int MESSAGE_CONNECT = 1; + @VisibleForTesting static final int MESSAGE_DISCONNECT = 2; // 100->199 Internal Events @VisibleForTesting static final int CLEANUP = 100; - @VisibleForTesting static final int CONNECT_TIMEOUT = 101; + @VisibleForTesting static final int MESSAGE_CONNECT_TIMEOUT = 101; // 200->299 Events from Native - @VisibleForTesting static final int STACK_EVENT = 200; + @VisibleForTesting static final int MESSAGE_STACK_EVENT = 200; static final int CONNECT_TIMEOUT_MS = 10000; @@ -62,13 +67,13 @@ class A2dpSinkStateMachine extends StateMachine { protected final Connected mConnected; protected final Disconnecting mDisconnecting; - protected int mMostRecentState = BluetoothProfile.STATE_DISCONNECTED; + protected int mMostRecentState = STATE_DISCONNECTED; protected BluetoothAudioConfig mAudioConfig = null; A2dpSinkStateMachine( - Looper looper, - BluetoothDevice device, A2dpSinkService service, + BluetoothDevice device, + Looper looper, A2dpSinkNativeInterface nativeInterface) { super(TAG, looper); mDevice = device; @@ -88,6 +93,7 @@ class A2dpSinkStateMachine extends StateMachine { setInitialState(mDisconnected); Log.d(TAG, "[" + mDevice + "] State machine created"); + start(); } /** @@ -115,17 +121,17 @@ class A2dpSinkStateMachine extends StateMachine { /** send the Connect command asynchronously */ final void connect() { - sendMessage(CONNECT); + sendMessage(MESSAGE_CONNECT); } /** send the Disconnect command asynchronously */ final void disconnect() { - sendMessage(DISCONNECT); + sendMessage(MESSAGE_DISCONNECT); } /** send the stack event asynchronously */ final void onStackEvent(StackEvent event) { - sendMessage(STACK_EVENT, event); + sendMessage(MESSAGE_STACK_EVENT, event); } /** @@ -154,56 +160,50 @@ class A2dpSinkStateMachine extends StateMachine { @Override public void enter() { Log.d(TAG, "[" + mDevice + "] Enter Disconnected"); - if (mMostRecentState != BluetoothProfile.STATE_DISCONNECTED) { + if (mMostRecentState != STATE_DISCONNECTED) { sendMessage(CLEANUP); } - onConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTED); + onConnectionStateChanged(STATE_DISCONNECTED); } @Override public boolean processMessage(Message message) { switch (message.what) { - case STACK_EVENT: - processStackEvent((StackEvent) message.obj); - return true; - case CONNECT: + case MESSAGE_STACK_EVENT -> processStackEvent((StackEvent) message.obj); + case MESSAGE_CONNECT -> { Log.d(TAG, "[" + mDevice + "] Connect"); transitionTo(mConnecting); - return true; - case CLEANUP: - mService.removeStateMachine(A2dpSinkStateMachine.this); - return true; + } + case CLEANUP -> mService.removeStateMachine(A2dpSinkStateMachine.this); + default -> { + return false; + } } - return false; + return true; } @RequiresPermission(BLUETOOTH_PRIVILEGED) void processStackEvent(StackEvent event) { - switch (event.mType) { - case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - switch (event.mState) { - case StackEvent.CONNECTION_STATE_CONNECTING: - if (mService.getConnectionPolicy(mDevice) - == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { - Log.w( - TAG, - "[" - + mDevice - + "] Ignore incoming connection, profile" - + " is turned off"); - mNativeInterface.disconnectA2dpSink(mDevice); - } else { - mConnecting.mIncomingConnection = true; - transitionTo(mConnecting); - } - break; - case StackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case StackEvent.CONNECTION_STATE_DISCONNECTED: - sendMessage(CLEANUP); - break; + if (event.mType != StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { + return; + } + switch (event.mState) { + case STATE_CONNECTING -> { + if (mService.getConnectionPolicy(mDevice) == CONNECTION_POLICY_FORBIDDEN) { + Log.w( + TAG, + "[" + + mDevice + + "] Ignore incoming connection, profile" + + " is turned off"); + mNativeInterface.disconnectA2dpSink(mDevice); + } else { + mConnecting.mIncomingConnection = true; + transitionTo(mConnecting); } + } + case STATE_CONNECTED -> transitionTo(mConnected); + case STATE_DISCONNECTED -> sendMessage(CLEANUP); } } } @@ -214,8 +214,8 @@ class A2dpSinkStateMachine extends StateMachine { @Override public void enter() { Log.d(TAG, "[" + mDevice + "] Enter Connecting"); - onConnectionStateChanged(BluetoothProfile.STATE_CONNECTING); - sendMessageDelayed(CONNECT_TIMEOUT, CONNECT_TIMEOUT_MS); + onConnectionStateChanged(STATE_CONNECTING); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT_MS); if (!mIncomingConnection) { mNativeInterface.connectA2dpSink(mDevice); @@ -227,13 +227,9 @@ class A2dpSinkStateMachine extends StateMachine { @Override public boolean processMessage(Message message) { switch (message.what) { - case STACK_EVENT: - processStackEvent((StackEvent) message.obj); - return true; - case CONNECT_TIMEOUT: - transitionTo(mDisconnected); - return true; - case DISCONNECT: + case MESSAGE_STACK_EVENT -> processStackEvent((StackEvent) message.obj); + case MESSAGE_CONNECT_TIMEOUT -> transitionTo(mDisconnected); + case MESSAGE_DISCONNECT -> { Log.d( TAG, "[" @@ -241,28 +237,27 @@ class A2dpSinkStateMachine extends StateMachine { + "] Received disconnect message while connecting." + "deferred"); deferMessage(message); - return true; + } + default -> { + return false; + } } - return false; + return true; } void processStackEvent(StackEvent event) { - switch (event.mType) { - case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - switch (event.mState) { - case StackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case StackEvent.CONNECTION_STATE_DISCONNECTED: - transitionTo(mDisconnected); - break; - } + if (event.mType != StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { + return; + } + switch (event.mState) { + case STATE_CONNECTED -> transitionTo(mConnected); + case STATE_DISCONNECTED -> transitionTo(mDisconnected); } } @Override public void exit() { - removeMessages(CONNECT_TIMEOUT); + removeMessages(MESSAGE_CONNECT_TIMEOUT); mIncomingConnection = false; } } @@ -271,42 +266,39 @@ class A2dpSinkStateMachine extends StateMachine { @Override public void enter() { Log.d(TAG, "[" + mDevice + "] Enter Connected"); - onConnectionStateChanged(BluetoothProfile.STATE_CONNECTED); + onConnectionStateChanged(STATE_CONNECTED); } @Override public boolean processMessage(Message message) { switch (message.what) { - case DISCONNECT: + case MESSAGE_DISCONNECT -> { transitionTo(mDisconnecting); mNativeInterface.disconnectA2dpSink(mDevice); - return true; - case STACK_EVENT: - processStackEvent((StackEvent) message.obj); - return true; + } + case MESSAGE_STACK_EVENT -> processStackEvent((StackEvent) message.obj); + default -> { + return false; + } } - return false; + return true; } void processStackEvent(StackEvent event) { switch (event.mType) { - case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { switch (event.mState) { - case StackEvent.CONNECTION_STATE_DISCONNECTING: - transitionTo(mDisconnecting); - break; - case StackEvent.CONNECTION_STATE_DISCONNECTED: - transitionTo(mDisconnected); - break; + case STATE_DISCONNECTING -> transitionTo(mDisconnecting); + case STATE_DISCONNECTED -> transitionTo(mDisconnected); } - break; - case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED: + } + case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED -> { mAudioConfig = new BluetoothAudioConfig( event.mSampleRate, event.mChannelCount, AudioFormat.ENCODING_PCM_16BIT); - break; + } } } } @@ -315,7 +307,7 @@ class A2dpSinkStateMachine extends StateMachine { @Override public void enter() { Log.d(TAG, "[" + mDevice + "] Enter Disconnecting"); - onConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTING); + onConnectionStateChanged(STATE_DISCONNECTING); transitionTo(mDisconnected); } } @@ -324,7 +316,7 @@ class A2dpSinkStateMachine extends StateMachine { if (mMostRecentState == currentState) { return; } - if (currentState == BluetoothProfile.STATE_CONNECTED) { + if (currentState == STATE_CONNECTED) { MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.A2DP_SINK); } Log.d(TAG, "[" + mDevice + "] Connection state: " + mMostRecentState + "->" + currentState); diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java index 6cf7d99643a..e62f924fda0 100644 --- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java +++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java @@ -70,9 +70,10 @@ public class A2dpSinkStreamHandler extends Handler { private static final int STATE_FOCUS_GRANTED = 1; // Private variables. - private A2dpSinkService mA2dpSinkService; - private A2dpSinkNativeInterface mNativeInterface; - private AudioManager mAudioManager; + private final A2dpSinkService mA2dpSinkService; + private final A2dpSinkNativeInterface mNativeInterface; + private final AudioManager mAudioManager; + // Keep track if the remote device is providing audio private boolean mStreamAvailable = false; // Keep track of the relevant audio focus (None, Transient, Gain) diff --git a/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java b/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java index 1a1429a0c5f..0c8859909a9 100644 --- a/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java +++ b/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java @@ -24,12 +24,6 @@ final class StackEvent { static final int EVENT_TYPE_AUDIO_STATE_CHANGED = 2; static final int EVENT_TYPE_AUDIO_CONFIG_CHANGED = 3; - // match up with btav_connection_state_t enum of bt_av.h - static final int CONNECTION_STATE_DISCONNECTED = 0; - static final int CONNECTION_STATE_CONNECTING = 1; - static final int CONNECTION_STATE_CONNECTED = 2; - static final int CONNECTION_STATE_DISCONNECTING = 3; - // match up with btav_audio_state_t enum of bt_av.h static final int AUDIO_STATE_REMOTE_SUSPEND = 0; static final int AUDIO_STATE_STOPPED = 1; diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java index 2503b164d9c..97a0aacc705 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java @@ -15,6 +15,12 @@ */ package com.android.bluetooth.a2dpsink; +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; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; @@ -26,11 +32,10 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.media.AudioFormat; +import android.media.AudioManager; import android.os.test.TestLooper; -import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; -import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; @@ -52,69 +57,44 @@ import java.util.List; @MediumTest @RunWith(AndroidJUnit4.class) public class A2dpSinkServiceTest { - private A2dpSinkService mService = null; - private BluetoothAdapter mAdapter = null; - private Context mTargetContext; - - @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @Mock private A2dpSinkNativeInterface mNativeInterface; - private BluetoothDevice mDevice1; - private BluetoothDevice mDevice2; - private BluetoothDevice mDevice3; - private BluetoothDevice mDevice4; - private BluetoothDevice mDevice5; - private BluetoothDevice mDevice6; - - private TestLooper mLooper; - private static final int TEST_SAMPLE_RATE = 44; private static final int TEST_CHANNEL_COUNT = 1; - @Before - public void setUp() throws Exception { - mTargetContext = InstrumentationRegistry.getTargetContext(); - - mLooper = new TestLooper(); + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice1 = mAdapter.getRemoteDevice("11:11:11:11:11:11"); + private final BluetoothDevice mDevice2 = mAdapter.getRemoteDevice("22:22:22:22:22:22"); - mAdapter = BluetoothAdapter.getDefaultAdapter(); - assertThat(mAdapter).isNotNull(); - mDevice1 = mAdapter.getRemoteDevice("11:11:11:11:11:11"); - mDevice2 = mAdapter.getRemoteDevice("22:22:22:22:22:22"); - mDevice3 = mAdapter.getRemoteDevice("33:33:33:33:33:33"); - mDevice4 = mAdapter.getRemoteDevice("44:44:44:44:44:44"); - mDevice5 = mAdapter.getRemoteDevice("55:55:55:55:55:55"); - mDevice6 = mAdapter.getRemoteDevice("66:66:66:66:66:66"); - BluetoothDevice[] bondedDevices = - new BluetoothDevice[] {mDevice1, mDevice2, mDevice3, mDevice4, mDevice5, mDevice6}; + private TestLooper mLooper; + private A2dpSinkService mService; - doReturn(true).when(mDatabaseManager).setProfileConnectionPolicy(any(), anyInt(), anyInt()); + @Before + public void setUp() throws Exception { + BluetoothDevice[] bondedDevices = new BluetoothDevice[] {mDevice1, mDevice2}; doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(bondedDevices).when(mAdapterService).getBondedDevices(); doReturn(1).when(mAdapterService).getMaxConnectedAudioDevices(); + TestUtils.mockGetSystemService(mAdapterService, Context.AUDIO_SERVICE, AudioManager.class); - TestUtils.setAdapterService(mAdapterService); + doReturn(true).when(mDatabaseManager).setProfileConnectionPolicy(any(), anyInt(), anyInt()); doReturn(true).when(mNativeInterface).setActiveDevice(any()); - mService = new A2dpSinkService(mTargetContext, mNativeInterface, mLooper.getLooper()); - mService.start(); - assertThat(mLooper.nextMessage()).isNull(); + mLooper = new TestLooper(); + + mService = new A2dpSinkService(mAdapterService, mNativeInterface, mLooper.getLooper()); } @After public void tearDown() throws Exception { - assertThat(mLooper.nextMessage()).isNull(); - mService.stop(); assertThat(A2dpSinkService.getA2dpSinkService()).isNull(); - TestUtils.clearAdapterService(mAdapterService); } private void syncHandler(int... what) { @@ -123,17 +103,15 @@ public class A2dpSinkServiceTest { private void setupDeviceConnection(BluetoothDevice device) { assertThat(mLooper.nextMessage()).isNull(); - assertThat(mService.getConnectionState(device)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mService.getConnectionState(device)).isEqualTo(STATE_DISCONNECTED); assertThat(mLooper.nextMessage()).isNull(); assertThat(mService.connect(device)).isTrue(); - syncHandler(-2 /* SM_INIT_CMD */, A2dpSinkStateMachine.CONNECT); - StackEvent nativeEvent = - StackEvent.connectionStateChanged(device, StackEvent.CONNECTION_STATE_CONNECTED); + syncHandler(-2 /* SM_INIT_CMD */, A2dpSinkStateMachine.MESSAGE_CONNECT); + StackEvent nativeEvent = StackEvent.connectionStateChanged(device, STATE_CONNECTED); mService.messageFromNative(nativeEvent); - syncHandler(A2dpSinkStateMachine.STACK_EVENT); - assertThat(mService.getConnectionState(device)).isEqualTo(BluetoothProfile.STATE_CONNECTED); + syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT); + assertThat(mService.getConnectionState(device)).isEqualTo(STATE_CONNECTED); } /** @@ -143,43 +121,48 @@ public class A2dpSinkServiceTest { * @param priority - The priority value you want the device to have */ private void mockDevicePriority(BluetoothDevice device, int priority) { - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.A2DP_SINK)) - .thenReturn(priority); + doReturn(priority) + .when(mDatabaseManager) + .getProfileConnectionPolicy(device, BluetoothProfile.A2DP_SINK); } /** Test that initialization of the service completes and that we can get a instance */ @Test public void testInitialize() { assertThat(A2dpSinkService.getA2dpSinkService()).isEqualTo(mService); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that asking to connect with a null device fails */ @Test public void testConnectNullDevice() { assertThrows(IllegalArgumentException.class, () -> mService.connect(null)); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that a CONNECTION_POLICY_ALLOWED device can connected */ @Test public void testConnectPolicyAllowedDevice() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that a CONNECTION_POLICY_FORBIDDEN device is not allowed to connect */ @Test public void testConnectPolicyForbiddenDevice() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + mockDevicePriority(mDevice1, CONNECTION_POLICY_FORBIDDEN); assertThat(mService.connect(mDevice1)).isFalse(); - assertThat(mService.getConnectionState(mDevice1)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that a CONNECTION_POLICY_UNKNOWN device is allowed to connect */ @Test public void testConnectPolicyUnknownDevice() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); + mockDevicePriority(mDevice1, CONNECTION_POLICY_UNKNOWN); setupDeviceConnection(mDevice1); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that we can connect multiple devices */ @@ -187,44 +170,40 @@ public class A2dpSinkServiceTest { public void testConnectMultipleDevices() { doReturn(5).when(mAdapterService).getMaxConnectedAudioDevices(); - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - mockDevicePriority(mDevice2, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - mockDevicePriority(mDevice3, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - mockDevicePriority(mDevice4, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - mockDevicePriority(mDevice5, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - mockDevicePriority(mDevice6, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice2, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); setupDeviceConnection(mDevice2); - setupDeviceConnection(mDevice3); - setupDeviceConnection(mDevice4); - setupDeviceConnection(mDevice5); + assertThat(mLooper.nextMessage()).isNull(); } /** Test to make sure we can disconnect a connected device */ @Test public void testDisconnect() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); assertThat(mService.disconnect(mDevice1)).isTrue(); - syncHandler(A2dpSinkStateMachine.DISCONNECT); - assertThat(mService.getConnectionState(mDevice1)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT); + assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */); + assertThat(mLooper.nextMessage()).isNull(); } /** Assure disconnect() fails with a device that's not connected */ @Test public void testDisconnectDeviceDoesNotExist() { assertThat(mService.disconnect(mDevice1)).isFalse(); + assertThat(mLooper.nextMessage()).isNull(); } /** Assure disconnect() fails with an invalid device */ @Test public void testDisconnectNullDevice() { assertThrows(IllegalArgumentException.class, () -> mService.disconnect(null)); + assertThat(mLooper.nextMessage()).isNull(); } /** Assure dump() returns something and does not crash */ @@ -233,6 +212,7 @@ public class A2dpSinkServiceTest { StringBuilder sb = new StringBuilder(); mService.dump(sb); assertThat(sb.toString()).isNotNull(); + assertThat(mLooper.nextMessage()).isNull(); } /** @@ -241,10 +221,11 @@ public class A2dpSinkServiceTest { */ @Test public void testSetActiveDevice() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); assertThat(mService.getActiveDevice()).isNotEqualTo(mDevice1); assertThat(mService.setActiveDevice(mDevice1)).isTrue(); assertThat(mService.getActiveDevice()).isEqualTo(mDevice1); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that calls to set a null active device succeed in unsetting the active device */ @@ -252,24 +233,26 @@ public class A2dpSinkServiceTest { public void testSetActiveDeviceNullDevice() { assertThat(mService.setActiveDevice(null)).isTrue(); assertThat(mService.getActiveDevice()).isNull(); + assertThat(mLooper.nextMessage()).isNull(); } /** Make sure we can receive the set audio configuration */ @Test public void testGetAudioConfiguration() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); StackEvent audioConfigChanged = StackEvent.audioConfigChanged(mDevice1, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT); mService.messageFromNative(audioConfigChanged); - syncHandler(A2dpSinkStateMachine.STACK_EVENT); + syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT); BluetoothAudioConfig expected = new BluetoothAudioConfig( TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT, AudioFormat.ENCODING_PCM_16BIT); BluetoothAudioConfig config = mService.getAudioConfig(mDevice1); assertThat(config).isEqualTo(expected); + assertThat(mLooper.nextMessage()).isNull(); } /** Make sure we ignore audio configuration changes for disconnected/unknown devices */ @@ -279,31 +262,34 @@ public class A2dpSinkServiceTest { StackEvent.audioConfigChanged(null, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT); mService.messageFromNative(audioConfigChanged); assertThat(mService.getAudioConfig(null)).isNull(); + assertThat(mLooper.nextMessage()).isNull(); } /** Make sure we ignore audio configuration changes for disconnected/unknown devices */ @Test public void testOnAudioConfigChanged_withUnknownDevice_eventDropped() { - assertThat(mService.getConnectionState(mDevice1)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED); StackEvent audioConfigChanged = StackEvent.audioConfigChanged(mDevice1, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT); mService.messageFromNative(audioConfigChanged); assertThat(mService.getAudioConfig(mDevice1)).isNull(); + assertThat(mLooper.nextMessage()).isNull(); } /** Getting an audio config for a device that hasn't received one yet should return null */ @Test public void testGetAudioConfigWithConfigUnset() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); assertThat(mService.getAudioConfig(mDevice1)).isNull(); + assertThat(mLooper.nextMessage()).isNull(); } /** Getting an audio config for a null device should return null */ @Test public void testGetAudioConfigNullDevice() { assertThat(mService.getAudioConfig(null)).isNull(); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that a newly connected device ends up in the set returned by getConnectedDevices */ @@ -312,11 +298,12 @@ public class A2dpSinkServiceTest { ArrayList expected = new ArrayList(); expected.add(mDevice1); - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); List devices = mService.getConnectedDevices(); assertThat(devices).isEqualTo(expected); + assertThat(mLooper.nextMessage()).isNull(); } /** @@ -327,13 +314,13 @@ public class A2dpSinkServiceTest { public void testGetDevicesMatchingConnectionStatesConnected() { ArrayList expected = new ArrayList(); expected.add(mDevice1); - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); List devices = - mService.getDevicesMatchingConnectionStates( - new int[] {BluetoothProfile.STATE_CONNECTED}); + mService.getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}); assertThat(devices).isEqualTo(expected); + assertThat(mLooper.nextMessage()).isNull(); } /** @@ -345,67 +332,55 @@ public class A2dpSinkServiceTest { ArrayList expected = new ArrayList(); expected.add(mDevice1); expected.add(mDevice2); - expected.add(mDevice3); - expected.add(mDevice4); - expected.add(mDevice5); - expected.add(mDevice6); List devices = - mService.getDevicesMatchingConnectionStates( - new int[] {BluetoothProfile.STATE_DISCONNECTED}); + mService.getDevicesMatchingConnectionStates(new int[] {STATE_DISCONNECTED}); assertThat(devices).isEqualTo(expected); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that GetConnectionPolicy() can get a device with policy "Allowed" */ @Test public void testGetConnectionPolicyDeviceAllowed() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - assertThat(mService.getConnectionPolicy(mDevice1)) - .isEqualTo(BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); + assertThat(mService.getConnectionPolicy(mDevice1)).isEqualTo(CONNECTION_POLICY_ALLOWED); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that GetConnectionPolicy() can get a device with policy "Forbidden" */ @Test public void testGetConnectionPolicyDeviceForbidden() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - assertThat(mService.getConnectionPolicy(mDevice1)) - .isEqualTo(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + mockDevicePriority(mDevice1, CONNECTION_POLICY_FORBIDDEN); + assertThat(mService.getConnectionPolicy(mDevice1)).isEqualTo(CONNECTION_POLICY_FORBIDDEN); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that GetConnectionPolicy() can get a device with policy "Unknown" */ @Test public void testGetConnectionPolicyDeviceUnknown() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - assertThat(mService.getConnectionPolicy(mDevice1)) - .isEqualTo(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); + mockDevicePriority(mDevice1, CONNECTION_POLICY_UNKNOWN); + assertThat(mService.getConnectionPolicy(mDevice1)).isEqualTo(CONNECTION_POLICY_UNKNOWN); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that SetConnectionPolicy() can change a device's policy to "Allowed" */ @Test public void testSetConnectionPolicyDeviceAllowed() { - assertThat( - mService.setConnectionPolicy( - mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED)) - .isTrue(); + assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_ALLOWED)).isTrue(); verify(mDatabaseManager) .setProfileConnectionPolicy( - mDevice1, - BluetoothProfile.A2DP_SINK, - BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_ALLOWED); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that SetConnectionPolicy() can change a device's policy to "Forbidden" */ @Test public void testSetConnectionPolicyDeviceForbiddenWhileNotConnected() { - assertThat( - mService.setConnectionPolicy( - mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) - .isTrue(); + assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_FORBIDDEN)).isTrue(); verify(mDatabaseManager) .setProfileConnectionPolicy( - mDevice1, - BluetoothProfile.A2DP_SINK, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_FORBIDDEN); + assertThat(mLooper.nextMessage()).isNull(); } /** @@ -414,57 +389,48 @@ public class A2dpSinkServiceTest { */ @Test public void testSetConnectionPolicyDeviceForbiddenWhileConnected() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); - assertThat( - mService.setConnectionPolicy( - mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) - .isTrue(); + assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_FORBIDDEN)).isTrue(); verify(mDatabaseManager) .setProfileConnectionPolicy( - mDevice1, - BluetoothProfile.A2DP_SINK, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_FORBIDDEN); - syncHandler(A2dpSinkStateMachine.DISCONNECT); + syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT); verify(mNativeInterface).disconnectA2dpSink(eq(mDevice1)); - assertThat(mService.getConnectionState(mDevice1)) - .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that SetConnectionPolicy() can change a device's policy to "Unknown" */ @Test public void testSetConnectionPolicyDeviceUnknown() { - assertThat( - mService.setConnectionPolicy( - mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN)) - .isTrue(); + assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_UNKNOWN)).isTrue(); verify(mDatabaseManager) .setProfileConnectionPolicy( - mDevice1, - BluetoothProfile.A2DP_SINK, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN); + mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_UNKNOWN); + assertThat(mLooper.nextMessage()).isNull(); } /** Test that SetConnectionPolicy is robust to DatabaseManager failures */ @Test public void testSetConnectionPolicyDatabaseWriteFails() { - when(mDatabaseManager.setProfileConnectionPolicy(any(), anyInt(), anyInt())) - .thenReturn(false); - assertThat( - mService.setConnectionPolicy( - mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED)) - .isFalse(); + doReturn(false) + .when(mDatabaseManager) + .setProfileConnectionPolicy(any(), anyInt(), anyInt()); + assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_ALLOWED)).isFalse(); + assertThat(mLooper.nextMessage()).isNull(); } @Test public void testDumpDoesNotCrash() { - mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED); setupDeviceConnection(mDevice1); mService.dump(new StringBuilder()); + assertThat(mLooper.nextMessage()).isNull(); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java index 55aeb0b515f..c635bfa4b44 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java @@ -15,10 +15,13 @@ */ package com.android.bluetooth.a2dpsink; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; + import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -45,46 +48,33 @@ import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class A2dpSinkStateMachineTest { - private static final String DEVICE_ADDRESS = "11:11:11:11:11:11"; - private static final int UNHANDLED_MESSAGE = 9999; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private A2dpSinkService mService; @Mock private A2dpSinkNativeInterface mNativeInterface; + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = mAdapter.getRemoteDevice("11:11:11:11:11:11"); + private A2dpSinkStateMachine mStateMachine; - private BluetoothAdapter mAdapter; - private BluetoothDevice mDevice; private TestLooper mLooper; @Before public void setUp() throws Exception { mLooper = new TestLooper(); - mAdapter = BluetoothAdapter.getDefaultAdapter(); - assertThat(mAdapter).isNotNull(); - mDevice = mAdapter.getRemoteDevice(DEVICE_ADDRESS); - - doNothing().when(mService).removeStateMachine(any(A2dpSinkStateMachine.class)); - mStateMachine = - new A2dpSinkStateMachine(mLooper.getLooper(), mDevice, mService, mNativeInterface); - mStateMachine.start(); + new A2dpSinkStateMachine(mService, mDevice, mLooper.getLooper(), mNativeInterface); syncHandler(-2 /* SM_INIT_CMD */); assertThat(mStateMachine.getDevice()).isEqualTo(mDevice); assertThat(mStateMachine.getAudioConfig()).isNull(); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); } @After public void tearDown() throws Exception { assertThat(mLooper.nextMessage()).isNull(); - - mStateMachine = null; - mDevice = null; - mAdapter = null; } private void syncHandler(int... what) { @@ -97,16 +87,16 @@ public class A2dpSinkStateMachineTest { private void sendConnectionEvent(int state) { mStateMachine.sendMessage( - A2dpSinkStateMachine.STACK_EVENT, + A2dpSinkStateMachine.MESSAGE_STACK_EVENT, StackEvent.connectionStateChanged(mDevice, state)); - syncHandler(A2dpSinkStateMachine.STACK_EVENT); + syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT); } private void sendAudioConfigChangedEvent(int sampleRate, int channelCount) { mStateMachine.sendMessage( - A2dpSinkStateMachine.STACK_EVENT, + A2dpSinkStateMachine.MESSAGE_STACK_EVENT, StackEvent.audioConfigChanged(mDevice, sampleRate, channelCount)); - syncHandler(A2dpSinkStateMachine.STACK_EVENT); + syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT); } /********************************************************************************************** @@ -116,37 +106,37 @@ public class A2dpSinkStateMachineTest { @Test public void testConnectInDisconnected() { mStateMachine.connect(); - syncHandler(A2dpSinkStateMachine.CONNECT); + syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT); verify(mNativeInterface).connectA2dpSink(mDevice); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); } @Test public void testDisconnectInDisconnected() { mStateMachine.disconnect(); - syncHandler(A2dpSinkStateMachine.DISCONNECT); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); } @Test public void testAudioConfigChangedInDisconnected() { sendAudioConfigChangedEvent(44, 1); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); assertThat(mStateMachine.getAudioConfig()).isNull(); } @Test public void testIncomingConnectedInDisconnected() { - sendConnectionEvent(BluetoothProfile.STATE_CONNECTED); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + sendConnectionEvent(STATE_CONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); } @Test public void testAllowedIncomingConnectionInDisconnected() { mockDeviceConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - sendConnectionEvent(BluetoothProfile.STATE_CONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + sendConnectionEvent(STATE_CONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); verify(mNativeInterface, times(0)).connectA2dpSink(mDevice); } @@ -154,24 +144,24 @@ public class A2dpSinkStateMachineTest { public void testForbiddenIncomingConnectionInDisconnected() { mockDeviceConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - sendConnectionEvent(BluetoothProfile.STATE_CONNECTING); + sendConnectionEvent(STATE_CONNECTING); verify(mNativeInterface).disconnectA2dpSink(mDevice); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); } @Test public void testUnknownIncomingConnectionInDisconnected() { mockDeviceConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - sendConnectionEvent(BluetoothProfile.STATE_CONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + sendConnectionEvent(STATE_CONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); verify(mNativeInterface, times(0)).connectA2dpSink(mDevice); } @Test public void testIncomingDisconnectInDisconnected() { - sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTED); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + sendConnectionEvent(STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP); verify(mService).removeStateMachine(mStateMachine); @@ -179,19 +169,20 @@ public class A2dpSinkStateMachineTest { @Test public void testIncomingDisconnectingInDisconnected() { - sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + sendConnectionEvent(STATE_DISCONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); verify(mService, times(0)).removeStateMachine(mStateMachine); } @Test public void testIncomingConnectingInDisconnected() { - sendConnectionEvent(BluetoothProfile.STATE_CONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + sendConnectionEvent(STATE_CONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); } @Test public void testUnhandledMessageInDisconnected() { + final int UNHANDLED_MESSAGE = 9999; mStateMachine.sendMessage(UNHANDLED_MESSAGE); mStateMachine.sendMessage(UNHANDLED_MESSAGE, 0 /* arbitrary payload */); syncHandler(UNHANDLED_MESSAGE, UNHANDLED_MESSAGE); @@ -205,32 +196,32 @@ public class A2dpSinkStateMachineTest { public void testConnectedInConnecting() { testConnectInDisconnected(); - sendConnectionEvent(BluetoothProfile.STATE_CONNECTED); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + sendConnectionEvent(STATE_CONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); } @Test public void testConnectingInConnecting() { testConnectInDisconnected(); - sendConnectionEvent(BluetoothProfile.STATE_CONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + sendConnectionEvent(STATE_CONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); } @Test public void testDisconnectingInConnecting() { testConnectInDisconnected(); - sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + sendConnectionEvent(STATE_DISCONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); } @Test public void testDisconnectedInConnecting() { testConnectInDisconnected(); - sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTED); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + sendConnectionEvent(STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP); verify(mService).removeStateMachine(mStateMachine); @@ -241,8 +232,8 @@ public class A2dpSinkStateMachineTest { testConnectInDisconnected(); mLooper.moveTimeForward(120_000); // Skip time so the timeout fires - syncHandler(A2dpSinkStateMachine.CONNECT_TIMEOUT); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT_TIMEOUT); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP); verify(mService).removeStateMachine(mStateMachine); @@ -253,7 +244,7 @@ public class A2dpSinkStateMachineTest { testConnectInDisconnected(); sendAudioConfigChangedEvent(44, 1); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); assertThat(mStateMachine.getAudioConfig()).isNull(); } @@ -262,8 +253,8 @@ public class A2dpSinkStateMachineTest { testConnectInDisconnected(); mStateMachine.connect(); - syncHandler(A2dpSinkStateMachine.CONNECT); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); } @Test @@ -271,16 +262,16 @@ public class A2dpSinkStateMachineTest { testConnectInDisconnected(); mStateMachine.disconnect(); - syncHandler(A2dpSinkStateMachine.DISCONNECT); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); + syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); // send connected, disconnect should get processed - sendConnectionEvent(BluetoothProfile.STATE_CONNECTED); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + sendConnectionEvent(STATE_CONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); - syncHandler(A2dpSinkStateMachine.DISCONNECT); // message was defer + syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT); // message was defer verify(mNativeInterface).disconnectA2dpSink(mDevice); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP); verify(mService).removeStateMachine(mStateMachine); @@ -295,8 +286,8 @@ public class A2dpSinkStateMachineTest { testConnectedInConnecting(); mStateMachine.connect(); - syncHandler(A2dpSinkStateMachine.CONNECT); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); } @Test @@ -304,9 +295,9 @@ public class A2dpSinkStateMachineTest { testConnectedInConnecting(); mStateMachine.disconnect(); - syncHandler(A2dpSinkStateMachine.DISCONNECT); + syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT); verify(mNativeInterface).disconnectA2dpSink(mDevice); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP); verify(mService).removeStateMachine(mStateMachine); @@ -317,7 +308,7 @@ public class A2dpSinkStateMachineTest { testConnectedInConnecting(); sendAudioConfigChangedEvent(44, 1); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); BluetoothAudioConfig expected = new BluetoothAudioConfig(44, 1, AudioFormat.ENCODING_PCM_16BIT); @@ -328,24 +319,24 @@ public class A2dpSinkStateMachineTest { public void testConnectedInConnected() { testConnectedInConnecting(); - sendConnectionEvent(BluetoothProfile.STATE_CONNECTED); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + sendConnectionEvent(STATE_CONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); } @Test public void testConnectingInConnected() { testConnectedInConnecting(); - sendConnectionEvent(BluetoothProfile.STATE_CONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + sendConnectionEvent(STATE_CONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); } @Test public void testDisconnectingInConnected() { testConnectedInConnecting(); - sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTING); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + sendConnectionEvent(STATE_DISCONNECTING); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP); verify(mService).removeStateMachine(mStateMachine); @@ -355,8 +346,8 @@ public class A2dpSinkStateMachineTest { public void testDisconnectedInConnected() { testConnectedInConnecting(); - sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTED); - assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + sendConnectionEvent(STATE_DISCONNECTED); + assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP); verify(mService).removeStateMachine(mStateMachine); diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java index 7f733804b8a..1f19faab424 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java @@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; import androidx.test.runner.AndroidJUnit4; @@ -48,22 +49,22 @@ public class StackEventTest { @Test public void testCreateConnectionStateChangedDisconnectedEvent() { - testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_DISCONNECTED); + testConnectionStateChangedBase(BluetoothProfile.STATE_DISCONNECTED); } @Test public void testCreateConnectionStateChangedConnectingEvent() { - testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_CONNECTING); + testConnectionStateChangedBase(BluetoothProfile.STATE_CONNECTING); } @Test public void testCreateConnectionStateChangedConnectedEvent() { - testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_CONNECTED); + testConnectionStateChangedBase(BluetoothProfile.STATE_CONNECTED); } @Test public void testCreateConnectionStateChangedDisconnectingEvent() { - testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_DISCONNECTING); + testConnectionStateChangedBase(BluetoothProfile.STATE_DISCONNECTING); } private void testConnectionStateChangedBase(int state) { diff --git a/framework/java/android/bluetooth/BluetoothA2dpSink.java b/framework/java/android/bluetooth/BluetoothA2dpSink.java index 166b4a45b98..ecaa9d33d71 100644 --- a/framework/java/android/bluetooth/BluetoothA2dpSink.java +++ b/framework/java/android/bluetooth/BluetoothA2dpSink.java @@ -138,11 +138,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * @hide */ @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothA2dpSink service = getService(); @@ -311,11 +307,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * @hide */ @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority)); @@ -367,11 +359,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * @hide */ @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device)); @@ -389,11 +377,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothA2dpSink service = getService(); @@ -419,11 +403,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ @SystemApi @RequiresBluetoothConnectPermission - @RequiresPermission( - allOf = { - BLUETOOTH_CONNECT, - BLUETOOTH_PRIVILEGED, - }) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean isAudioPlaying(@NonNull BluetoothDevice device) { if (VDBG) log("isAudioPlaying(" + device + ")"); final IBluetoothA2dpSink service = getService(); -- GitLab From d55576b2a649276e96014ec5349d54a1b8b406e9 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 21 Oct 2024 18:13:37 -0700 Subject: [PATCH 486/875] Framework VCP: use wrapper for readability Bug: 311772251 Test: m Bluetooth Flag: Exempt refactor Change-Id: Ib2fd9157f04b5c12d08d1cd0cd7fefd1029abbd5 --- .../bluetooth/BluetoothVolumeControl.java | 201 +++++++----------- 1 file changed, 80 insertions(+), 121 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java index 1e07043c641..983802d8172 100644 --- a/framework/java/android/bluetooth/BluetoothVolumeControl.java +++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java @@ -19,6 +19,7 @@ package android.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.callServiceIfEnabled; import static android.bluetooth.BluetoothUtils.executeFromBinder; import static java.util.Objects.requireNonNull; @@ -43,6 +44,7 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -327,18 +329,15 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull List getConnectedDevices() { Log.d(TAG, "getConnectedDevices()"); - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled()) { - try { - return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } - return Collections.emptyList(); + List defaultValue = Collections.emptyList(); + + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> + Attributable.setAttributionSource( + s.getConnectedDevices(mAttributionSource), mAttributionSource), + defaultValue); } /** @@ -351,20 +350,17 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public List getDevicesMatchingConnectionStates(int[] states) { - Log.d(TAG, "getDevicesMatchingStates()"); - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled()) { - try { - return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), - mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } - return Collections.emptyList(); + Log.d(TAG, "getDevicesMatchingStates(" + Arrays.toString(states) + ")"); + List defaultValue = Collections.emptyList(); + + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> + Attributable.setAttributionSource( + s.getDevicesMatchingConnectionStates(states, mAttributionSource), + mAttributionSource), + defaultValue); } /** @@ -378,17 +374,16 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresPermission(BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { Log.d(TAG, "getConnectionState(" + device + ")"); - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + + if (!isValidDevice(device)) { + return defaultValue; } - return BluetoothProfile.STATE_DISCONNECTED; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getConnectionState(device, mAttributionSource), + defaultValue); } /** @@ -553,26 +548,16 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @NonNull BluetoothDevice device, @IntRange(from = 1, to = 255) int instanceId, @IntRange(from = -255, to = 255) int volumeOffset) { + Log.d(TAG, "setVolumeOffset(" + device + ", " + instanceId + ", " + volumeOffset + ")"); + requireNonNull(device); - Log.d( - TAG, - "setVolumeOffset(" - + device - + "/" - + instanceId - + " volumeOffset: " - + volumeOffset - + ")"); - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled()) { - try { - service.setVolumeOffset(device, instanceId, volumeOffset, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + if (!isValidDevice(device)) { + return; } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.setVolumeOffset(device, instanceId, volumeOffset, mAttributionSource)); } /** @@ -588,25 +573,18 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean isVolumeOffsetAvailable(@NonNull BluetoothDevice device) { - requireNonNull(device); Log.d(TAG, "isVolumeOffsetAvailable(" + device + ")"); - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - return false; - } - - if (!mAdapter.isEnabled()) { - return false; - } + final boolean defaultValue = false; - try { - return service.isVolumeOffsetAvailable(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + requireNonNull(device); + if (!isValidDevice(device)) { + return defaultValue; } - - return false; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.isVolumeOffsetAvailable(device, mAttributionSource), + defaultValue); } /** @@ -620,26 +598,18 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresBluetoothConnectPermission @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public int getNumberOfVolumeOffsetInstances(@NonNull BluetoothDevice device) { - requireNonNull(device); Log.d(TAG, "getNumberOfVolumeOffsetInstances(" + device + ")"); - final IBluetoothVolumeControl service = getService(); final int defaultValue = 0; - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - return defaultValue; - } - - if (!mAdapter.isEnabled()) { + requireNonNull(device); + if (!isValidDevice(device)) { return defaultValue; } - try { - return service.getNumberOfVolumeOffsetInstances(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - - return defaultValue; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getNumberOfVolumeOffsetInstances(device, mAttributionSource), + defaultValue); } /** @@ -660,28 +630,22 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose public boolean setConnectionPolicy( @NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled() - && isValidDevice(device) - && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { - try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + boolean defaultValue = false; + if (!isValidDevice(device) + || (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + return defaultValue; } - return false; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.setConnectionPolicy(device, connectionPolicy, mAttributionSource), + defaultValue); } /** * Get the connection policy of the profile. * - *

    The connection policy can be any of: {@link #CONNECTION_POLICY_ALLOWED}, {@link - * #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN} - * * @param device Bluetooth device * @return connection policy of the device * @hide @@ -691,17 +655,15 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { Log.v(TAG, "getConnectionPolicy(" + device + ")"); - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { - try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } + int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (!isValidDevice(device)) { + return defaultValue; } - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.getConnectionPolicy(device, mAttributionSource), + defaultValue); } /** @@ -730,19 +692,16 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @IntRange(from = 0, to = 255) int volume, boolean isGroupOperation) { requireNonNull(device); + if (!isValidDevice(device)) { + return; + } if (volume < 0 || volume > 255) { throw new IllegalArgumentException("illegal volume " + volume); } - final IBluetoothVolumeControl service = getService(); - if (service == null) { - Log.d(TAG, "Proxy not attached to service" + Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled()) { - try { - service.setDeviceVolume(device, volume, isGroupOperation, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } + callServiceIfEnabled( + mAdapter, + this::getService, + s -> s.setDeviceVolume(device, volume, isGroupOperation, mAttributionSource)); } private static boolean isValidDevice(@Nullable BluetoothDevice device) { -- GitLab From 748e0f7b692f3238432ac0783fc1bbcb252a057b Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 24 Oct 2024 02:37:28 -0700 Subject: [PATCH 487/875] AvrcpTargetService: merge "start" into constructor Test: atest BluetoothInstrumentationTests Flag: Exempt refactor no-op Bug: 311772251 Change-Id: I4478af39b44c7c40492a88b7ae80f7da77eda797 --- .../bluetooth/avrcp/AvrcpTargetService.java | 193 ++++++++---------- 1 file changed, 82 insertions(+), 111 deletions(-) diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java index 17bf92f8ecc..93579a845c9 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java @@ -16,6 +16,8 @@ package com.android.bluetooth.avrcp; +import static java.util.Objects.requireNonNull; + import android.annotation.NonNull; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; @@ -62,14 +64,18 @@ public class AvrcpTargetService extends ProfileService { private final BluetoothEventLogger mMediaKeyEventLogger = new BluetoothEventLogger(MEDIA_KEY_EVENT_LOGGER_SIZE, MEDIA_KEY_EVENT_LOGGER_TITLE); - private AvrcpVersion mAvrcpVersion; - private MediaPlayerList mMediaPlayerList; - private PlayerSettingsManager mPlayerSettingsManager; - private AudioManager mAudioManager; - private AvrcpBroadcastReceiver mReceiver; - private AvrcpNativeInterface mNativeInterface; - private AvrcpVolumeManager mVolumeManager; - private ServiceFactory mFactory = new ServiceFactory(); + // Cover Art Service (Storage + BIP Server) + private final AvrcpCoverArtService mAvrcpCoverArtService; + private final AdapterService mAdapterService; + private final AvrcpVersion mAvrcpVersion; + private final MediaPlayerList mMediaPlayerList; + private final PlayerSettingsManager mPlayerSettingsManager; + private final AudioManager mAudioManager; + private final AvrcpBroadcastReceiver mReceiver; + private final AvrcpNativeInterface mNativeInterface; + private final AvrcpVolumeManager mVolumeManager; + + private final ServiceFactory mFactory = new ServiceFactory(); private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() { @Override @@ -84,24 +90,65 @@ public class AvrcpTargetService extends ProfileService { Log.e(TAG, "userChangeReceiver received an invalid EXTRA_USER_HANDLE"); return; } - if (mMediaPlayerList != null) { - mMediaPlayerList.init(new ListCallback()); - } + mMediaPlayerList.init(new ListCallback()); } }; // Only used to see if the metadata has changed from its previous value private MediaData mCurrentData; - // Cover Art Service (Storage + BIP Server) - private AvrcpCoverArtService mAvrcpCoverArtService = null; - private static AvrcpTargetService sInstance = null; - private final AdapterService mAdapterService; public AvrcpTargetService(AdapterService adapterService) { - super(adapterService); + super(requireNonNull(adapterService)); mAdapterService = adapterService; + mAudioManager = requireNonNull(getSystemService(AudioManager.class)); + mNativeInterface = requireNonNull(AvrcpNativeInterface.getInstance()); + + mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this); + + IntentFilter userFilter = new IntentFilter(); + userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + userFilter.addAction(Intent.ACTION_USER_UNLOCKED); + getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter); + + Log.i(TAG, "Starting the AVRCP Target Service"); + mCurrentData = new MediaData(null, null, null); + + mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this); + mNativeInterface.init(this); + + mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue(); + mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface); + + UserManager userManager = getApplicationContext().getSystemService(UserManager.class); + if (userManager.isUserUnlocked()) { + mMediaPlayerList.init(new ListCallback()); + } + + if (!getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) { + mAvrcpCoverArtService = null; + } else if (!mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) { + Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art"); + mAvrcpCoverArtService = null; + } else { + AvrcpCoverArtService coverArtService = new AvrcpCoverArtService(); + if (coverArtService.start()) { + mAvrcpCoverArtService = coverArtService; + } else { + Log.e(TAG, "Failed to start cover art service"); + mAvrcpCoverArtService = null; + } + } + + mReceiver = new AvrcpBroadcastReceiver(); + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(AudioManager.ACTION_VOLUME_CHANGED); + registerReceiver(mReceiver, filter); + + // Only allow the service to be used once it is initialized + sInstance = this; } /** Checks for profile enabled state in Bluetooth sysprops. */ @@ -113,8 +160,6 @@ public class AvrcpTargetService extends ProfileService { class ListCallback implements MediaPlayerList.MediaUpdateCallback { @Override public void run(MediaData data) { - if (mNativeInterface == null) return; - boolean metadata = !Objects.equals(mCurrentData.metadata, data.metadata); boolean state = !MediaPlayerWrapper.playstateEquals(mCurrentData.state, data.state); boolean queue = isQueueUpdated(mCurrentData.queue, data.queue); @@ -134,8 +179,6 @@ public class AvrcpTargetService extends ProfileService { @Override public void run(boolean availablePlayers, boolean addressedPlayers, boolean uids) { - if (mNativeInterface == null) return; - mNativeInterface.sendFolderUpdate(availablePlayers, addressedPlayers, uids); } } @@ -148,17 +191,18 @@ public class AvrcpTargetService extends ProfileService { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(AudioManager.ACTION_VOLUME_CHANGED)) { - int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); - if (streamType == AudioManager.STREAM_MUSIC) { - int volume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); - BluetoothDevice activeDevice = getA2dpActiveDevice(); - if (activeDevice != null - && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) { - Log.d(TAG, "stream volume change to " + volume + " " + activeDevice); - mVolumeManager.storeVolumeForDevice(activeDevice, volume); - } - } + if (!action.equals(AudioManager.ACTION_VOLUME_CHANGED)) { + return; + } + int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); + if (streamType != AudioManager.STREAM_MUSIC) { + return; + } + int volume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); + BluetoothDevice activeDevice = getA2dpActiveDevice(); + if (activeDevice != null && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) { + Log.d(TAG, "stream volume change to " + volume + " " + activeDevice); + mVolumeManager.storeVolumeForDevice(activeDevice, volume); } } } @@ -193,61 +237,6 @@ public class AvrcpTargetService extends ProfileService { return null; } - @Override - public void start() { - if (sInstance != null) { - throw new IllegalStateException("start() called twice"); - } - - IntentFilter userFilter = new IntentFilter(); - userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - userFilter.addAction(Intent.ACTION_USER_UNLOCKED); - getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter); - - Log.i(TAG, "Starting the AVRCP Target Service"); - mCurrentData = new MediaData(null, null, null); - - mAudioManager = getSystemService(AudioManager.class); - - mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this); - - mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this); - - mNativeInterface = AvrcpNativeInterface.getInstance(); - mNativeInterface.init(AvrcpTargetService.this); - - mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue(); - - mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface); - - UserManager userManager = getApplicationContext().getSystemService(UserManager.class); - if (userManager.isUserUnlocked()) { - mMediaPlayerList.init(new ListCallback()); - } - - if (getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) { - if (mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) { - mAvrcpCoverArtService = new AvrcpCoverArtService(); - boolean started = mAvrcpCoverArtService.start(); - if (!started) { - Log.e(TAG, "Failed to start cover art service"); - mAvrcpCoverArtService = null; - } - } else { - Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art"); - } - } - - mReceiver = new AvrcpBroadcastReceiver(); - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction(AudioManager.ACTION_VOLUME_CHANGED); - registerReceiver(mReceiver, filter); - - // Only allow the service to be used once it is initialized - sInstance = this; - } - @Override public void stop() { Log.i(TAG, "Stopping the AVRCP Target Service"); @@ -260,22 +249,15 @@ public class AvrcpTargetService extends ProfileService { if (mAvrcpCoverArtService != null) { mAvrcpCoverArtService.stop(); } - mAvrcpCoverArtService = null; sInstance = null; unregisterReceiver(mReceiver); // We check the interfaces first since they only get set on User Unlocked - if (mPlayerSettingsManager != null) mPlayerSettingsManager.cleanup(); - if (mMediaPlayerList != null) mMediaPlayerList.cleanup(); - if (mNativeInterface != null) mNativeInterface.cleanup(); + mPlayerSettingsManager.cleanup(); + mMediaPlayerList.cleanup(); + mNativeInterface.cleanup(); getApplicationContext().unregisterReceiver(mUserUnlockedReceiver); - - mPlayerSettingsManager = null; - mMediaPlayerList = null; - mNativeInterface = null; - mAudioManager = null; - mReceiver = null; } /** Returns the active A2DP {@link BluetoothDevice} */ @@ -339,7 +321,7 @@ public class AvrcpTargetService extends ProfileService { *

    If the A2DP connection disconnects, we request AVRCP to disconnect device as well. */ public void handleA2dpConnectionStateChanged(BluetoothDevice device, int newState) { - if (device == null || mNativeInterface == null) return; + if (device == null) return; if (newState == BluetoothProfile.STATE_DISCONNECTED) { // If there is no connection, disconnectDevice() will do nothing if (mNativeInterface.disconnectDevice(device)) { @@ -359,10 +341,8 @@ public class AvrcpTargetService extends ProfileService { */ public void handleA2dpActiveDeviceChanged(BluetoothDevice device) { mVolumeManager.volumeDeviceSwitched(device); - if (mNativeInterface != null) { - // Update all the playback status info for each connected device - mNativeInterface.sendMediaUpdate(false, true, false); - } + // Update all the playback status info for each connected device + mNativeInterface.sendMediaUpdate(false, true, false); } /** Informs {@link AvrcpVolumeManager} that a remote device requests a volume change */ @@ -575,11 +555,6 @@ public class AvrcpTargetService extends ProfileService { /** Called from player callback to indicate new settings to remote device. */ public void sendPlayerSettings(int repeatMode, int shuffleMode) { - if (mNativeInterface == null) { - Log.i(TAG, "Tried to send Player Settings while native interface is null"); - return; - } - mNativeInterface.sendPlayerSettings(repeatMode, shuffleMode); } @@ -626,11 +601,7 @@ public class AvrcpTargetService extends ProfileService { StringBuilder tempBuilder = new StringBuilder(); tempBuilder.append("AVRCP version: ").append(mAvrcpVersion).append("\n"); - if (mMediaPlayerList != null) { - mMediaPlayerList.dump(tempBuilder); - } else { - tempBuilder.append("\nMedia Player List is empty\n"); - } + mMediaPlayerList.dump(tempBuilder); mMediaKeyEventLogger.dump(tempBuilder); tempBuilder.append("\n"); -- GitLab From 513dcb114392c872fa4131dc2a31ff2de3b8a665 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 29 Oct 2024 21:16:12 +0100 Subject: [PATCH 488/875] Add flag: smp_state_machine_stuck_after_disconnection_fix Bug: 315241296 Bug: 376306092 Test: mmm packages/modules/Bluetooth Change-Id: I3cd0d93e3dd352f23508c839773a659cf5e888d2 --- flags/pairing.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig index b3e2095e675..6662aee3827 100644 --- a/flags/pairing.aconfig +++ b/flags/pairing.aconfig @@ -190,3 +190,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +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 + } +} \ No newline at end of file -- GitLab From 9cc8e7c2ed817434f37d8ec63a8bbc79e9d0654e Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Thu, 24 Oct 2024 04:08:11 +0000 Subject: [PATCH 489/875] Remove gatt_fix_device_busy flag Bug: 322580271 Test: m -j; Change-Id: Ifdaa057ea476aaa94665588c27351b4cdd4bc387 --- flags/gap.aconfig | 7 ------- framework/java/android/bluetooth/BluetoothGatt.java | 10 +++------- .../bumble/src/android/bluetooth/GattClientTest.java | 3 --- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/flags/gap.aconfig b/flags/gap.aconfig index 2b2b5cdd557..ca15527ad55 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -29,13 +29,6 @@ flag { bug: "317128464" } -flag { - name: "gatt_fix_device_busy" - namespace: "bluetooth" - description: "Fix device busy bug in BluetoothGatt" - bug: "322580271" -} - flag { name: "gatt_cleanup_restricted_handles" namespace: "bluetooth" diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java index 92d058207f6..8847016560e 100644 --- a/framework/java/android/bluetooth/BluetoothGatt.java +++ b/framework/java/android/bluetooth/BluetoothGatt.java @@ -35,8 +35,6 @@ import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; -import com.android.bluetooth.flags.Flags; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -1618,11 +1616,9 @@ public final class BluetoothGatt implements BluetoothProfile { } throw e.rethrowAsRuntimeException(); } - if (Flags.gattFixDeviceBusy()) { - if (requestStatus != BluetoothStatusCodes.SUCCESS) { - synchronized (mDeviceBusyLock) { - mDeviceBusy = false; - } + if (requestStatus != BluetoothStatusCodes.SUCCESS) { + synchronized (mDeviceBusyLock) { + mDeviceBusy = false; } } diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java index 80f08760c6f..38671a28e99 100644 --- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java +++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java @@ -327,11 +327,8 @@ public class GattClientTest { eq(BluetoothProfile.STATE_DISCONNECTED)); } - @RequiresFlagsEnabled(Flags.FLAG_GATT_FIX_DEVICE_BUSY) @Test public void consecutiveWriteCharacteristicFails_thenSuccess() throws Exception { - Assume.assumeTrue(Flags.gattFixDeviceBusy()); - registerGattService(); BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); -- GitLab From 0b4e31866412bf1cbdf2d3d5b853185c064522b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 30 Oct 2024 08:08:18 +0000 Subject: [PATCH 490/875] leaudio: Fix setting disconnecting state for ASEs Without this patch, when stream is canceled in Enabling state, when CISes are not yet created and Data Path is not set, btm_iso DisconnectCis could be called twice for bidirectional CIS and this could lead to assert in btm_iso. Bug: 376396494 Flag: Exempt, trivial and obvious fix. Test: atest bluetooth_le_audio_test Change-Id: I9df7b6e1c7bd706676a22c76e81c4b1e1cb29d2b --- system/bta/le_audio/state_machine.cc | 5 +++ system/bta/le_audio/state_machine_test.cc | 48 +++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 48d09a30b12..cc9f843f045 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -2946,6 +2946,11 @@ private: return CIS_STILL_NEEDED; } + ase->cis_state = CisState::DISCONNECTING; + if (bidirection_ase) { + bidirection_ase->cis_state = CisState::DISCONNECTING; + } + group->RemoveCisFromStreamIfNeeded(leAudioDevice, ase->cis_conn_hdl); IsoManager::GetInstance()->DisconnectCis(ase->cis_conn_hdl, HCI_ERR_PEER_USER); log_history_->AddLogHistory(kLogStateMachineTag, group->group_id_, leAudioDevice->address_, diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index 84b997b3ff0..dc601a5b409 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -4920,6 +4920,54 @@ TEST_F(StateMachineTest, testStateTransitionTimeoutAndDisconnectWhenEnabling) { } } +TEST_F(StateMachineTest, testInjectReleasingStateWhenEnabling) { + const auto context_type = kContextTypeConversational; + const int leaudio_group_id = 4; + channel_count_ = kLeAudioCodecChannelCountSingleChannel; + + // Prepare fake connected device group + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type); + PrepareConfigureCodecHandler(group, 2); + PrepareConfigureQosHandler(group, 2); + PrepareEnableHandler(group, 0, true, false); + + InjectInitialConfiguredNotification(group); + + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0); + EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0); + EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0); + EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0); + + // Stub Establish Cis and Remove CIG + ON_CALL(*mock_iso_manager_, EstablishCis).WillByDefault(Return()); + ON_CALL(*mock_iso_manager_, RemoveCig).WillByDefault(Return()); + + group->PrintDebugState(); + + // Start the configuration and stream Media content + ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream( + group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)})); + + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); + + group->PrintDebugState(); + + log::info("Inject Release of all ASEs"); + + EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1); + + // Stub DisconnectCis to trigger the issue. + ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return()); + + InjectReleaseAndIdleStateForAGroup(group, true, false); + + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); +} + MATCHER_P(dataPathIsEq, expected, "") { return arg.data_path_id == expected; } TEST_F(StateMachineTest, testConfigureDataPathForHost) { -- GitLab From f35fa036591e6e0b44c43401704c92cee4310ef5 Mon Sep 17 00:00:00 2001 From: "Grzegorz Kolodziejczyk (xWF)" Date: Wed, 30 Oct 2024 11:52:56 +0000 Subject: [PATCH 491/875] le_audio: Make allowed context test more strict Most important check for that case is configured context for stream, there is no need to check other parameters that would make this test more safe. Bug: 360051130 Change-Id: I35d0032ec1e281ceeebdc273823ea18eeff83421 Flag: EXEMPT; simple improvement Test: atest le_audio_client_test --- system/bta/le_audio/le_audio_client_test.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 05a26249ac4..705be0375f2 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -12324,10 +12324,7 @@ TEST_F(UnicastTestHandoverMode, SetAllowedContextMask) { ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); - types::BidirectionalPair metadata = {.sink = types::AudioContexts(), - .source = types::AudioContexts()}; - EXPECT_CALL(mock_state_machine_, - StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, metadata, _)) + EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, _, _)) .Times(0); LeAudioClient::Get()->GroupSetActive(group_id); -- GitLab From fdd49146e5ba36fc83deacf537291f4592868a2a Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 29 Oct 2024 23:36:56 +0000 Subject: [PATCH 492/875] system/stack/gatt: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I766addf414dc03345d4a254326e396856f229dbb --- system/btif/src/bluetooth.cc | 2 +- system/stack/acl/ble_acl.cc | 3 +- system/stack/btm/btm_dev.cc | 2 +- system/stack/gatt/att_protocol.cc | 4 -- system/stack/gatt/gatt_api.cc | 7 +-- system/stack/gatt/gatt_attr.cc | 20 +++---- system/stack/gatt/gatt_auth.cc | 5 +- system/stack/gatt/gatt_cl.cc | 52 +++++++++++-------- system/stack/gatt/gatt_db.cc | 5 +- system/stack/gatt/gatt_int.h | 14 +++-- system/stack/gatt/gatt_main.cc | 13 ++--- system/stack/gatt/gatt_sr.cc | 23 ++++---- system/stack/gatt/gatt_utils.cc | 36 ++----------- system/stack/include/gatt_api.h | 6 +++ system/stack/test/gatt/gatt_sr_test.cc | 9 ++-- system/stack/test/gatt/mock_gatt_utils_ref.cc | 6 --- system/test/mock/mock_stack_gatt.cc | 9 ---- system/test/mock/mock_stack_gatt_api.cc | 16 ------ system/test/mock/mock_stack_gatt_api.h | 27 ---------- system/test/mock/mock_stack_gatt_attr.cc | 27 +--------- system/test/mock/mock_stack_gatt_auth.cc | 7 --- system/test/mock/mock_stack_gatt_main.cc | 20 +------ 22 files changed, 82 insertions(+), 231 deletions(-) diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index c4bb371e80a..906a8bd732a 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -106,6 +106,7 @@ #include "stack/include/avdt_api.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_status.h" +#include "stack/include/gatt_api.h" #include "stack/include/hfp_lc3_decoder.h" #include "stack/include/hfp_lc3_encoder.h" #include "stack/include/hfp_msbc_decoder.h" @@ -188,7 +189,6 @@ extern VolumeControlInterface* btif_volume_control_get_interface(); bt_status_t btif_av_sink_execute_service(bool b_enable); -extern void gatt_tcb_dump(int fd); extern void bta_gatt_client_dump(int fd); /******************************************************************************* diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index 0606716f757..fb26beab708 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -29,6 +29,7 @@ #include "stack/include/acl_api.h" #include "stack/include/btm_ble_addr.h" #include "stack/include/btm_ble_privacy.h" +#include "stack/include/gatt_api.h" #include "stack/include/l2cap_hci_link_interface.h" #include "types/raw_address.h" @@ -144,8 +145,6 @@ void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type, uint16_t /* btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, &address_with_type.bda, status); } -void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval, uint16_t latency, - uint16_t timeout, tHCI_STATUS status); void acl_ble_update_event_received(tHCI_STATUS status, uint16_t handle, uint16_t interval, uint16_t latency, uint16_t timeout) { l2cble_process_conn_update_evt(handle, status, interval, latency, timeout); diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc index cdc7e27f91b..c791c033192 100644 --- a/system/stack/btm/btm_dev.cc +++ b/system/stack/btm/btm_dev.cc @@ -45,6 +45,7 @@ #include "stack/include/btm_ble_privacy.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_log_history.h" +#include "stack/include/gatt_api.h" #include "stack/include/l2cap_interface.h" #include "types/raw_address.h" @@ -54,7 +55,6 @@ using namespace bluetooth; extern tBTM_CB btm_cb; -void gatt_consolidate(const RawAddress& identity_addr, const RawAddress& rpa); namespace { diff --git a/system/stack/gatt/att_protocol.cc b/system/stack/gatt/att_protocol.cc index 60bf695167b..8360b814060 100644 --- a/system/stack/gatt/att_protocol.cc +++ b/system/stack/gatt/att_protocol.cc @@ -37,10 +37,6 @@ #define GATT_OP_CODE_SIZE 1 #define GATT_START_END_HANDLE_SIZE 4 -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using base::StringPrintf; using bluetooth::Uuid; using namespace bluetooth; diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index 7ed0fe05160..3f2c7136a94 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -51,9 +51,6 @@ #include "types/bt_transport.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; @@ -63,7 +60,7 @@ using bluetooth::Uuid; * Add a service handle range to the list in descending order of the start * handle. Return reference to the newly added element. **/ -tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) { +static tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) { auto lst_ptr = gatt_cb.hdl_list_info; auto it = lst_ptr->begin(); for (; it != lst_ptr->end(); it++) { @@ -353,7 +350,7 @@ tGATT_STATUS GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service, in return GATT_SERVICE_STARTED; } -bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) { +static bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) { for (auto& info : *gatt_cb.srv_list_info) { Uuid* p_this_uuid = gatts_get_service_uuid(info.p_db); diff --git a/system/stack/gatt/gatt_attr.cc b/system/stack/gatt/gatt_attr.cc index a4b2935c52c..a9d9e12b662 100644 --- a/system/stack/gatt/gatt_attr.cc +++ b/system/stack/gatt/gatt_attr.cc @@ -40,10 +40,6 @@ #include "types/bluetooth/uuid.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using base::StringPrintf; using bluetooth::Uuid; using namespace bluetooth; @@ -192,8 +188,8 @@ static tGATT_PROFILE_CLCB* gatt_profile_find_clcb_by_bd_addr(const RawAddress& b * block. * ******************************************************************************/ -tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(tCONN_ID conn_id, const RawAddress& bda, - tBT_TRANSPORT tranport) { +static tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(tCONN_ID conn_id, const RawAddress& bda, + tBT_TRANSPORT tranport) { uint8_t i_clcb = 0; tGATT_PROFILE_CLCB* p_clcb = NULL; @@ -224,13 +220,13 @@ tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(tCONN_ID conn_id, const RawAddress& * Returns void * ******************************************************************************/ -void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* p_clcb) { +static void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* p_clcb) { memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB)); } /** GAP Attributes Database Request callback */ -tGATT_STATUS read_attr_value(tCONN_ID conn_id, uint16_t handle, tGATT_VALUE* p_value, - bool is_long) { +static tGATT_STATUS read_attr_value(tCONN_ID conn_id, uint16_t handle, tGATT_VALUE* p_value, + bool is_long) { uint8_t* p = p_value->value; if (handle == gatt_cb.handle_sr_supported_feat) { @@ -271,8 +267,8 @@ tGATT_STATUS read_attr_value(tCONN_ID conn_id, uint16_t handle, tGATT_VALUE* p_v } /** GAP Attributes Database Read/Read Blob Request process */ -tGATT_STATUS proc_read_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data, - tGATTS_RSP* p_rsp) { +static tGATT_STATUS proc_read_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data, + tGATTS_RSP* p_rsp) { if (p_data->is_long) { p_rsp->attr_value.offset = p_data->offset; } @@ -283,7 +279,7 @@ tGATT_STATUS proc_read_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_READ_REQ* p_ } /** GAP ATT server process a write request */ -tGATT_STATUS proc_write_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) { +static tGATT_STATUS proc_write_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) { uint16_t handle = p_data->handle; /* GATT_UUID_SERVER_SUP_FEAT*/ diff --git a/system/stack/gatt/gatt_auth.cc b/system/stack/gatt/gatt_auth.cc index fc11e2570ca..4323c8ed137 100644 --- a/system/stack/gatt/gatt_auth.cc +++ b/system/stack/gatt/gatt_auth.cc @@ -39,9 +39,6 @@ #include "stack/include/btm_status.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /******************************************************************************* @@ -281,7 +278,7 @@ tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* p_tcb) { * This routine determine the security action based on auth_request and current * link status. Returns tGATT_SEC_ACTION (security action) */ -tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* p_clcb) { +static tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* p_clcb) { tGATT_SEC_ACTION act = GATT_SEC_OK; tGATT_TCB* p_tcb = p_clcb->p_tcb; tGATT_AUTH_REQ auth_req = p_clcb->auth_req; diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc index 61fb47fa406..50844962f42 100644 --- a/system/stack/gatt/gatt_cl.cc +++ b/system/stack/gatt/gatt_cl.cc @@ -52,9 +52,6 @@ #define L2CAP_PKT_OVERHEAD 4 -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; using bluetooth::Uuid; using bluetooth::eatt::EattChannel; @@ -277,6 +274,7 @@ void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) { return; } } + /******************************************************************************* * * Function gatt_send_queue_write_cancel @@ -299,6 +297,7 @@ void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, tGATT_EXEC gatt_end_operation(p_clcb, rt, NULL); } } + /******************************************************************************* * * Function gatt_check_write_long_terminate @@ -308,7 +307,8 @@ void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, tGATT_EXEC * Returns true: write long is terminated; false keep sending. * ******************************************************************************/ -bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, tGATT_VALUE* p_rsp_value) { +static bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, + tGATT_VALUE* p_rsp_value) { tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf; bool terminate = false; tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC; @@ -389,8 +389,8 @@ void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb) { * Returns void * ******************************************************************************/ -void gatt_process_find_type_value_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint16_t len, - uint8_t* p_data) { +static void gatt_process_find_type_value_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint16_t len, + uint8_t* p_data) { tGATT_DISC_RES result; uint8_t* p = p_data; @@ -434,8 +434,8 @@ void gatt_process_find_type_value_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, * Returns void * ******************************************************************************/ -void gatt_process_read_info_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_t /* op_code */, - uint16_t len, uint8_t* p_data) { +static void gatt_process_read_info_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, + uint8_t /* op_code */, uint16_t len, uint8_t* p_data) { tGATT_DISC_RES result; uint8_t *p = p_data, uuid_len = 0, type; @@ -481,6 +481,7 @@ void gatt_process_read_info_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_ /* initiate another request */ gatt_act_discovery(p_clcb); } + /******************************************************************************* * * Function gatt_proc_disc_error_rsp @@ -491,8 +492,8 @@ void gatt_process_read_info_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_ * Returns void. * ******************************************************************************/ -void gatt_proc_disc_error_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_t opcode, - uint16_t /* handle */, uint8_t reason) { +static void gatt_proc_disc_error_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_t opcode, + uint16_t /* handle */, uint8_t reason) { tGATT_STATUS status = (tGATT_STATUS)reason; log::verbose("reason: {:02x} cmd_code {:04x}", reason, opcode); @@ -525,8 +526,8 @@ void gatt_proc_disc_error_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_t * Returns void * ******************************************************************************/ -void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */, uint16_t len, - uint8_t* p_data) { +static void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */, + uint16_t len, uint8_t* p_data) { uint8_t opcode, *p = p_data; uint8_t reason; uint16_t handle; @@ -569,6 +570,7 @@ void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_co } } } + /******************************************************************************* * * Function gatt_process_prep_write_rsp @@ -579,8 +581,8 @@ void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_co * Returns void * ******************************************************************************/ -void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +static void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, + uint16_t len, uint8_t* p_data) { uint8_t* p = p_data; tGATT_VALUE value = { @@ -630,8 +632,8 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_ * Returns void * ******************************************************************************/ -void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +static void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, + uint8_t* p_data) { tGATT_VALUE value = {}; tGATT_REG* p_reg; tCONN_ID conn_id; @@ -815,8 +817,8 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, ui * Returns void * ******************************************************************************/ -void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, - uint16_t len, uint8_t* p_data) { +static void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, + uint16_t len, uint8_t* p_data) { tGATT_DISC_RES result; tGATT_DISC_VALUE record_value; uint8_t *p = p_data, value_len, handle_len = 2; @@ -1027,8 +1029,8 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t o * Returns void * ******************************************************************************/ -void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */, uint16_t len, - uint8_t* p_data) { +static void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */, + uint16_t len, uint8_t* p_data) { uint16_t offset = p_clcb->counter; uint8_t* p = p_data; @@ -1110,7 +1112,10 @@ void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_cod * Returns void * ******************************************************************************/ -void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) { gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); } +static void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) { + gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); +} + /******************************************************************************* * * Function gatt_process_mtu_rsp @@ -1121,7 +1126,8 @@ void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) { gatt_end_operation(p_clcb, GA * Returns void * ******************************************************************************/ -void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len, uint8_t* p_data) { +static void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len, + uint8_t* p_data) { uint16_t mtu; tGATT_STATUS status = GATT_SUCCESS; @@ -1173,7 +1179,7 @@ void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len, uint * Returns response code. * ******************************************************************************/ -uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) { +static uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) { uint8_t rsp_code = 0; if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) { diff --git a/system/stack/gatt/gatt_db.cc b/system/stack/gatt/gatt_db.cc index 2141fd47eba..cd55ffdb71a 100644 --- a/system/stack/gatt/gatt_db.cc +++ b/system/stack/gatt/gatt_db.cc @@ -31,9 +31,6 @@ #include "stack/include/l2cap_types.h" #include "types/bluetooth/uuid.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::Uuid; using namespace bluetooth; @@ -442,7 +439,7 @@ uint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm, const Uuid& des /******************************************************************************/ /* Service Attribute Database Query Utility Functions */ /******************************************************************************/ -tGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) { +static tGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) { if (!p_db) { return nullptr; } diff --git a/system/stack/gatt/gatt_int.h b/system/stack/gatt/gatt_int.h index 59dc338b5df..88c8b88ab69 100644 --- a/system/stack/gatt/gatt_int.h +++ b/system/stack/gatt/gatt_int.h @@ -499,10 +499,6 @@ bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr, tBT_TRANSPORT int8_t initiating_phys); bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBT_TRANSPORT transport, int8_t initiating_phys); -bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBT_TRANSPORT transport, - uint8_t initiating_phys, tGATT_IF gatt_if); -bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBLE_ADDR_TYPE addr_type, - tBT_TRANSPORT transport, uint8_t initiating_phys, tGATT_IF gatt_if); void gatt_data_process(tGATT_TCB& p_tcb, uint16_t cid, BT_HDR* p_buf); void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb, bool is_add, bool check_acl_link); @@ -692,10 +688,20 @@ tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code, ui tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long, uint16_t handle, tGATT_SEC_FLAG sec_flag, uint8_t key_size); bluetooth::Uuid* gatts_get_service_uuid(tGATT_SVC_DB* p_db); +void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb); /* gatt_sr_hash.cc */ Octet16 gatts_calculate_database_hash(std::list* lst_ptr); +namespace bluetooth { +namespace legacy { +namespace testing { +BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code, uint16_t handle, + uint16_t offset, uint16_t len, uint8_t* p_data); +} // namespace testing +} // namespace legacy +} // namespace bluetooth + namespace fmt { template <> struct formatter : enum_formatter {}; diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index f5591d21948..2cf2c42a517 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -45,15 +45,13 @@ #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" #include "stack/include/btm_client_interface.h" +#include "stack/include/gatt_api.h" #include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cap_interface.h" #include "stack/include/l2cdefs.h" #include "stack/include/srvc_api.h" // tDIS_VALUE #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::eatt::EattExtension; using namespace bluetooth; @@ -218,8 +216,8 @@ void gatt_free(void) { * Returns true if connection is started, otherwise return false. * ******************************************************************************/ -bool gatt_connect(const RawAddress& rem_bda, tBLE_ADDR_TYPE addr_type, tGATT_TCB* p_tcb, - tBT_TRANSPORT transport, uint8_t /* initiating_phys */, tGATT_IF gatt_if) { +static bool gatt_connect(const RawAddress& rem_bda, tBLE_ADDR_TYPE addr_type, tGATT_TCB* p_tcb, + tBT_TRANSPORT transport, uint8_t /* initiating_phys */, tGATT_IF gatt_if) { if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN) { gatt_set_ch_state(p_tcb, GATT_CH_CONN); } @@ -240,11 +238,6 @@ bool gatt_connect(const RawAddress& rem_bda, tBLE_ADDR_TYPE addr_type, tGATT_TCB return connection_manager::create_le_connection(gatt_if, rem_bda, addr_type); } -bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBT_TRANSPORT transport, - uint8_t initiating_phys, tGATT_IF gatt_if) { - return gatt_connect(rem_bda, BLE_ADDR_PUBLIC, p_tcb, transport, initiating_phys, gatt_if); -} - /******************************************************************************* * * Function gatt_cancel_connect diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 7e12f30e7da..8b67f2e204f 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -44,9 +44,6 @@ #define GATT_MTU_REQ_MIN_LEN 2 #define L2CAP_PKT_OVERHEAD 4 -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::Uuid; using bluetooth::eatt::EattChannel; using bluetooth::eatt::EattExtension; @@ -107,7 +104,7 @@ uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint * Returns true if empty, false if there is pending command. * ******************************************************************************/ -bool gatt_sr_cmd_empty(tGATT_TCB& tcb, uint16_t cid) { +static bool gatt_sr_cmd_empty(tGATT_TCB& tcb, uint16_t cid) { if (cid == tcb.att_lcid) { return tcb.sr_cmd.op_code == 0; } @@ -369,8 +366,8 @@ tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if, uint32_t * Returns void * ******************************************************************************/ -void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +static void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, + uint8_t* p_data) { uint8_t *p = p_data, flag; uint32_t trans_id = 0; tGATT_IF gatt_if; @@ -441,8 +438,8 @@ void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, * Returns void * ******************************************************************************/ -void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +static void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, + uint8_t* p_data) { uint32_t trans_id; uint16_t handle = 0, ll = len; uint8_t* p = p_data; @@ -730,8 +727,8 @@ static tGATT_STATUS gatts_validate_packet_format(uint8_t op_code, uint16_t& len, * Returns void * ******************************************************************************/ -void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +static void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, + uint16_t len, uint8_t* p_data) { uint16_t s_hdl = 0, e_hdl = 0; Uuid uuid = Uuid::kEmpty; @@ -1144,8 +1141,8 @@ static void gatts_process_read_req(tGATT_TCB& tcb, uint16_t cid, tGATT_SRV_LIST_ * Returns void * ******************************************************************************/ -void gatts_process_attribute_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, - uint8_t* p_data) { +static void gatts_process_attribute_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, + uint8_t* p_data) { uint16_t handle = 0; uint8_t* p = p_data; tGATT_STATUS status = GATT_INVALID_HANDLE; @@ -1291,7 +1288,7 @@ static bool gatts_proc_ind_ack(tGATT_TCB& tcb, uint16_t ack_handle) { * Returns void * ******************************************************************************/ -void gatts_process_value_conf(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code) { +static void gatts_process_value_conf(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code) { uint16_t handle; if (!gatt_tcb_find_indicate_handle(tcb, cid, &handle)) { diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index d159bbd794a..5be17c302a9 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -45,16 +45,12 @@ #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" #include "stack/include/bt_uuid16.h" +#include "stack/include/btm_sec_api.h" #include "stack/include/l2cdefs.h" #include "stack/include/sdp_api.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr); - using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth; @@ -108,7 +104,7 @@ uint16_t gatt_get_local_mtu(void) { return ATT_MTU_DEFAULT; } -uint16_t gatt_get_max_phy_channel() { +static uint16_t gatt_get_max_phy_channel() { static const uint16_t MAX_PHY_CHANNEL = std::min(std::max(osi_property_get_int32( "bluetooth.core.le.max_number_of_concurrent_connections", 0), @@ -126,7 +122,7 @@ uint16_t gatt_get_max_phy_channel() { * Returns None * ******************************************************************************/ -void gatt_free_pending_ind(tGATT_TCB* p_tcb) { +static void gatt_free_pending_ind(tGATT_TCB* p_tcb) { log::verbose(""); if (p_tcb->pending_ind_q == NULL) { @@ -375,28 +371,6 @@ tGATTS_SRV_CHG* gatt_is_bda_in_the_srv_chg_clt_list(const RawAddress& bda) { return NULL; } -/******************************************************************************* - * - * Function gatt_is_bda_connected - * - * Description - * - * Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb. - * - ******************************************************************************/ -bool gatt_is_bda_connected(const RawAddress& bda) { - uint8_t i = 0; - bool connected = false; - - for (i = 0; i < gatt_get_max_phy_channel(); i++) { - if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].peer_bda == bda) { - connected = true; - break; - } - } - return connected; -} - /******************************************************************************* * * Function gatt_find_i_tcb_by_addr @@ -406,7 +380,7 @@ bool gatt_is_bda_connected(const RawAddress& bda) { * Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb. * ******************************************************************************/ -uint8_t gatt_find_i_tcb_by_addr(const RawAddress& bda, tBT_TRANSPORT transport) { +static uint8_t gatt_find_i_tcb_by_addr(const RawAddress& bda, tBT_TRANSPORT transport) { uint8_t i = 0; for (; i < gatt_get_max_phy_channel(); i++) { @@ -794,8 +768,6 @@ void gatt_rsp_timeout(void* data) { } } -void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb); - /******************************************************************************* * * Function gatt_indication_confirmation_timeout diff --git a/system/stack/include/gatt_api.h b/system/stack/include/gatt_api.h index e51ddc08255..54ecfdccb32 100644 --- a/system/stack/include/gatt_api.h +++ b/system/stack/include/gatt_api.h @@ -1272,6 +1272,10 @@ void gatt_init(void); // Frees resources used by the GATT profile. void gatt_free(void); +void gatt_consolidate(const RawAddress& identity_addr, const RawAddress& rpa); +void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval, uint16_t latency, + uint16_t timeout, tHCI_STATUS status); + // Link encryption complete notification for all encryption process // initiated outside GATT. void gatt_notify_enc_cmpl(const RawAddress& bd_addr); @@ -1283,6 +1287,8 @@ void gatt_reset_bgdev_list(bool after_reset); // Initialize GATTS list of bonded device service change updates. void gatt_load_bonded(void); +void gatt_tcb_dump(int fd); + namespace fmt { template <> struct formatter : enum_formatter {}; diff --git a/system/stack/test/gatt/gatt_sr_test.cc b/system/stack/test/gatt/gatt_sr_test.cc index 7992f876ea3..285aa23ea84 100644 --- a/system/stack/test/gatt/gatt_sr_test.cc +++ b/system/stack/test/gatt/gatt_sr_test.cc @@ -20,6 +20,7 @@ #include #include +#include "stack/connection_manager/connection_manager.h" #include "stack/gatt/gatt_int.h" #include "stack/include/bt_hdr.h" #include "stack/include/main_thread.h" @@ -120,12 +121,8 @@ tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* /*p_db*/, uint8_t /*op_co void gatt_update_app_use_link_flag(tGATT_IF /*gatt_if*/, tGATT_TCB* /*p_tcb*/, bool /*is_add*/, bool /*check_acl_link*/) {} bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; } -void l2cble_set_fixed_channel_tx_data_length(const RawAddress& /*remote_bda*/, uint16_t /*fix_cid*/, - uint16_t /*tx_mtu*/) {} -void L2CA_SetLeFixedChannelTxDataLength(const RawAddress& /*remote_bda*/, uint16_t /*fix_cid*/, - uint16_t /*tx_mtu*/) {} -void ApplicationRequestCallback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, - tGATTS_DATA* p_data) { +static void ApplicationRequestCallback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, + tGATTS_DATA* p_data) { test_state_.application_request_callback.conn_id_ = conn_id; test_state_.application_request_callback.trans_id_ = trans_id; test_state_.application_request_callback.type_ = type; diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc index 2f392b3e90a..fcd758640f0 100644 --- a/system/stack/test/gatt/mock_gatt_utils_ref.cc +++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc @@ -63,9 +63,3 @@ uint32_t gatt_sr_enqueue_cmd(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint return 0x0000; } void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid) {} - -/** stack/l2cap/l2c_ble.cc */ -void l2cble_set_fixed_channel_tx_data_length(const RawAddress& remote_bda, uint16_t fix_cid, - uint16_t tx_mtu) {} -void L2CA_SetLeFixedChannelTxDataLength(const RawAddress& remote_bda, uint16_t fix_cid, - uint16_t tx_mtu) {} diff --git a/system/test/mock/mock_stack_gatt.cc b/system/test/mock/mock_stack_gatt.cc index 297ec5747ae..a6dfb1d52b2 100644 --- a/system/test/mock/mock_stack_gatt.cc +++ b/system/test/mock/mock_stack_gatt.cc @@ -26,17 +26,8 @@ #include "test/common/mock_functions.h" #include "types/bluetooth/uuid.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; -tGATT_HDL_LIST_ELEM elem; // gatt_add_an_item_to_list - -tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t /* s_handle */) { - inc_func_call_count(__func__); - return elem; -} tGATT_STATUS GATTC_Discover(uint16_t /* conn_id */, tGATT_DISC_TYPE /* disc_type */, uint16_t /* start_handle */, uint16_t /* end_handle */, const Uuid& /* uuid */) { diff --git a/system/test/mock/mock_stack_gatt_api.cc b/system/test/mock/mock_stack_gatt_api.cc index cde6c3fa6b3..2822d79420f 100644 --- a/system/test/mock/mock_stack_gatt_api.cc +++ b/system/test/mock/mock_stack_gatt_api.cc @@ -27,9 +27,6 @@ #include "test/common/mock_functions.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - // Original usings using bluetooth::Uuid; @@ -66,8 +63,6 @@ struct GATT_GetConnectionInfor GATT_GetConnectionInfor; struct GATT_Register GATT_Register; struct GATT_SetIdleTimeout GATT_SetIdleTimeout; struct GATT_StartIf GATT_StartIf; -// struct gatt_add_an_item_to_list gatt_add_an_item_to_list; -struct is_active_service is_active_service; } // namespace stack_gatt_api } // namespace mock @@ -99,9 +94,6 @@ tGATT_STATUS GATT_Disconnect::return_value = GATT_SUCCESS; bool GATT_GetConnIdIfConnected::return_value = false; bool GATT_GetConnectionInfor::return_value = false; tGATT_IF GATT_Register::return_value = 0; -// tGATT_HDL_LIST_ELEM gatt_add_an_item_to_list::return_value = { .svc_db = {}, -// .asgn_range = {}}; -bool is_active_service::return_value = false; } // namespace stack_gatt_api } // namespace mock @@ -230,14 +222,6 @@ void GATT_StartIf(tGATT_IF gatt_if) { inc_func_call_count(__func__); test::mock::stack_gatt_api::GATT_StartIf(gatt_if); } -// tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) { -// inc_func_call_count(__func__); -// return test::mock::stack_gatt_api::gatt_add_an_item_to_list(s_handle); -// } -bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) { - inc_func_call_count(__func__); - return test::mock::stack_gatt_api::is_active_service(app_uuid128, p_svc_uuid, start_handle); -} // Mocked functions complete // bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYPE connection_type, diff --git a/system/test/mock/mock_stack_gatt_api.h b/system/test/mock/mock_stack_gatt_api.h index 74bf566f2f0..63d4e0f7d52 100644 --- a/system/test/mock/mock_stack_gatt_api.h +++ b/system/test/mock/mock_stack_gatt_api.h @@ -398,33 +398,6 @@ struct GATT_StartIf { }; extern struct GATT_StartIf GATT_StartIf; -// // Name: gatt_add_an_item_to_list -// // Params: uint16_t s_handle -// // Return: tGATT_HDL_LIST_ELEM& -// struct gatt_add_an_item_to_list { -// static tGATT_HDL_LIST_ELEM return_value; -// std::function body{ -// [](uint16_t s_handle) { return return_value; }}; -// tGATT_HDL_LIST_ELEM& operator()(uint16_t s_handle) { return body(s_handle); -// }; -// }; -// extern struct gatt_add_an_item_to_list gatt_add_an_item_to_list; - -// Name: is_active_service -// Params: const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle -// Return: bool -struct is_active_service { - static bool return_value; - std::function body{ - [](const Uuid& /* app_uuid128 */, Uuid* /* p_svc_uuid */, uint16_t /* start_handle */) { - return return_value; - }}; - bool operator()(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) { - return body(app_uuid128, p_svc_uuid, start_handle); - } -}; -extern struct is_active_service is_active_service; - } // namespace stack_gatt_api } // namespace mock } // namespace test diff --git a/system/test/mock/mock_stack_gatt_attr.cc b/system/test/mock/mock_stack_gatt_attr.cc index 6de9539644f..4e46e87f2ff 100644 --- a/system/test/mock/mock_stack_gatt_attr.cc +++ b/system/test/mock/mock_stack_gatt_attr.cc @@ -28,15 +28,11 @@ #include "types/bt_transport.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - uint16_t gatt_profile_find_conn_id_by_bd_addr(const RawAddress& /* remote_bda */) { inc_func_call_count(__func__); return 0; } -bool gatt_profile_get_eatt_support(const RawAddress& /* remote_bda */, - base::OnceCallback /* cb */) { +bool gatt_profile_get_eatt_support(const RawAddress& /* remote_bda */) { inc_func_call_count(__func__); return false; } @@ -48,31 +44,10 @@ bool gatt_sr_is_cl_change_aware(tGATT_TCB& /* tcb */) { inc_func_call_count(__func__); return false; } -tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(uint16_t /* conn_id */, const RawAddress& /* bda */, - tBT_TRANSPORT /* tranport */) { - inc_func_call_count(__func__); - return nullptr; -} -tGATT_STATUS proc_read_req(uint16_t /* conn_id */, tGATTS_REQ_TYPE, tGATT_READ_REQ* /* p_data */, - tGATTS_RSP* /* p_rsp */) { - inc_func_call_count(__func__); - return GATT_SUCCESS; -} -tGATT_STATUS proc_write_req(uint16_t /* conn_id */, tGATTS_REQ_TYPE, - tGATT_WRITE_REQ* /* p_data */) { - inc_func_call_count(__func__); - return GATT_SUCCESS; -} -tGATT_STATUS read_attr_value(uint16_t /* conn_id */, uint16_t /* handle */, - tGATT_VALUE* /* p_value */, bool /* is_long */) { - inc_func_call_count(__func__); - return GATT_SUCCESS; -} void GATT_ConfigServiceChangeCCC(const RawAddress& /* remote_bda */, bool /* enable */, tBT_TRANSPORT /* transport */) { inc_func_call_count(__func__); } -void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* /* p_clcb */) { inc_func_call_count(__func__); } void gatt_profile_db_init(void) { inc_func_call_count(__func__); } void gatt_sr_init_cl_status(tGATT_TCB& /* tcb */) { inc_func_call_count(__func__); } void gatt_sr_update_cl_status(tGATT_TCB& /* tcb */, bool /* chg_aware */) { diff --git a/system/test/mock/mock_stack_gatt_auth.cc b/system/test/mock/mock_stack_gatt_auth.cc index 1e59e8152d0..0351bf3e704 100644 --- a/system/test/mock/mock_stack_gatt_auth.cc +++ b/system/test/mock/mock_stack_gatt_auth.cc @@ -26,17 +26,10 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - bool gatt_security_check_start(tGATT_CLCB* /* p_clcb */) { inc_func_call_count(__func__); return false; } -tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* /* p_clcb */) { - inc_func_call_count(__func__); - return GATT_SEC_NONE; -} tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* /* p_tcb */) { inc_func_call_count(__func__); return GATT_SEC_NONE; diff --git a/system/test/mock/mock_stack_gatt_main.cc b/system/test/mock/mock_stack_gatt_main.cc index 8ef0677c495..2c09b4a7682 100644 --- a/system/test/mock/mock_stack_gatt_main.cc +++ b/system/test/mock/mock_stack_gatt_main.cc @@ -21,13 +21,11 @@ #include "stack/gatt/gatt_int.h" #include "stack/include/bt_hdr.h" +#include "stack/include/gatt_api.h" #include "stack/include/l2cap_interface.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - void gatt_init(void) { inc_func_call_count(__func__); } bool gatt_act_connect(tGATT_REG* /* p_reg */, const RawAddress& /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */, tBT_TRANSPORT /* transport */, @@ -35,12 +33,6 @@ bool gatt_act_connect(tGATT_REG* /* p_reg */, const RawAddress& /* bd_addr */, inc_func_call_count(__func__); return false; } -bool gatt_connect(const RawAddress& /* rem_bda */, tGATT_TCB* /* p_tcb */, - tBLE_ADDR_TYPE /* addr_type */, tBT_TRANSPORT /* transport */, - uint8_t /* initiating_phys */, tGATT_IF /* gatt_if */) { - inc_func_call_count(__func__); - return false; -} void gatt_cancel_connect(const RawAddress& /* bd_addr */, tBT_TRANSPORT /* transport*/) { inc_func_call_count(__func__); } @@ -64,16 +56,6 @@ void gatt_consolidate(const RawAddress& /* identity_addr */, const RawAddress& / } void gatt_free(void) { inc_func_call_count(__func__); } void gatt_init_srv_chg(void) { inc_func_call_count(__func__); } -void gatt_l2cif_config_cfm_cback(uint16_t /* lcid */, uint16_t /* initiator */, - tL2CAP_CFG_INFO* /* p_cfg */) { - inc_func_call_count(__func__); -} -void gatt_l2cif_config_ind_cback(uint16_t /* lcid */, tL2CAP_CFG_INFO* /* p_cfg */) { - inc_func_call_count(__func__); -} -void gatt_l2cif_disconnect_ind_cback(uint16_t /* lcid */, bool /* ack_needed */) { - inc_func_call_count(__func__); -} void gatt_notify_conn_update(const RawAddress& /* remote */, uint16_t /* interval */, uint16_t /* latency */, uint16_t /* timeout */, tHCI_STATUS /* status */) { -- GitLab From 874c27d16f6f882c671064e424d5d2a2e9d4eee9 Mon Sep 17 00:00:00 2001 From: Ryo Hashimoto Date: Wed, 16 Oct 2024 16:02:30 +0900 Subject: [PATCH 493/875] Pass appropriate types to base::StringPrintf Bug: 367200458 Flag: EXEMPT, no logical change Test: mmm packages/modules/Bluetooth Change-Id: Ib70bd61002be56a52f29658e86dd5dab0aa5ac30 --- system/bta/dm/bta_dm_device_search.cc | 11 ++++++----- system/btif/src/btif_dm.cc | 6 ++++-- system/stack/btm/btm_sec.cc | 2 +- system/stack/btm/security_device_record.h | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/system/bta/dm/bta_dm_device_search.cc b/system/bta/dm/bta_dm_device_search.cc index a5428dc9837..76219c3fbb1 100644 --- a/system/bta/dm/bta_dm_device_search.cc +++ b/system/bta/dm/bta_dm_device_search.cc @@ -342,11 +342,12 @@ static void bta_dm_inq_cmpl() { } static void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) { - BTM_LogHistory(kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed", - base::StringPrintf("status:%s state:%s name:\"%s\"", - hci_status_code_text(remote_name_msg.hci_status).c_str(), - bta_dm_state_text(bta_dm_search_get_state()).c_str(), - PRIVATE_NAME(remote_name_msg.bd_name))); + BTM_LogHistory( + kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed", + base::StringPrintf("status:%s state:%s name:\"%s\"", + hci_status_code_text(remote_name_msg.hci_status).c_str(), + bta_dm_state_text(bta_dm_search_get_state()).c_str(), + PRIVATE_NAME(reinterpret_cast(remote_name_msg.bd_name)))); tBTM_INQ_INFO* p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbRead(remote_name_msg.bd_addr); diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index a57ad767811..a6e8fc95670 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -972,7 +972,8 @@ static void btif_dm_pin_req_evt(tBTA_DM_PIN_REQ* p_pin_req) { } } BTM_LogHistory(kBtmLogTagCallback, bd_addr, "Pin request", - base::StringPrintf("name:\"%s\" min16:%c", PRIVATE_NAME(bd_name.name), + base::StringPrintf("name:\"%s\" min16:%c", + PRIVATE_NAME(reinterpret_cast(bd_name.name)), (p_pin_req->min_16_digit) ? 'T' : 'F')); GetInterfaceToProfiles()->events->invoke_pin_request_cb(bd_addr, bd_name, cod, p_pin_req->min_16_digit); @@ -3536,7 +3537,8 @@ static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ* p_pin_req) { cod = COD_UNCLASSIFIED; BTM_LogHistory(kBtmLogTagCallback, bd_addr, "PIN request", - base::StringPrintf("name:'%s'", PRIVATE_NAME(bd_name.name))); + base::StringPrintf("name:'%s'", + PRIVATE_NAME(reinterpret_cast(bd_name.name)))); GetInterfaceToProfiles()->events->invoke_pin_request_cb(bd_addr, bd_name, cod, false); } diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index e647715e40b..fb9454c3e05 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -2159,7 +2159,7 @@ tBTM_SEC_DEV_REC* btm_rnr_add_name_to_security_record(const RawAddress* p_bd_add BTM_LogHistory( kBtmLogTag, (p_bd_addr) ? *p_bd_addr : RawAddress::kEmpty, "RNR complete", base::StringPrintf("hci_status:%s name:%s", hci_error_code_text(hci_status).c_str(), - PRIVATE_NAME(p_bd_name))); + PRIVATE_NAME(reinterpret_cast(p_bd_name)))); if (p_dev_rec == nullptr) { // We need to send the callbacks to complete the RNR cycle despite failure diff --git a/system/stack/btm/security_device_record.h b/system/stack/btm/security_device_record.h index 14463ac2113..322e7836d89 100644 --- a/system/stack/btm/security_device_record.h +++ b/system/stack/btm/security_device_record.h @@ -338,8 +338,8 @@ public: "sec_prop:%s", ADDRESS_TO_LOGGABLE_CSTR(bd_addr), DeviceTypeText(device_type).c_str(), dev_class_text(dev_class).c_str(), remote_version_info.ToString().c_str(), sm4, - (remote_supports_secure_connections) ? 'T' : 'F', PRIVATE_NAME(sec_bd_name), - sec_rec.ToString().c_str()); + (remote_supports_secure_connections) ? 'T' : 'F', + PRIVATE_NAME(reinterpret_cast(sec_bd_name)), sec_rec.ToString().c_str()); } public: -- GitLab From 83fb60f6c8c138193c3c608bd15df408e444deef Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 30 Oct 2024 17:30:49 +0000 Subject: [PATCH 494/875] system/stack/gap: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I5e5bab4f10e54d928fdae0dbe234f70fe4f5cbd9 --- system/stack/gap/gap_ble.cc | 46 ++++++++++++------------- system/stack/gap/gap_conn.cc | 8 ++--- system/stack/gap/gap_int.h | 20 +++++++++++ system/test/mock/mock_stack_gap_ble.cc | 4 +-- system/test/mock/mock_stack_gap_conn.cc | 6 ---- 5 files changed, 45 insertions(+), 39 deletions(-) create mode 100644 system/stack/gap/gap_int.h diff --git a/system/stack/gap/gap_ble.cc b/system/stack/gap/gap_ble.cc index 92c826afc31..a97a8cab366 100644 --- a/system/stack/gap/gap_ble.cc +++ b/system/stack/gap/gap_ble.cc @@ -23,6 +23,7 @@ #include #include "gap_api.h" +#include "gap_int.h" #include "gatt_api.h" #include "hardware/bt_gatt_types.h" #include "stack/include/bt_types.h" @@ -33,9 +34,6 @@ #include "types/bt_transport.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::Uuid; using namespace bluetooth; @@ -61,10 +59,10 @@ typedef struct { tGAP_BLE_ATTR_VALUE attr_value; } tGAP_ATTR; -void server_attr_request_cback(tCONN_ID, uint32_t, tGATTS_REQ_TYPE, tGATTS_DATA*); -void client_connect_cback(tGATT_IF, const RawAddress&, tCONN_ID, bool, tGATT_DISCONN_REASON, - tBT_TRANSPORT); -void client_cmpl_cback(tCONN_ID, tGATTC_OPTYPE, tGATT_STATUS, tGATT_CL_COMPLETE*); +static void server_attr_request_cback(tCONN_ID, uint32_t, tGATTS_REQ_TYPE, tGATTS_DATA*); +static void client_connect_cback(tGATT_IF, const RawAddress&, tCONN_ID, bool, tGATT_DISCONN_REASON, + tBT_TRANSPORT); +static void client_cmpl_cback(tCONN_ID, tGATTC_OPTYPE, tGATT_STATUS, tGATT_CL_COMPLETE*); tGATT_CBACK gap_cback = { .p_conn_cb = client_connect_cback, @@ -88,7 +86,7 @@ std::array gatt_attr; tGATT_IF gatt_if; /** returns LCB with matching bd address, or nullptr */ -tGAP_CLCB* find_clcb_by_bd_addr(const RawAddress& bda) { +static tGAP_CLCB* find_clcb_by_bd_addr(const RawAddress& bda) { for (auto& cb : gap_clcbs) { if (cb.bda == bda) { return &cb; @@ -99,7 +97,7 @@ tGAP_CLCB* find_clcb_by_bd_addr(const RawAddress& bda) { } /** returns LCB with matching connection ID, or nullptr if not found */ -tGAP_CLCB* ble_find_clcb_by_conn_id(tCONN_ID conn_id) { +static tGAP_CLCB* ble_find_clcb_by_conn_id(tCONN_ID conn_id) { for (auto& cb : gap_clcbs) { if (cb.connected && cb.conn_id == conn_id) { return &cb; @@ -110,7 +108,7 @@ tGAP_CLCB* ble_find_clcb_by_conn_id(tCONN_ID conn_id) { } /** allocates a GAP connection link control block */ -tGAP_CLCB* clcb_alloc(const RawAddress& bda) { +static tGAP_CLCB* clcb_alloc(const RawAddress& bda) { gap_clcbs.emplace_back(); tGAP_CLCB& cb = gap_clcbs.back(); cb.bda = bda; @@ -118,7 +116,7 @@ tGAP_CLCB* clcb_alloc(const RawAddress& bda) { } /** The function clean up the pending request queue in GAP */ -void clcb_dealloc(tGAP_CLCB& clcb) { +static void clcb_dealloc(tGAP_CLCB& clcb) { // put last element into place of current element, and remove last one - just // fast remove. for (auto it = gap_clcbs.begin(); it != gap_clcbs.end(); it++) { @@ -132,7 +130,7 @@ void clcb_dealloc(tGAP_CLCB& clcb) { } /** GAP Attributes Database Request callback */ -tGATT_STATUS read_attr_value(uint16_t handle, tGATT_VALUE* p_value, bool is_long) { +static tGATT_STATUS read_attr_value(uint16_t handle, tGATT_VALUE* p_value, bool is_long) { uint8_t* p = p_value->value; uint16_t offset = p_value->offset; uint8_t* p_dev_name = NULL; @@ -191,7 +189,7 @@ tGATT_STATUS read_attr_value(uint16_t handle, tGATT_VALUE* p_value, bool is_long } /** GAP Attributes Database Read/Read Blob Request process */ -tGATT_STATUS proc_read(tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data, tGATTS_RSP* p_rsp) { +static tGATT_STATUS proc_read(tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data, tGATTS_RSP* p_rsp) { if (p_data->is_long) { p_rsp->attr_value.offset = p_data->offset; } @@ -202,7 +200,7 @@ tGATT_STATUS proc_read(tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data, tGATTS_RSP* p_rs } /** GAP ATT server process a write request */ -tGATT_STATUS proc_write_req(tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) { +static tGATT_STATUS proc_write_req(tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) { for (const auto& db_addr : gatt_attr) { if (p_data->handle == db_addr.handle) { return GATT_WRITE_NOT_PERMIT; @@ -213,8 +211,8 @@ tGATT_STATUS proc_write_req(tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) { } /** GAP ATT server attribute access request callback */ -void server_attr_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, - tGATTS_DATA* p_data) { +static void server_attr_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type, + tGATTS_DATA* p_data) { tGATT_STATUS status = GATT_INVALID_PDU; bool ignore = false; @@ -262,7 +260,7 @@ void server_attr_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_T * Utility function to send a read request for GAP characteristics. * Returns true if read started, else false if GAP is busy. */ -bool send_cl_read_request(tGAP_CLCB& clcb) { +static bool send_cl_read_request(tGAP_CLCB& clcb) { if (!clcb.requests.size() || clcb.cl_op_uuid != 0) { return false; } @@ -288,7 +286,7 @@ bool send_cl_read_request(tGAP_CLCB& clcb) { } /** GAP client operation complete callback */ -void cl_op_cmpl(tGAP_CLCB& clcb, bool status, uint16_t len, uint8_t* p_name) { +static void cl_op_cmpl(tGAP_CLCB& clcb, bool status, uint16_t len, uint8_t* p_name) { tGAP_BLE_CMPL_CBACK* p_cback = clcb.p_cback; uint16_t op = clcb.cl_op_uuid; @@ -311,8 +309,8 @@ void cl_op_cmpl(tGAP_CLCB& clcb, bool status, uint16_t len, uint8_t* p_name) { } /** Client connection callback */ -void client_connect_cback(tGATT_IF, const RawAddress& bda, tCONN_ID conn_id, bool connected, - tGATT_DISCONN_REASON /* reason */, tBT_TRANSPORT) { +static void client_connect_cback(tGATT_IF, const RawAddress& bda, tCONN_ID conn_id, bool connected, + tGATT_DISCONN_REASON /* reason */, tBT_TRANSPORT) { tGAP_CLCB* p_clcb = find_clcb_by_bd_addr(bda); if (p_clcb == NULL) { log::info("No active GAP service found for peer:{} callback:{}", bda, @@ -336,8 +334,8 @@ void client_connect_cback(tGATT_IF, const RawAddress& bda, tCONN_ID conn_id, boo } /** Client operation complete callback */ -void client_cmpl_cback(tCONN_ID conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, - tGATT_CL_COMPLETE* p_data) { +static void client_cmpl_cback(tCONN_ID conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, + tGATT_CL_COMPLETE* p_data) { tGAP_CLCB* p_clcb = ble_find_clcb_by_conn_id(conn_id); uint16_t op_type; uint16_t min, max, latency, tout; @@ -396,8 +394,8 @@ void client_cmpl_cback(tCONN_ID conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, } } -bool accept_client_operation(const RawAddress& peer_bda, uint16_t uuid, - tGAP_BLE_CMPL_CBACK* p_cback) { +static bool accept_client_operation(const RawAddress& peer_bda, uint16_t uuid, + tGAP_BLE_CMPL_CBACK* p_cback) { if (p_cback == NULL && uuid != GATT_UUID_GAP_PREF_CONN_PARAM) { return false; } diff --git a/system/stack/gap/gap_conn.cc b/system/stack/gap/gap_conn.cc index 8208edf4d53..fd988c8fd31 100644 --- a/system/stack/gap/gap_conn.cc +++ b/system/stack/gap/gap_conn.cc @@ -21,6 +21,7 @@ #include #include "gap_api.h" +#include "gap_int.h" #include "hci/controller_interface.h" #include "internal_include/bt_target.h" #include "main/shim/entry.h" @@ -34,9 +35,6 @@ #include "types/bt_transport.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; /* Define the GAP Connection Control Block */ @@ -117,7 +115,7 @@ static void gap_checks_con_flags(tGAP_CCB* p_ccb); * Returns void * ******************************************************************************/ -void gap_conn_init(void) { +static void gap_conn_init(void) { memset(&conn, 0, sizeof(tGAP_CONN)); conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind; conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm; @@ -1050,8 +1048,6 @@ static void gap_release_ccb(tGAP_CCB* p_ccb) { } } -void gap_attr_db_init(void); - /* * This routine should not be called except once per stack invocation. */ diff --git a/system/stack/gap/gap_int.h b/system/stack/gap/gap_int.h new file mode 100644 index 00000000000..c63a4ce899f --- /dev/null +++ b/system/stack/gap/gap_int.h @@ -0,0 +1,20 @@ +/* + * 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 + +/// GAP ATT database initialization. +void gap_attr_db_init(void); diff --git a/system/test/mock/mock_stack_gap_ble.cc b/system/test/mock/mock_stack_gap_ble.cc index 941ca7d1875..3f852ff03cb 100644 --- a/system/test/mock/mock_stack_gap_ble.cc +++ b/system/test/mock/mock_stack_gap_ble.cc @@ -21,13 +21,11 @@ #include +#include "stack/gap/gap_int.h" #include "stack/include/gap_api.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - bool GAP_BleCancelReadPeerDevName(const RawAddress& /* peer_bda */) { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_stack_gap_conn.cc b/system/test/mock/mock_stack_gap_conn.cc index 6fb98265881..19034a9fec0 100644 --- a/system/test/mock/mock_stack_gap_conn.cc +++ b/system/test/mock/mock_stack_gap_conn.cc @@ -24,9 +24,6 @@ #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - const RawAddress* GAP_ConnGetRemoteAddr(uint16_t /* gap_handle */) { inc_func_call_count(__func__); return nullptr; @@ -65,6 +62,3 @@ uint16_t GAP_ConnWriteData(uint16_t /* gap_handle */, BT_HDR* /* msg */) { return 0; } void GAP_Init(void) { inc_func_call_count(__func__); } -void gap_tx_complete_ind(uint16_t /* l2cap_cid */, uint16_t /* sdu_sent */) { - inc_func_call_count(__func__); -} -- GitLab From ace92111727bba98df2c5a361f5b9e5d1b0c3ea7 Mon Sep 17 00:00:00 2001 From: Sal Savage Date: Wed, 30 Oct 2024 10:14:10 -0700 Subject: [PATCH 495/875] Flags: Add PBAP Client storage and caching flags Bug: 315241296 Bug: 376461939 Bug: 376461947 Bug: 376478155 Test: m com.android.btservices Change-Id: Ic88e60b879fb7680c586c1cfa84ad7e446533968 --- flags/Android.bp | 1 + flags/BUILD.gn | 1 + flags/pbapclient.aconfig | 16 ++++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 flags/pbapclient.aconfig diff --git a/flags/Android.bp b/flags/Android.bp index d5f0c1f3374..f9b84264f1b 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -43,6 +43,7 @@ aconfig_declarations { "metric.aconfig", "opp.aconfig", "pairing.aconfig", + "pbapclient.aconfig", "ranging.aconfig", "rfcomm.aconfig", "rnr.aconfig", diff --git a/flags/BUILD.gn b/flags/BUILD.gn index ba233689acc..6f98c239637 100644 --- a/flags/BUILD.gn +++ b/flags/BUILD.gn @@ -34,6 +34,7 @@ aconfig("bluetooth_flags_c_lib") { "metric.aconfig", "opp.aconfig", "pairing.aconfig", + "pbapclient.aconfig", "ranging.aconfig", "rfcomm.aconfig", "rnr.aconfig", diff --git a/flags/pbapclient.aconfig b/flags/pbapclient.aconfig new file mode 100644 index 00000000000..dbbbb7773b7 --- /dev/null +++ b/flags/pbapclient.aconfig @@ -0,0 +1,16 @@ +package: "com.android.bluetooth.flags" +container: "com.android.btservices" + +flag { + name: "pbap_client_storage_refactor" + namespace: "bluetooth" + description: "Abstract away accounts/storage and change how contacts are passed and stored" + bug: "376461939" +} + +flag { + name: "pbap_client_contacts_caching" + namespace: "bluetooth" + description: "Use primary and secondary versions to persist contacts across connections" + bug: "376461947" +} -- GitLab From 28286ee9f8d533257d14e8d2e90b62af1ae220df Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 30 Oct 2024 18:04:09 +0000 Subject: [PATCH 496/875] system/stack/smp: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I5d849b9f46bc5e113833821703b2a328396b35d2 --- system/stack/btm/btm_sec.cc | 3 --- system/stack/btu/btu_hcif.cc | 2 +- system/stack/include/smp_api.h | 2 ++ system/stack/smp/smp_act.cc | 4 +--- system/stack/smp/smp_int.h | 4 ++++ system/stack/smp/smp_keys.cc | 22 ++++++++-------------- system/stack/smp/smp_utils.cc | 5 +---- system/test/mock/mock_stack_smp_act.cc | 4 +--- 8 files changed, 18 insertions(+), 28 deletions(-) diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index e647715e40b..8a66c22c16c 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -3424,9 +3424,6 @@ static void read_encryption_key_size_complete_after_encryption_change(uint8_t st btm_sec_encrypt_change(handle, static_cast(status), 1 /* enable */, key_size); } -// TODO: Remove -void smp_cancel_start_encryption_attempt(); - /******************************************************************************* * * Function btm_encryption_change_evt diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc index f184626779a..9dc7d98bc26 100644 --- a/system/stack/btu/btu_hcif.cc +++ b/system/stack/btu/btu_hcif.cc @@ -55,6 +55,7 @@ #include "stack/include/main_thread.h" #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" @@ -68,7 +69,6 @@ using bluetooth::hci::IsoManager; bool BTM_BLE_IS_RESOLVE_BDA(const RawAddress& x); // TODO remove void BTA_sys_signal_hw_error(); // TODO remove -void smp_cancel_start_encryption_attempt(); // TODO remove void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason, std::string comment); // TODO remove diff --git a/system/stack/include/smp_api.h b/system/stack/include/smp_api.h index b9eeee4ff6b..6957c718752 100644 --- a/system/stack/include/smp_api.h +++ b/system/stack/include/smp_api.h @@ -207,4 +207,6 @@ bool smp_proc_ltk_request(const RawAddress& bda); // Proceed to send LTK, DIV and ER to central if bonding the devices. void smp_link_encrypted(const RawAddress& bda, uint8_t encr_enable); +void smp_cancel_start_encryption_attempt(); + #endif /* SMP_API_H */ diff --git a/system/stack/smp/smp_act.cc b/system/stack/smp/smp_act.cc index 07502a2a889..6de1db3ae8f 100644 --- a/system/stack/smp/smp_act.cc +++ b/system/stack/smp/smp_act.cc @@ -39,12 +39,10 @@ #include "stack/include/btm_client_interface.h" #include "stack/include/btm_log_history.h" #include "stack/include/btm_status.h" +#include "stack/include/smp_api.h" #include "stack/include/smp_api_types.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; namespace { diff --git a/system/stack/smp/smp_int.h b/system/stack/smp/smp_int.h index 2978212870e..dd51c0de4f9 100644 --- a/system/stack/smp/smp_int.h +++ b/system/stack/smp/smp_int.h @@ -489,6 +489,10 @@ void smp_start_nonce_generation(tSMP_CB* p_cb); bool smp_calculate_link_key_from_long_term_key(tSMP_CB* p_cb); bool smp_calculate_long_term_key_from_link_key(tSMP_CB* p_cb); +Octet16 smp_gen_p1_4_confirm(tSMP_CB* p_cb, tBLE_ADDR_TYPE remote_bd_addr_type); +Octet16 smp_gen_p2_4_confirm(tSMP_CB* p_cb, const RawAddress& remote_bda); +tSMP_STATUS smp_calculate_confirm(tSMP_CB* p_cb, const Octet16& rand, Octet16* output); + void print128(const Octet16& x, const char* key_name); void smp_xor_128(Octet16* a, const Octet16& b); diff --git a/system/stack/smp/smp_keys.cc b/system/stack/smp/smp_keys.cc index 801a3d4e630..f0fb8b9ba19 100644 --- a/system/stack/smp/smp_keys.cc +++ b/system/stack/smp/smp_keys.cc @@ -47,9 +47,6 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using bluetooth::common::BindOnce; using bluetooth::common::OnceCallback; using crypto_toolbox::aes_128; @@ -84,19 +81,16 @@ static bool is_oob_data_empty(tSMP_LOC_OOB_DATA* data) { bool smp_has_local_oob_data() { return !is_oob_data_empty(&saved_local_oob_data); } -void smp_debug_print_nbyte_little_endian(uint8_t* /* p */, const char* /* key_name */, - uint8_t /* len */) {} +static void smp_debug_print_nbyte_little_endian(uint8_t* /* p */, const char* /* key_name */, + uint8_t /* len */) {} -inline void smp_debug_print_nbyte_little_endian(const Octet16& p, const char* key_name, +static void smp_debug_print_nbyte_little_endian(const Octet16& p, const char* key_name, uint8_t len) { smp_debug_print_nbyte_little_endian(const_cast(p.data()), key_name, len); } -void smp_debug_print_nbyte_big_endian(uint8_t* /* p */, const char* /* key_name */, - uint8_t /* len */) {} - /** This function is called to process a passkey. */ -void smp_proc_passkey(tSMP_CB* p_cb, uint64_t rand) { +static void smp_proc_passkey(tSMP_CB* p_cb, uint64_t rand) { uint8_t* tt = p_cb->tk.data(); uint32_t passkey = static_cast(rand & SMP_PASSKEY_MASK); @@ -176,7 +170,7 @@ void smp_generate_stk(tSMP_CB* p_cb, tSMP_INT_DATA* /* p_data */) { /** * This function is called to calculate CSRK */ -void smp_compute_csrk(uint16_t div, tSMP_CB* p_cb) { +static void smp_compute_csrk(uint16_t div, tSMP_CB* p_cb) { Octet16 buffer{}; /* for (r || DIV) r=1*/ uint16_t r = 1; uint8_t* p = buffer.data(); @@ -216,10 +210,10 @@ void smp_generate_csrk(tSMP_CB* p_cb, tSMP_INT_DATA* /* p_data */) { } /******************************************************************************* - * Function smp_concatenate_peer - LSB first + * Function smp_concatenate_local - LSB first * add pairing command sent from local device into p1. ******************************************************************************/ -void smp_concatenate_local(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) { +static void smp_concatenate_local(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) { uint8_t* p = *p_data; log::verbose("addr:{}", p_cb->pairing_bda); @@ -238,7 +232,7 @@ void smp_concatenate_local(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) { * Function smp_concatenate_peer - LSB first * add pairing command received from peer device into p1. ******************************************************************************/ -void smp_concatenate_peer(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) { +static void smp_concatenate_peer(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) { uint8_t* p = *p_data; log::verbose("addr:{}", p_cb->pairing_bda); diff --git a/system/stack/smp/smp_utils.cc b/system/stack/smp/smp_utils.cc index 01a045bda9d..bcde927ba5c 100644 --- a/system/stack/smp/smp_utils.cc +++ b/system/stack/smp/smp_utils.cc @@ -71,9 +71,6 @@ Check*/) #define SMP_PAIR_KEYPR_NOTIF_SIZE (1 /* opcode */ + 1 /*Notif Type*/) -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; namespace { @@ -341,7 +338,7 @@ void smp_log_metrics(const RawAddress& bd_addr, bool is_outgoing, const uint8_t* * Description Send message to L2CAP. * ******************************************************************************/ -bool smp_send_msg_to_L2CAP(const RawAddress& rem_bda, BT_HDR* p_toL2CAP) { +static bool smp_send_msg_to_L2CAP(const RawAddress& rem_bda, BT_HDR* p_toL2CAP) { tL2CAP_DW_RESULT l2cap_ret; uint16_t fixed_cid = L2CAP_SMP_CID; diff --git a/system/test/mock/mock_stack_smp_act.cc b/system/test/mock/mock_stack_smp_act.cc index 486cf5dea7a..2802fb6fd3f 100644 --- a/system/test/mock/mock_stack_smp_act.cc +++ b/system/test/mock/mock_stack_smp_act.cc @@ -26,15 +26,13 @@ #include // Original included files, if any +#include "stack/include/smp_api.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" // Mocked compile conditionals, if any // Mocked internal structures, if any -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace test { namespace mock { namespace stack_smp_act { -- GitLab From 4038e37aeec274073381e2a9d03ba4c565c0dac2 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 29 Oct 2024 17:50:03 -0700 Subject: [PATCH 497/875] VCP: silence gmock warning in test The huge amount of GMOCK WARNING is making very difficult to look at the test logs without loosing my patience Since we don't care about its return value and don't want to enforce a strict mode, it make sense to use a nice mock Bug: 372328699 Flag: com.android.bluetooth.flags.aics_api Test: atest bluetooth_vc_test Change-Id: I0decbb7f6b36b6f4b9f914591d8dd3689e6b32fe --- system/bta/vc/devices_test.cc | 11 +- system/bta/vc/vc_test.cc | 277 +++++++++++++++++----------------- 2 files changed, 145 insertions(+), 143 deletions(-) diff --git a/system/bta/vc/devices_test.cc b/system/bta/vc/devices_test.cc index d2f389a8641..8b39a9e0123 100644 --- a/system/bta/vc/devices_test.cc +++ b/system/bta/vc/devices_test.cc @@ -44,6 +44,7 @@ using ::testing::_; using ::testing::DoAll; using ::testing::Invoke; using ::testing::Mock; +using ::testing::NiceMock; using ::testing::Return; using ::testing::SaveArg; using ::testing::SetArgPointee; @@ -74,8 +75,8 @@ protected: } VolumeControlDevices* devices_ = nullptr; - gatt::MockBtaGattInterface gatt_interface; - gatt::MockBtaGattQueue gatt_queue; + NiceMock gatt_interface; + NiceMock gatt_queue; }; TEST_F(VolumeControlDevicesTest, test_add) { @@ -361,9 +362,9 @@ protected: } VolumeControlDevice* device = nullptr; - gatt::MockBtaGattInterface gatt_interface; - gatt::MockBtaGattQueue gatt_queue; - bluetooth::manager::MockBtmInterface btm_interface; + NiceMock gatt_interface; + NiceMock gatt_queue; + NiceMock btm_interface; std::list services; }; diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index b0f203bc824..39954dd1e5e 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -48,6 +48,8 @@ struct alarm_t { bool on_main_loop = false; }; +using ::testing::NiceMock; + namespace bluetooth { namespace vc { namespace internal { @@ -315,7 +317,7 @@ private: std::vector value; auto add_element = [&](uint8_t data[], uint8_t len) -> void { - // LE order, 2 octects + // LE order, 2 octets value.push_back(len); value.push_back(0x00); @@ -434,7 +436,6 @@ protected: MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_); gatt::SetMockBtaGattInterface(&gatt_interface); gatt::SetMockBtaGattQueue(&gatt_queue); - callbacks.reset(new MockVolumeControlCallbacks()); reset_mock_function_count_map(); ON_CALL(btm_interface, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(true))); @@ -535,7 +536,6 @@ protected: void TearDown(void) override { com::android::bluetooth::flags::provider_->reset_flags(); services_map.clear(); - callbacks.reset(); gatt::SetMockBtaGattQueue(nullptr); gatt::SetMockBtaGattInterface(nullptr); bluetooth::manager::SetMockBtmInterface(nullptr); @@ -546,7 +546,7 @@ protected: BtaAppRegisterCallback app_register_callback; EXPECT_CALL(gatt_interface, AppRegister(_, _, _)) .WillOnce(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback))); - VolumeControl::Initialize(callbacks.get(), base::DoNothing()); + VolumeControl::Initialize(&callbacks, base::DoNothing()); ASSERT_TRUE(gatt_callback); ASSERT_TRUE(app_register_callback); app_register_callback.Run(gatt_if, GATT_SUCCESS); @@ -738,11 +738,12 @@ protected: set_sample_database(conn_id, true, false, true, false, true, false); } - std::unique_ptr callbacks; - bluetooth::manager::MockBtmInterface btm_interface; + NiceMock callbacks; + NiceMock btm_interface; MockCsisClient mock_csis_client_module_; - gatt::MockBtaGattInterface gatt_interface; - gatt::MockBtaGattQueue gatt_queue; + NiceMock gatt_interface; + NiceMock gatt_queue; + tBTA_GATTC_CBACK* gatt_callback; const uint8_t gatt_if = 0xff; std::map> services_map; @@ -756,7 +757,7 @@ TEST_F(VolumeControlTest, test_initialize) { EXPECT_CALL(gatt_interface, AppRegister(_, _, _)) .WillOnce(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback))); VolumeControl::Initialize( - callbacks.get(), + &callbacks, base::Bind([](bool* init_cb_called) { *init_cb_called = true; }, &init_cb_called)); ASSERT_TRUE(gatt_callback); ASSERT_TRUE(app_register_callback); @@ -768,15 +769,15 @@ TEST_F(VolumeControlTest, test_initialize) { } TEST_F(VolumeControlTest, test_initialize_twice) { - VolumeControl::Initialize(callbacks.get(), base::DoNothing()); + VolumeControl::Initialize(&callbacks, base::DoNothing()); VolumeControl* volume_control_p = VolumeControl::Get(); - VolumeControl::Initialize(callbacks.get(), base::DoNothing()); + VolumeControl::Initialize(&callbacks, base::DoNothing()); ASSERT_EQ(volume_control_p, VolumeControl::Get()); VolumeControl::CleanUp(); } TEST_F(VolumeControlTest, test_cleanup_initialized) { - VolumeControl::Initialize(callbacks.get(), base::DoNothing()); + VolumeControl::Initialize(&callbacks, base::DoNothing()); VolumeControl::CleanUp(); ASSERT_FALSE(VolumeControl::IsVolumeControlRunning()); } @@ -805,18 +806,18 @@ TEST_F(VolumeControlTest, test_connect_after_remove) { TestConnect(test_address); GetConnectedEvent(test_address, conn_id); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1); TestRemove(test_address, conn_id); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1); ON_CALL(btm_interface, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(false))); VolumeControl::Get()->Connect(test_address); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -828,15 +829,15 @@ TEST_F(VolumeControlTest, test_reconnect_after_interrupted_discovery) { SetSampleDatabaseVOCS(1); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0); - EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0); + EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0); GetConnectedEvent(test_address, 1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); // Remote disconnects in the middle of the service discovery - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); GetDisconnectedEvent(test_address, 1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); // This time let the service discovery pass ON_CALL(gatt_interface, ServiceSearchRequest(_, _)) @@ -847,19 +848,19 @@ TEST_F(VolumeControlTest, test_reconnect_after_interrupted_discovery) { })); // Remote is being connected by another GATT client - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); - EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); + EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _)); GetConnectedEvent(test_address, 1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); // Request connect when the remote was already connected by another service - EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); + EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); VolumeControl::Get()->Connect(test_address); // The GetConnectedEvent(test_address, 1); should not be triggered here, since // GATT implementation will not send this event for the already connected // device - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -871,14 +872,14 @@ TEST_F(VolumeControlTest, test_verify_opportunistic_connect_active_after_connect TestAddFromStorage(address); Mock::VerifyAndClearExpectations(&gatt_interface); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)).Times(1); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)).Times(1); TestConnect(address); EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, _)).Times(0); EXPECT_CALL(gatt_interface, Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, true)).Times(1); GetConnectedEvent(address, 1, GATT_ERROR); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); Mock::VerifyAndClearExpectations(&gatt_interface); TestAppUnregister(); } @@ -890,12 +891,12 @@ TEST_F(VolumeControlTest, test_reconnect_after_timeout) { SetSampleDatabaseVOCS(1); TestAppRegister(); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, address)).Times(0); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, address)).Times(0); TestConnect(address); // Disconnect not connected device - upper layer times out and needs a // disconnection event to leave the transient Connecting state - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)); EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, false)).Times(0); TestDisconnect(address, 0); @@ -909,16 +910,16 @@ TEST_F(VolumeControlTest, test_reconnect_after_timeout) { GetSearchCompleteEvent(conn_id); } })); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, address)); - EXPECT_CALL(*callbacks, OnDeviceAvailable(address, 2, _)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, address)); + EXPECT_CALL(callbacks, OnDeviceAvailable(address, 2, _)); GetConnectedEvent(address, 1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); // Make sure that the upper layer gets the disconnection event even if not // connecting actively anymore due to the mentioned time-out mechanism. - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)); GetDisconnectedEvent(address, 1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -932,7 +933,7 @@ TEST_F(VolumeControlTest, test_remove_non_connected) { const RawAddress test_address = GetTestAddress(0); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); TestRemove(test_address, 0); TestAppUnregister(); } @@ -942,7 +943,7 @@ TEST_F(VolumeControlTest, test_remove_connected) { TestAppRegister(); TestConnect(test_address); GetConnectedEvent(test_address, 1); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); TestDisconnect(test_address, 1); TestAppUnregister(); } @@ -951,7 +952,7 @@ TEST_F(VolumeControlTest, test_disconnect_non_connected) { const RawAddress test_address = GetTestAddress(0); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); TestDisconnect(test_address, 0); TestAppUnregister(); } @@ -961,7 +962,7 @@ TEST_F(VolumeControlTest, test_disconnect_connected) { TestAppRegister(); TestConnect(test_address); GetConnectedEvent(test_address, 1); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); TestDisconnect(test_address, 1); TestAppUnregister(); } @@ -971,7 +972,7 @@ TEST_F(VolumeControlTest, test_disconnected) { TestAppRegister(); TestConnect(test_address); GetConnectedEvent(test_address, 1); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); GetDisconnectedEvent(test_address, 1); TestAppUnregister(); } @@ -982,7 +983,7 @@ TEST_F(VolumeControlTest, test_disconnected_while_autoconnect) { TestAddFromStorage(test_address); GetConnectedEvent(test_address, 1); // autoconnect - don't indicate disconnection - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0); GetDisconnectedEvent(test_address, 1); TestAppUnregister(); } @@ -997,7 +998,7 @@ TEST_F(VolumeControlTest, test_disconnect_when_link_key_gone) { .WillByDefault(Return(tBTM_STATUS::BTM_ERR_KEY_MISSING)); // autoconnect - don't indicate disconnection - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0); EXPECT_CALL(gatt_interface, Close(1)); GetConnectedEvent(test_address, 1); Mock::VerifyAndClearExpectations(&btm_interface); @@ -1010,7 +1011,7 @@ TEST_F(VolumeControlTest, test_reconnect_after_encryption_failed) { TestAddFromStorage(test_address); SetEncryptionResult(test_address, false); // autoconnect - don't indicate disconnection - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0); GetConnectedEvent(test_address, 1); Mock::VerifyAndClearExpectations(&btm_interface); SetEncryptionResult(test_address, true); @@ -1029,14 +1030,14 @@ TEST_F(VolumeControlTest, test_service_discovery_completed_before_encryption) { ON_CALL(btm_interface, SetEncryption(test_address, _, _, _, _)) .WillByDefault(Return(tBTM_STATUS::BTM_SUCCESS)); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0); uint16_t conn_id = 1; GetConnectedEvent(test_address, conn_id); GetSearchCompleteEvent(conn_id); Mock::VerifyAndClearExpectations(&btm_interface); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(1); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(1); ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(DoAll(Return(true))); EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _)); @@ -1044,7 +1045,7 @@ TEST_F(VolumeControlTest, test_service_discovery_completed_before_encryption) { GetEncryptionCompleteEvt(test_address); GetSearchCompleteEvent(conn_id); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); Mock::VerifyAndClearExpectations(&gatt_interface); TestAppUnregister(); @@ -1055,11 +1056,11 @@ TEST_F(VolumeControlTest, test_discovery_vcs_found) { SetSampleDatabaseVCS(1); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _, _)); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); + EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, _, _)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); GetConnectedEvent(test_address, 1); GetSearchCompleteEvent(1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -1068,11 +1069,11 @@ TEST_F(VolumeControlTest, test_discovery_vcs_not_found) { SetSampleDatabaseNoVCS(1); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); GetConnectedEvent(test_address, 1); GetSearchCompleteEvent(1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -1081,10 +1082,10 @@ TEST_F(VolumeControlTest, test_discovery_vcs_broken) { SetSampleDatabaseVCSBroken(1); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); GetConnectedEvent(test_address, 1); GetSearchCompleteEvent(1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -1110,7 +1111,7 @@ TEST_F(VolumeControlTest, test_subscribe_vocs_output_description) { TEST_F(VolumeControlTest, test_read_vcs_volume_state) { const RawAddress test_address = GetTestAddress(0); - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _, true)).Times(1); + EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, _, _, _, true)).Times(1); std::vector handles({0x0021}); TestReadCharacteristic(test_address, 1, handles); } @@ -1123,29 +1124,29 @@ TEST_F(VolumeControlTest, test_read_vcs_volume_flags) { TEST_F(VolumeControlTest, test_read_vocs_volume_offset) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(false); const RawAddress test_address = GetTestAddress(0); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); std::vector handles({0x0072, 0x0082}); TestReadCharacteristic(test_address, 1, handles); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); } TEST_F(VolumeControlTest, test_read_vocs_volume_offset_multi) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true); const RawAddress test_address = GetTestAddress(0); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); std::vector handles({0x0072, 0x0082}); TestReadCharacteristic(test_address, 1, handles); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); } TEST_F(VolumeControlTest, test_read_vocs_offset_location) { @@ -1153,15 +1154,15 @@ TEST_F(VolumeControlTest, test_read_vocs_offset_location) { const RawAddress test_address = GetTestAddress(0); // It is called twice because after connect read is done once and second read is coming from the // test. - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); std::vector handles({0x0075, 0x0085}); TestReadCharacteristic(test_address, 1, handles); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); } TEST_F(VolumeControlTest, test_read_vocs_offset_location_multi) { @@ -1169,26 +1170,26 @@ TEST_F(VolumeControlTest, test_read_vocs_offset_location_multi) { const RawAddress test_address = GetTestAddress(0); // It is called twice because after connect read is done once and second read is coming from the // test. - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); std::vector handles({0x0075, 0x0085}); TestReadCharacteristic(test_address, 1, handles); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); } TEST_F(VolumeControlTest, test_read_vocs_output_description) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(false); const RawAddress test_address = GetTestAddress(0); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); std::vector handles({0x0079, 0x008a}); TestReadCharacteristic(test_address, 1, handles); } @@ -1196,12 +1197,12 @@ TEST_F(VolumeControlTest, test_read_vocs_output_description) { TEST_F(VolumeControlTest, test_read_vocs_output_description_multi) { com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true); const RawAddress test_address = GetTestAddress(0); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1); std::vector handles({0x0079, 0x008a}); TestReadCharacteristic(test_address, 1, handles); } @@ -1211,11 +1212,11 @@ TEST_F(VolumeControlTest, test_discovery_vocs_found) { SetSampleDatabaseVOCS(1); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); - EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); + EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _)); GetConnectedEvent(test_address, 1); GetSearchCompleteEvent(1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -1224,11 +1225,11 @@ TEST_F(VolumeControlTest, test_discovery_vocs_not_found) { SetSampleDatabaseVCS(1); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); - EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 0, _)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); + EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 0, _)); GetConnectedEvent(test_address, 1); GetSearchCompleteEvent(1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } @@ -1237,17 +1238,17 @@ TEST_F(VolumeControlTest, test_discovery_vocs_broken) { SetSampleDatabaseVOCSBroken(1); TestAppRegister(); TestConnect(test_address); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); - EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 1, _)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)); + EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 1, _)); GetConnectedEvent(test_address, 1); GetSearchCompleteEvent(1); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); TestAppUnregister(); } TEST_F(VolumeControlTest, test_read_vcs_database_out_of_sync) { const RawAddress test_address = GetTestAddress(0); - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _, true)); + EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, _, _, _, true)); std::vector handles({0x0021}); uint16_t conn_id = 1; @@ -1320,12 +1321,12 @@ protected: TEST_F(VolumeControlCallbackTest, test_volume_state_changed_stress) { std::vector value({0x03, 0x01, 0x02}); - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true, _, true)); + EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, 0x03, true, _, true)); GetNotificationEvent(0x0021, value); } TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) { - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _, _)).Times(0); + EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, _, _, _, _)).Times(0); std::vector too_short({0x03, 0x01}); GetNotificationEvent(0x0021, too_short); std::vector too_long({0x03, 0x01, 0x02, 0x03}); @@ -1334,12 +1335,12 @@ TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed) { std::vector value({0x03, 0x01, 0x02, 0x04}); - EXPECT_CALL(*callbacks, OnExtAudioInStateChanged(test_address, 1, 0x03, 0x02, true)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x03, 0x02, true)); GetNotificationEvent(0x0032, value); } TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed_malformed) { - EXPECT_CALL(*callbacks, OnExtAudioInStateChanged(test_address, 1, _, _, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, _, _, _)).Times(0); std::vector too_short({0x03, 0x01, 0x02}); GetNotificationEvent(0x0032, too_short); std::vector too_long({0x03, 0x01, 0x02, 0x04, 0x05}); @@ -1348,12 +1349,12 @@ TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed) { std::vector value({0x03, 0x01, 0x02}); - EXPECT_CALL(*callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x03, 0x01, 0x02)); + EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x03, 0x01, 0x02)); GetNotificationEvent(0x0055, value); } TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed_malformed) { - EXPECT_CALL(*callbacks, OnExtAudioInGainPropsChanged(test_address, 2, _, _, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 2, _, _, _)).Times(0); std::vector too_short({0x03, 0x01}); GetNotificationEvent(0x0055, too_short); std::vector too_long({0x03, 0x01, 0x02, 0x03}); @@ -1362,13 +1363,13 @@ TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed) { std::vector value({static_cast(bluetooth::vc::VolumeInputStatus::Inactive)}); - EXPECT_CALL(*callbacks, OnExtAudioInStatusChanged(test_address, 1, - bluetooth::vc::VolumeInputStatus::Inactive)); + EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, 1, + bluetooth::vc::VolumeInputStatus::Inactive)); GetNotificationEvent(0x0039, value); } TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed_malformed) { - EXPECT_CALL(*callbacks, OnExtAudioInStatusChanged(test_address, 1, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, 1, _)).Times(0); std::vector too_short(0); GetNotificationEvent(0x0039, too_short); std::vector too_long({0x03, 0x01}); @@ -1378,18 +1379,18 @@ TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_input_description_changed) { std::string descr = "SPDIF"; std::vector value(descr.begin(), descr.end()); - EXPECT_CALL(*callbacks, OnExtAudioInDescriptionChanged(test_address, 2, descr)); + EXPECT_CALL(callbacks, OnExtAudioInDescriptionChanged(test_address, 2, descr)); GetNotificationEvent(0x005e, value); } TEST_F(VolumeControlCallbackTest, test_volume_offset_changed) { std::vector value({0x04, 0x05, 0x06}); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, 0x0504)); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, 0x0504)); GetNotificationEvent(0x0082, value); } TEST_F(VolumeControlCallbackTest, test_volume_offset_changed_malformed) { - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(0); std::vector too_short({0x04}); GetNotificationEvent(0x0082, too_short); std::vector too_long({0x04, 0x05, 0x06, 0x07}); @@ -1398,12 +1399,12 @@ TEST_F(VolumeControlCallbackTest, test_volume_offset_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_offset_location_changed) { std::vector value({0x01, 0x02, 0x03, 0x04}); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201)); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201)); GetNotificationEvent(0x0085, value); } TEST_F(VolumeControlCallbackTest, test_offset_location_changed_malformed) { - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(0); std::vector too_short({0x04}); GetNotificationEvent(0x0085, too_short); std::vector too_long({0x04, 0x05, 0x06}); @@ -1413,7 +1414,7 @@ TEST_F(VolumeControlCallbackTest, test_offset_location_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_output_description_changed) { std::string descr = "left"; std::vector value(descr.begin(), descr.end()); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr)); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr)); GetNotificationEvent(0x008a, value); } @@ -1449,7 +1450,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_out_volume_offset) { VolumeControl::Get()->GetExtAudioOutVolumeOffset(test_address, 1); EXPECT_TRUE(cb); std::vector value({0x01, 0x02, 0x03}); - EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, 0x0201)); + EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, 0x0201)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1457,7 +1458,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_out_location) { VolumeControl::Get()->GetExtAudioOutLocation(test_address, 2); EXPECT_TRUE(cb); std::vector value({0x01, 0x02, 0x03, 0x04}); - EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201)); + EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1466,7 +1467,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_out_description) { EXPECT_TRUE(cb); std::string descr = "right"; std::vector value(descr.begin(), descr.end()); - EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr)); + EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1474,7 +1475,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_state) { VolumeControl::Get()->GetExtAudioInState(test_address, 1); EXPECT_TRUE(cb); std::vector value({0x01, 0x00, 0x02, 0x03}); - EXPECT_CALL(*callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, false)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, false)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1482,7 +1483,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_status) { VolumeControl::Get()->GetExtAudioInStatus(test_address, 2); EXPECT_TRUE(cb); std::vector value({static_cast(bluetooth::vc::VolumeInputStatus::Active)}); - EXPECT_CALL(*callbacks, + EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, 2, bluetooth::vc::VolumeInputStatus::Active)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1491,7 +1492,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_gain_props) { VolumeControl::Get()->GetExtAudioInGainProps(test_address, 2); EXPECT_TRUE(cb); std::vector value({0x01, 0x02, 0x03}); - EXPECT_CALL(*callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x01, 0x02, 0x03)); + EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x01, 0x02, 0x03)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1500,7 +1501,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_description) { EXPECT_TRUE(cb); std::string descr = "AUX-IN"; std::vector value(descr.begin(), descr.end()); - EXPECT_CALL(*callbacks, OnExtAudioInDescriptionChanged(test_address, 1, descr)); + EXPECT_CALL(callbacks, OnExtAudioInDescriptionChanged(test_address, 1, descr)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1508,7 +1509,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_type) { VolumeControl::Get()->GetExtAudioInType(test_address, 1); EXPECT_TRUE(cb); std::vector value({static_cast(bluetooth::vc::VolumeInputType::Ambient)}); - EXPECT_CALL(*callbacks, + EXPECT_CALL(callbacks, OnExtAudioInTypeChanged(test_address, 1, bluetooth::vc::VolumeInputType::Ambient)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1641,11 +1642,11 @@ TEST_F(VolumeControlValueSetTest, test_volume_operation_failed_due_to_device_dis ASSERT_NE(active_alarm_cb, nullptr); EXPECT_CALL(*AlarmMock::Get(), AlarmCancel(_)).Times(1); - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)); GetDisconnectedEvent(test_address, conn_id); ASSERT_EQ(active_alarm_cb, nullptr); - Mock::VerifyAndClearExpectations(callbacks.get()); + Mock::VerifyAndClearExpectations(&callbacks); } TEST_F(VolumeControlValueSetTest, test_set_volume) { @@ -1932,7 +1933,7 @@ TEST_F(VolumeControlCsis, test_set_volume) { VolumeControl::Get()->SetVolume(group_id, 10); /* Now inject notification and make sure callback is sent up to Java layer */ - EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true, false)); + EXPECT_CALL(callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true, false)); std::vector value({0x03, 0x01, 0x02}); GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value); @@ -1947,8 +1948,8 @@ TEST_F(VolumeControlCsis, test_set_volume) { VolumeControl::Get()->SetVolume(test_address_1, 20); VolumeControl::Get()->SetVolume(test_address_2, 20); - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address_1, 20, false, _, false)); - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address_2, 20, false, _, false)); + EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address_1, 20, false, _, false)); + EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address_2, 20, false, _, false)); std::vector value2({20, 0x00, 0x03}); GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value2); GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value2); @@ -1983,7 +1984,7 @@ TEST_F(VolumeControlCsis, autonomus_test_set_volume) { GetSearchCompleteEvent(conn_id_2); /* Now inject notification and make sure callback is sent up to Java layer */ - EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true)); + EXPECT_CALL(callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true)); std::vector value({0x03, 0x00, 0x02}); GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value); @@ -1999,11 +2000,11 @@ TEST_F(VolumeControlCsis, autonomus_single_device_test_set_volume) { GetSearchCompleteEvent(conn_id_2); /* Disconnect one device. */ - EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address_1)); + EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address_1)); GetDisconnectedEvent(test_address_1, conn_id_1); /* Now inject notification and make sure callback is sent up to Java layer */ - EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true)); + EXPECT_CALL(callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true)); std::vector value({0x03, 0x00, 0x02}); GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value); -- GitLab From 504ee53834f2b8ad1b5cbcb9bdcac90ac00135b7 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 18:20:58 -0700 Subject: [PATCH 498/875] Aics: shift ids to start at 0 Bug: 372328699 Flag: com.android.bluetooth.flags.aics_api Test: atest vc_test Change-Id: I97e343899b33d3b20c5bd275bb4b537cc70d690d --- .../bluetooth/vc/VolumeControlService.java | 5 +- system/bta/vc/device.cc | 76 ++++++----- system/bta/vc/devices.h | 2 +- system/bta/vc/devices_test.cc | 36 ++--- system/bta/vc/types.h | 128 +++++++++--------- system/bta/vc/vc_test.cc | 40 +++--- 6 files changed, 144 insertions(+), 143 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 99f296b9be1..0efd36f6bef 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -947,9 +947,8 @@ public class VolumeControlService extends ProfileService { inputs.clear(); } - /* Stack delivers us number of audio inputs. - * Offset ids a countinous from 1 to numberOfExternalInputs*/ - for (int i = 1; i <= numberOfExternalInputs; i++) { + // Stack delivers us number of audio inputs. ids are countinous from [0;n[ + for (int i = 0; i < numberOfExternalInputs; i++) { inputs.add(i); } } diff --git a/system/bta/vc/device.cc b/system/bta/vc/device.cc index f4f016f2d9b..43f1e61d56e 100644 --- a/system/bta/vc/device.cc +++ b/system/bta/vc/device.cc @@ -123,53 +123,61 @@ bool VolumeControlDevice::set_volume_control_service_handles(const gatt::Service } void VolumeControlDevice::set_audio_input_control_service_handles(const gatt::Service& service) { - VolumeAudioInput input = VolumeAudioInput(service.handle); + uint16_t state_handle{0}; + uint16_t state_ccc_handle{0}; + uint16_t gain_setting_handle{0}; + uint16_t type_handle{0}; + uint16_t status_handle{0}; + uint16_t status_ccc_handle{0}; + uint16_t control_point_handle{0}; + uint16_t description_handle{0}; + uint16_t description_ccc_handle{0}; + uint16_t description_writable{0}; + for (const gatt::Characteristic& chrc : service.characteristics) { if (chrc.uuid == kVolumeAudioInputStateUuid) { - input.state_handle = chrc.value_handle; - input.state_ccc_handle = find_ccc_handle(chrc.value_handle); - log::debug("{}, input_state handle={:#x}, ccc {:#x}", address, input.state_handle, - input.state_ccc_handle); - - } else if (chrc.uuid == kVolumeAudioInputGainSettingUuid) { - input.gain_setting_handle = chrc.value_handle; - + state_handle = chrc.value_handle; + state_ccc_handle = find_ccc_handle(chrc.value_handle); + log::debug("{} state_handle={:#x} ccc={:#x}", address, state_handle, state_ccc_handle); + } else if (chrc.uuid == kVolumeAudioInputGainSettingPropertiesUuid) { + gain_setting_handle = chrc.value_handle; } else if (chrc.uuid == kVolumeAudioInputTypeUuid) { - input.type_handle = chrc.value_handle; - + type_handle = chrc.value_handle; } else if (chrc.uuid == kVolumeAudioInputStatusUuid) { - input.status_handle = chrc.value_handle; - input.status_ccc_handle = find_ccc_handle(chrc.value_handle); - log::debug("{}, input_status handle={:#x}, ccc {:#x}", address, input.status_handle, - input.status_ccc_handle); - + status_handle = chrc.value_handle; + status_ccc_handle = find_ccc_handle(chrc.value_handle); + log::debug("{} status_handle={:#x} ccc={:#x}", address, status_handle, status_ccc_handle); } else if (chrc.uuid == kVolumeAudioInputControlPointUuid) { - input.control_point_handle = chrc.value_handle; - + control_point_handle = chrc.value_handle; } else if (chrc.uuid == kVolumeAudioInputDescriptionUuid) { - input.description_handle = chrc.value_handle; - input.description_ccc_handle = find_ccc_handle(chrc.value_handle); - input.description_writable = chrc.properties & GATT_CHAR_PROP_BIT_WRITE_NR; - log::debug("{}, input_desc handle={:#x}, ccc {:#x}", address, input.description_handle, - input.description_ccc_handle); - + description_handle = chrc.value_handle; + description_ccc_handle = find_ccc_handle(chrc.value_handle); + description_writable = chrc.properties & GATT_CHAR_PROP_BIT_WRITE_NR; + log::debug("{} description_handle={:#x} ccc={:#x}", address, description_handle, + description_ccc_handle); } else { - log::warn("unknown characteristic={}", chrc.uuid); + log::info("found unexpected characteristic={}", chrc.uuid); } } // Check if all mandatory attributes are present - if (GATT_HANDLE_IS_VALID(input.state_handle) && GATT_HANDLE_IS_VALID(input.state_ccc_handle) && - GATT_HANDLE_IS_VALID(input.gain_setting_handle) && GATT_HANDLE_IS_VALID(input.type_handle) && - GATT_HANDLE_IS_VALID(input.status_handle) && GATT_HANDLE_IS_VALID(input.status_ccc_handle) && - GATT_HANDLE_IS_VALID(input.control_point_handle) && - GATT_HANDLE_IS_VALID(input.description_handle) + if (!GATT_HANDLE_IS_VALID(state_handle) || !GATT_HANDLE_IS_VALID(state_ccc_handle) || + !GATT_HANDLE_IS_VALID(gain_setting_handle) || !GATT_HANDLE_IS_VALID(type_handle) || + !GATT_HANDLE_IS_VALID(status_handle) || !GATT_HANDLE_IS_VALID(status_ccc_handle) || + !GATT_HANDLE_IS_VALID(control_point_handle) || !GATT_HANDLE_IS_VALID(description_handle) /* description_ccc_handle is optional */) { - audio_inputs.Add(input); - log::info("{}, input added id={:#x}", address, input.id); - } else { - log::warn("{}, ignoring input handle={:#x}", address, service.handle); + log::error( + "The remote device {} does not comply with AICS 1-0, some handles are invalid. " + "The aics service with handle {:#x} will be ignored", + address, service.handle); + return; } + VolumeAudioInput input = VolumeAudioInput( + audio_inputs.Size(), service.handle, state_handle, state_ccc_handle, gain_setting_handle, + type_handle, status_handle, status_ccc_handle, control_point_handle, description_handle, + description_ccc_handle, description_writable); + audio_inputs.Add(input); + log::info("{}, input added id={:#x}", address, input.id); } void VolumeControlDevice::set_volume_offset_control_service_handles(const gatt::Service& service) { diff --git a/system/bta/vc/devices.h b/system/bta/vc/devices.h index 3e810726cb4..8c0a5739c43 100644 --- a/system/bta/vc/devices.h +++ b/system/bta/vc/devices.h @@ -156,7 +156,7 @@ private: /* * This is used to track the pending GATT operation handles. Once the list is * empty the device is assumed ready and connected. We are doing it because we - * want to make sure all the required characteristics and descritors are + * want to make sure all the required characteristics and descriptors are * available on server side. */ std::unordered_set handles_pending; diff --git a/system/bta/vc/devices_test.cc b/system/bta/vc/devices_test.cc index 8b39a9e0123..fea281c7010 100644 --- a/system/bta/vc/devices_test.cc +++ b/system/bta/vc/devices_test.cc @@ -289,7 +289,7 @@ protected: builder.AddService(0x0020, 0x002e, kVolumeAudioInputUuid, false); builder.AddCharacteristic(0x0021, 0x0022, kVolumeAudioInputStateUuid, GATT_CHAR_PROP_BIT_READ); builder.AddDescriptor(0x0023, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); - builder.AddCharacteristic(0x0024, 0x0025, kVolumeAudioInputGainSettingUuid, + builder.AddCharacteristic(0x0024, 0x0025, kVolumeAudioInputGainSettingPropertiesUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0026, 0x0027, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0028, 0x0029, kVolumeAudioInputStatusUuid, @@ -305,7 +305,7 @@ protected: builder.AddCharacteristic(0x0041, 0x0042, kVolumeAudioInputStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x0043, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); - builder.AddCharacteristic(0x0044, 0x0045, kVolumeAudioInputGainSettingUuid, + builder.AddCharacteristic(0x0044, 0x0045, kVolumeAudioInputGainSettingPropertiesUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0046, 0x0047, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0048, 0x0049, kVolumeAudioInputStatusUuid, @@ -388,7 +388,7 @@ TEST_F(VolumeControlDeviceTest, test_service_aics_incomplete) { builder.AddCharacteristic(0x000c, 0x000d, kVolumeAudioInputStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); - builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingUuid, + builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingPropertiesUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0011, 0x0012, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0013, 0x0014, kVolumeAudioInputStatusUuid, @@ -424,7 +424,7 @@ TEST_F(VolumeControlDeviceTest, test_service_aics_found) { builder.AddCharacteristic(0x000c, 0x000d, kVolumeAudioInputStateUuid, GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); - builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingUuid, + builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingPropertiesUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0011, 0x0012, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0013, 0x0014, kVolumeAudioInputStatusUuid, @@ -543,8 +543,8 @@ TEST_F(VolumeControlDeviceTest, test_multiple_services_found) { SetSampleDatabase1(); ASSERT_EQ((size_t)2, device->audio_offsets.Size()); ASSERT_EQ((size_t)2, device->audio_inputs.Size()); - VolumeAudioInput* input_1 = device->audio_inputs.FindById(1); - VolumeAudioInput* input_2 = device->audio_inputs.FindById(2); + VolumeAudioInput* input_1 = device->audio_inputs.FindById(0); + VolumeAudioInput* input_2 = device->audio_inputs.FindById(1); ASSERT_NE(nullptr, input_1); ASSERT_NE(nullptr, input_2); ASSERT_NE(input_1->service_handle, input_2->service_handle); @@ -579,7 +579,7 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) { tGATT_IF gatt_if = 0x0001; std::vector register_for_notification_data({0x01, 0x00}); - std::map expected_subscribtions{ + std::map expected_subscriptions{ {0x0011, 0x0012} /* volume control state */, {0x0016, 0x0017} /* volume control flags */, {0x0022, 0x0023} /* audio input state 1 */, @@ -596,7 +596,7 @@ TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) { EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0011, _, _)); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0016, _, _)); - for (auto const& handle_pair : expected_subscribtions) { + for (auto const& handle_pair : expected_subscriptions) { EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second, register_for_notification_data, GATT_WRITE, _, _)); EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first)); @@ -857,7 +857,7 @@ TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_state) { uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0022, read_cb, nullptr)); - device->GetExtAudioInState(1, read_cb, nullptr); + device->GetExtAudioInState(0, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_status) { @@ -865,7 +865,7 @@ TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_status) { uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0049, read_cb, nullptr)); - device->GetExtAudioInStatus(2, read_cb, nullptr); + device->GetExtAudioInStatus(1, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_gain_props) { @@ -873,7 +873,7 @@ TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_gain_props) { uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0025, read_cb, nullptr)); - device->GetExtAudioInGainProps(1, read_cb, nullptr); + device->GetExtAudioInGainProps(0, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_description) { @@ -881,7 +881,7 @@ TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_description) { uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x002e, read_cb, nullptr)); - device->GetExtAudioInDescription(1, read_cb, nullptr); + device->GetExtAudioInDescription(0, read_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description) { @@ -890,7 +890,7 @@ TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description) { std::vector expected_data(descr.begin(), descr.end()); EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x004e, expected_data, GATT_WRITE_NO_RSP, nullptr, nullptr)); - device->SetExtAudioInDescription(2, descr); + device->SetExtAudioInDescription(1, descr); } TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description_non_writable) { @@ -898,34 +898,34 @@ TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description_non_writable) std::string descr = "AUX"; std::vector expected_data(descr.begin(), descr.end()); EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0); - device->SetExtAudioInDescription(1, descr); + device->SetExtAudioInDescription(0, descr); } TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation) { GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); - VolumeAudioInput* input = device->audio_inputs.FindById(2); + VolumeAudioInput* input = device->audio_inputs.FindById(1); ASSERT_NE(nullptr, input); input->change_counter = 0x11; std::vector expected_data({0x0c, 0x11}); EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x004c, expected_data, GATT_WRITE, write_cb, nullptr)); - device->ExtAudioInControlPointOperation(2, 0x0c, nullptr, write_cb, nullptr); + device->ExtAudioInControlPointOperation(1, 0x0c, nullptr, write_cb, nullptr); } TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation_arg) { GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/, uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {}; SetSampleDatabase1(); - VolumeAudioInput* input = device->audio_inputs.FindById(2); + VolumeAudioInput* input = device->audio_inputs.FindById(1); ASSERT_NE(nullptr, input); input->change_counter = 0x12; std::vector expected_data({0x0d, 0x12, 0x01, 0x02, 0x03, 0x04}); std::vector arg({0x01, 0x02, 0x03, 0x04}); EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x004c, expected_data, GATT_WRITE, write_cb, nullptr)); - device->ExtAudioInControlPointOperation(2, 0x0d, &arg, write_cb, nullptr); + device->ExtAudioInControlPointOperation(1, 0x0d, &arg, write_cb, nullptr); } } // namespace internal diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h index f1f35a1b854..bdb242bb20f 100644 --- a/system/bta/vc/types.h +++ b/system/bta/vc/types.h @@ -53,24 +53,24 @@ static constexpr uint8_t kVolumeInputControlPointOpcodeMute = 0x static constexpr uint8_t kVolumeInputControlPointOpcodeSetManualGainMode = 0x04; static constexpr uint8_t kVolumeInputControlPointOpcodeSetAutoGainMode = 0x05; -static const Uuid kVolumeControlUuid = Uuid::From16Bit(0x1844); -static const Uuid kVolumeControlStateUuid = Uuid::From16Bit(0x2B7D); -static const Uuid kVolumeControlPointUuid = Uuid::From16Bit(0x2B7E); -static const Uuid kVolumeFlagsUuid = Uuid::From16Bit(0x2B7F); - -static const Uuid kVolumeOffsetUuid = Uuid::From16Bit(0x1845); -static const Uuid kVolumeOffsetStateUuid = Uuid::From16Bit(0x2B80); -static const Uuid kVolumeOffsetLocationUuid = Uuid::From16Bit(0x2B81); -static const Uuid kVolumeOffsetControlPointUuid = Uuid::From16Bit(0x2B82); -static const Uuid kVolumeOffsetOutputDescriptionUuid = Uuid::From16Bit(0x2B83); - -static const Uuid kVolumeAudioInputUuid = Uuid::From16Bit(0x1843); -static const Uuid kVolumeAudioInputStateUuid = Uuid::From16Bit(0x2B77); -static const Uuid kVolumeAudioInputGainSettingUuid = Uuid::From16Bit(0x2B78); -static const Uuid kVolumeAudioInputTypeUuid = Uuid::From16Bit(0x2B79); -static const Uuid kVolumeAudioInputStatusUuid = Uuid::From16Bit(0x2B7A); -static const Uuid kVolumeAudioInputControlPointUuid = Uuid::From16Bit(0x2B7B); -static const Uuid kVolumeAudioInputDescriptionUuid = Uuid::From16Bit(0x2B7C); +static const Uuid kVolumeControlUuid = Uuid::From16Bit(0x1844); +static const Uuid kVolumeControlStateUuid = Uuid::From16Bit(0x2B7D); +static const Uuid kVolumeControlPointUuid = Uuid::From16Bit(0x2B7E); +static const Uuid kVolumeFlagsUuid = Uuid::From16Bit(0x2B7F); + +static const Uuid kVolumeOffsetUuid = Uuid::From16Bit(0x1845); +static const Uuid kVolumeOffsetStateUuid = Uuid::From16Bit(0x2B80); +static const Uuid kVolumeOffsetLocationUuid = Uuid::From16Bit(0x2B81); +static const Uuid kVolumeOffsetControlPointUuid = Uuid::From16Bit(0x2B82); +static const Uuid kVolumeOffsetOutputDescriptionUuid = Uuid::From16Bit(0x2B83); + +static const Uuid kVolumeAudioInputUuid = Uuid::From16Bit(0x1843); +static const Uuid kVolumeAudioInputStateUuid = Uuid::From16Bit(0x2B77); +static const Uuid kVolumeAudioInputGainSettingPropertiesUuid = Uuid::From16Bit(0x2B78); +static const Uuid kVolumeAudioInputTypeUuid = Uuid::From16Bit(0x2B79); +static const Uuid kVolumeAudioInputStatusUuid = Uuid::From16Bit(0x2B7A); +static const Uuid kVolumeAudioInputControlPointUuid = Uuid::From16Bit(0x2B7B); +static const Uuid kVolumeAudioInputDescriptionUuid = Uuid::From16Bit(0x2B7C); /* clang-format on */ @@ -127,64 +127,58 @@ struct VolumeOperation { }; struct GainSettings { - uint8_t unit; - int8_t min; - int8_t max; + uint8_t unit = 0; + int8_t min = 0; + int8_t max = 0; - GainSettings() : unit(0), min(0), max(0) {} + GainSettings() {} }; struct VolumeAudioInput { - uint8_t id; - bool mute; - int8_t gain_value; - VolumeInputStatus status; - VolumeInputType type; - uint8_t change_counter; - uint8_t mode; - std::string description; - uint16_t service_handle; - uint16_t state_handle; - uint16_t state_ccc_handle; - uint16_t gain_setting_handle; - uint16_t type_handle; - uint16_t status_handle; - uint16_t status_ccc_handle; - uint16_t control_point_handle; - uint16_t description_handle; - uint16_t description_ccc_handle; - bool description_writable; - struct GainSettings gain_settings; - - explicit VolumeAudioInput(uint16_t service_handle) - : id(0), - mute(false), - gain_value(0), - status(VolumeInputStatus::Inactive), - type(VolumeInputType::Unspecified), - change_counter(0), - mode(0), - description(""), + /* const */ uint8_t id; + bool mute = false; + int8_t gain_value = 0; + VolumeInputStatus status = VolumeInputStatus::Inactive; + VolumeInputType type = VolumeInputType::Unspecified; + uint8_t change_counter = 0; + uint8_t mode = 0; + std::string description = ""; + /* const */ uint16_t service_handle; + /* const */ uint16_t state_handle; + /* const */ uint16_t state_ccc_handle; + /* const */ uint16_t gain_setting_handle; + /* const */ uint16_t type_handle; + /* const */ uint16_t status_handle; + /* const */ uint16_t status_ccc_handle; + /* const */ uint16_t control_point_handle; + /* const */ uint16_t description_handle; + /* const */ uint16_t description_ccc_handle; + /* const */ bool description_writable; + struct GainSettings gain_settings = GainSettings(); + + explicit VolumeAudioInput(uint8_t id, uint16_t service_handle, uint16_t state_handle, + uint16_t state_ccc_handle, uint16_t gain_setting_handle, + uint16_t type_handle, uint16_t status_handle, + uint16_t status_ccc_handle, uint16_t control_point_handle, + uint16_t description_handle, uint16_t description_ccc_handle, + bool description_writable) + : id(id), service_handle(service_handle), - state_handle(0), - state_ccc_handle(0), - gain_setting_handle(0), - type_handle(0), - status_handle(0), - status_ccc_handle(0), - control_point_handle(0), - description_handle(0), - description_ccc_handle(0), - description_writable(false), - gain_settings(GainSettings()) {} + state_handle(state_handle), + state_ccc_handle(state_ccc_handle), + gain_setting_handle(gain_setting_handle), + type_handle(type_handle), + status_handle(status_handle), + status_ccc_handle(status_ccc_handle), + control_point_handle(control_point_handle), + description_handle(description_handle), + description_ccc_handle(description_ccc_handle), + description_writable(description_writable) {} }; class VolumeAudioInputs { public: - void Add(VolumeAudioInput input) { - input.id = (uint8_t)Size() + 1; - volume_audio_inputs.push_back(input); - } + void Add(VolumeAudioInput input) { volume_audio_inputs.push_back(input); } VolumeAudioInput* FindByType(VolumeInputType type) { auto iter = std::find_if(volume_audio_inputs.begin(), volume_audio_inputs.end(), diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index 39954dd1e5e..f75cdbf3cf1 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -154,7 +154,7 @@ private: builder.AddCharacteristic(0x0031, 0x0032, kVolumeAudioInputStateUuid, GATT_CHAR_PROP_BIT_READ); builder.AddDescriptor(0x0033, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); - builder.AddCharacteristic(0x0034, 0x0035, kVolumeAudioInputGainSettingUuid, + builder.AddCharacteristic(0x0034, 0x0035, kVolumeAudioInputGainSettingPropertiesUuid, GATT_CHAR_PROP_BIT_READ); builder.AddCharacteristic(0x0036, 0x0037, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ); @@ -173,7 +173,7 @@ private: GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY); builder.AddDescriptor(0x0053, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)); if (!aics_broken) { - builder.AddCharacteristic(0x0054, 0x0055, kVolumeAudioInputGainSettingUuid, + builder.AddCharacteristic(0x0054, 0x0055, kVolumeAudioInputGainSettingPropertiesUuid, GATT_CHAR_PROP_BIT_READ); } builder.AddCharacteristic(0x0056, 0x0057, kVolumeAudioInputTypeUuid, @@ -1335,12 +1335,12 @@ TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed) { std::vector value({0x03, 0x01, 0x02, 0x04}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x03, 0x02, true)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, true)); GetNotificationEvent(0x0032, value); } TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed_malformed) { - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, _, _, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, _, _, _)).Times(0); std::vector too_short({0x03, 0x01, 0x02}); GetNotificationEvent(0x0032, too_short); std::vector too_long({0x03, 0x01, 0x02, 0x04, 0x05}); @@ -1349,12 +1349,12 @@ TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed) { std::vector value({0x03, 0x01, 0x02}); - EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x03, 0x01, 0x02)); + EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, _, 0x03, 0x01, 0x02)); GetNotificationEvent(0x0055, value); } TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed_malformed) { - EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 2, _, _, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, _, _, _, _)).Times(0); std::vector too_short({0x03, 0x01}); GetNotificationEvent(0x0055, too_short); std::vector too_long({0x03, 0x01, 0x02, 0x03}); @@ -1363,13 +1363,13 @@ TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed) { std::vector value({static_cast(bluetooth::vc::VolumeInputStatus::Inactive)}); - EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, 1, + EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, _, bluetooth::vc::VolumeInputStatus::Inactive)); GetNotificationEvent(0x0039, value); } TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed_malformed) { - EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, 1, _)).Times(0); + EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, _, _)).Times(0); std::vector too_short(0); GetNotificationEvent(0x0039, too_short); std::vector too_long({0x03, 0x01}); @@ -1379,7 +1379,7 @@ TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed_malformed) { TEST_F(VolumeControlCallbackTest, test_audio_input_description_changed) { std::string descr = "SPDIF"; std::vector value(descr.begin(), descr.end()); - EXPECT_CALL(callbacks, OnExtAudioInDescriptionChanged(test_address, 2, descr)); + EXPECT_CALL(callbacks, OnExtAudioInDescriptionChanged(test_address, _, descr)); GetNotificationEvent(0x005e, value); } @@ -1480,19 +1480,19 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_state) { } TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_status) { - VolumeControl::Get()->GetExtAudioInStatus(test_address, 2); + VolumeControl::Get()->GetExtAudioInStatus(test_address, 0); EXPECT_TRUE(cb); std::vector value({static_cast(bluetooth::vc::VolumeInputStatus::Active)}); EXPECT_CALL(callbacks, - OnExtAudioInStatusChanged(test_address, 2, bluetooth::vc::VolumeInputStatus::Active)); + OnExtAudioInStatusChanged(test_address, 0, bluetooth::vc::VolumeInputStatus::Active)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_gain_props) { - VolumeControl::Get()->GetExtAudioInGainProps(test_address, 2); + VolumeControl::Get()->GetExtAudioInGainProps(test_address, 0); EXPECT_TRUE(cb); std::vector value({0x01, 0x02, 0x03}); - EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x01, 0x02, 0x03)); + EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 0, 0x01, 0x02, 0x03)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1836,38 +1836,38 @@ TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_description) { std::vector expected_data(descr.begin(), descr.end()); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005e, expected_data, GATT_WRITE_NO_RSP, _, _)); - VolumeControl::Get()->SetExtAudioInDescription(test_address, 2, descr); + VolumeControl::Get()->SetExtAudioInDescription(test_address, 1, descr); } TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_description_non_writable) { std::string descr = "AUX"; std::vector expected_data(descr.begin(), descr.end()); EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0); - VolumeControl::Get()->SetExtAudioInDescription(test_address, 1, descr); + VolumeControl::Get()->SetExtAudioInDescription(test_address, 0, descr); } TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_value) { std::vector expected_data({0x01, 0x00, 0x34}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, expected_data, GATT_WRITE, _, _)); - VolumeControl::Get()->SetExtAudioInGainValue(test_address, 2, 0x34); + VolumeControl::Get()->SetExtAudioInGainValue(test_address, 1, 0x34); } TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_mode) { std::vector mode_manual({0x04, 0x00}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, mode_manual, GATT_WRITE, _, _)); - VolumeControl::Get()->SetExtAudioInGainMode(test_address, 2, false); + VolumeControl::Get()->SetExtAudioInGainMode(test_address, 1, false); std::vector mode_automatic({0x05, 0x00}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, mode_automatic, GATT_WRITE, _, _)); - VolumeControl::Get()->SetExtAudioInGainMode(test_address, 2, true); + VolumeControl::Get()->SetExtAudioInGainMode(test_address, 1, true); } TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_mute) { std::vector mute({0x03, 0x00}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, mute, GATT_WRITE, _, _)); - VolumeControl::Get()->SetExtAudioInGainMute(test_address, 2, true); + VolumeControl::Get()->SetExtAudioInGainMute(test_address, 1, true); std::vector unmute({0x02, 0x00}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, unmute, GATT_WRITE, _, _)); - VolumeControl::Get()->SetExtAudioInGainMute(test_address, 2, false); + VolumeControl::Get()->SetExtAudioInGainMute(test_address, 1, false); } class VolumeControlCsis : public VolumeControlTest { -- GitLab From 06c98fdca71a729362b764364d4afcf8e37376ac Mon Sep 17 00:00:00 2001 From: Sal Savage Date: Wed, 30 Oct 2024 10:27:13 -0700 Subject: [PATCH 499/875] Remove flag "randomize_device_level_media_ids" This flag is enabled by default now and can be removed Bug: 332367017 Bug: 376478894 Test: m com.android.btservices Change-Id: I5b56223013cde6f6482c8a09a8f2a90854f9376f --- .../bluetooth/avrcpcontroller/BrowseTree.java | 15 +-------------- .../AvrcpControllerServiceTest.java | 6 ------ .../AvrcpControllerStateMachineTest.java | 17 +---------------- .../avrcpcontroller/BrowseNodeTest.java | 15 +-------------- .../avrcpcontroller/BrowseTreeTest.java | 19 +------------------ flags/avrcp_controller.aconfig | 10 ---------- 6 files changed, 4 insertions(+), 78 deletions(-) diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java b/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java index a8c31ea165c..298162ac8c0 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java @@ -77,15 +77,6 @@ public class BrowseTree { .setBrowsable(true) .build()); mRootNode.setCached(true); - } else if (!Flags.randomizeDeviceLevelMediaIds()) { - mRootNode = - new BrowseNode( - new AvrcpItem.Builder() - .setDevice(device) - .setUuid(ROOT + device.getAddress().toString()) - .setTitle(Utils.getName(device)) - .setBrowsable(true) - .build()); } else { mRootNode = new BrowseNode( @@ -184,11 +175,7 @@ public class BrowseTree { BrowseNode(BluetoothDevice device) { AvrcpItem.Builder aid = new AvrcpItem.Builder(); aid.setDevice(device); - if (Flags.randomizeDeviceLevelMediaIds()) { - aid.setUuid(ROOT + device.getAddress().toString() + UUID.randomUUID().toString()); - } else { - aid.setUuid(PLAYER_PREFIX + device.getAddress().toString()); - } + aid.setUuid(ROOT + device.getAddress().toString() + UUID.randomUUID().toString()); aid.setDisplayableName(Utils.getName(device)); aid.setTitle(Utils.getName(device)); aid.setBrowsable(true); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java index deabdbe1087..4aeb4480ac3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java @@ -31,8 +31,6 @@ import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.media.AudioManager; -import android.platform.test.annotations.EnableFlags; -import android.platform.test.flag.junit.SetFlagsRule; import android.support.v4.media.session.PlaybackStateCompat; import androidx.test.InstrumentationRegistry; @@ -44,7 +42,6 @@ import com.android.bluetooth.TestUtils; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService.BrowseResult; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.flags.Flags; import org.junit.After; import org.junit.Before; @@ -69,8 +66,6 @@ public class AvrcpControllerServiceTest { private AvrcpControllerService mService = null; private BluetoothAdapter mAdapter = null; - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - @Rule public final ServiceTestRule mBluetoothBrowserMediaServiceTestRule = new ServiceTestRule(); @@ -516,7 +511,6 @@ public class AvrcpControllerServiceTest { * first device by checking that it has remained as the active device. */ @Test - @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) public void testActiveDeviceMaintainsAudioFocusWhenOtherDeviceConnects_audioFocusMaintained() { mService.onConnectionStateChanged(true, true, mRemoteDevice); // check set active device is called diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java index 70fac79ca16..dbe35e1660c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java @@ -31,7 +31,6 @@ import android.content.res.Resources; import android.media.AudioManager; import android.os.Bundle; import android.os.Looper; -import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.support.v4.media.MediaMetadataCompat; @@ -467,21 +466,7 @@ public class AvrcpControllerStateMachineTest { /** Get the root of the device */ @Test - @DisableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) - public void testGetDeviceRootNode_flagRandomDeviceIdDisabled_rootNodeMatchesUuidFormat() { - // create new state machine to follow current flags rule - mAvrcpStateMachine = makeStateMachine(mTestDevice); - setUpConnectedState(true, true); - final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); - // Get the root of the device - BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); - Assert.assertEquals(rootName, results.getID()); - } - - /** Get the root of the device */ - @Test - @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) - public void testGetDeviceRootNode_flagRandomDeviceIdEnabled_rootNodeMatchesUuidFormat() { + public void testGetDeviceRootNode_rootNodeMatchesUuidFormat() { // create new state machine to follow current flags rule mAvrcpStateMachine = makeStateMachine(mTestDevice); setUpConnectedState(true, true); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java index f91b44e2c6e..6241e65d0a5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import android.annotation.SuppressLint; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; @@ -80,19 +79,7 @@ public class BrowseNodeTest { } @Test - @DisableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) - public void constructor_withBluetoothDevice() { - BrowseNode browseNode = mBrowseTree.new BrowseNode(mTestDevice); - - assertThat(browseNode.getID()).isNotNull(); - assertThat(browseNode.getDevice()).isEqualTo(mTestDevice); - assertThat(browseNode.isPlayer()).isFalse(); - assertThat(browseNode.isBrowsable()).isTrue(); - } - - @Test - @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) - public void constructor_withBluetoothDevice_withRandomUuid() { + public void constructor_withBluetoothDevice_createsRandomUuid() { BrowseNode browseNode1 = mBrowseTree.new BrowseNode(mTestDevice); assertThat(browseNode1.getID()).isNotNull(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java index d27dcbd661b..275b39452df 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java @@ -20,15 +20,10 @@ import static com.google.common.truth.Truth.assertThat; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.platform.test.annotations.DisableFlags; -import android.platform.test.annotations.EnableFlags; -import android.platform.test.flag.junit.SetFlagsRule; import com.android.bluetooth.avrcpcontroller.BrowseTree.BrowseNode; -import com.android.bluetooth.flags.Flags; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import java.util.Set; @@ -38,8 +33,6 @@ public class BrowseTreeTest { private static final String TEST_HANDLE = "test_handle"; private static final String TEST_NODE_ID = "test_node_id"; - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - private final byte[] mTestAddress = new byte[] {01, 01, 01, 01, 01, 01}; private BluetoothAdapter mAdapter; private BluetoothDevice mTestDevice = null; @@ -102,7 +95,6 @@ public class BrowseTreeTest { } @Test - @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) public void sameDeviceDifferentBrowseTrees_uniqueMediaIds() { BrowseTree browseTree1 = new BrowseTree(mTestDevice); BrowseTree browseTree2 = new BrowseTree(mTestDevice); @@ -119,14 +111,6 @@ public class BrowseTreeTest { assertThat(browseTree.findBrowseNodeByID(BrowseTree.ROOT)).isEqualTo(browseTree.mRootNode); } - @Test - @DisableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) - public void findBrowseNodeByIDForDevice() { - BrowseTree browseTree = new BrowseTree(mTestDevice); - final String deviceId = BrowseTree.ROOT + mTestDevice.getAddress().toString(); - assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); - } - @Test public void findBrowseNodeByIDForIllegalId() { BrowseTree browseTree = new BrowseTree(mTestDevice); @@ -143,8 +127,7 @@ public class BrowseTreeTest { } @Test - @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS) - public void findBrowseNodeByIDForDevice_withRandomDeviceID_nodeIsFound() { + public void findBrowseNodeByIDForDevice_nodeIsFound() { BrowseTree browseTree = new BrowseTree(mTestDevice); final String deviceId = browseTree.mRootNode.getID(); assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); diff --git a/flags/avrcp_controller.aconfig b/flags/avrcp_controller.aconfig index de205eba5cb..4374eef8fab 100644 --- a/flags/avrcp_controller.aconfig +++ b/flags/avrcp_controller.aconfig @@ -1,16 +1,6 @@ package: "com.android.bluetooth.flags" container: "com.android.btservices" -flag { - name: "randomize_device_level_media_ids" - namespace: "bluetooth" - description: "Randomize the media id of device level nodes in our browse tree by attaching a randomized string after the UUID, each time a device connects" - bug: "332367017" - metadata { - purpose: PURPOSE_BUGFIX - } -} - flag { name: "uncache_player_when_browsed_player_changes" namespace: "bluetooth" -- GitLab From 03544e4c69159809fce25e562e9b72e11f1ae76b Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 11 Oct 2024 17:35:21 -0700 Subject: [PATCH 500/875] AICS: Simplify VolumeControlInputDescriptor usage Since we are storing the instance with index [0-NumOfInput], we don't need to store it in a map. Using an array re-write unit test to test smaller behavior re-write accessor method to unify logging make use of new defined constant for data check Bug: 372328699 Flag: com.android.bluetooth.flags.aics_api Test: m Bluetooth Change-Id: Id5ddfa65c72ae409be5968b2a60ef629da4ca288 --- .../vc/VolumeControlInputDescriptor.java | 199 +++++---------- .../bluetooth/vc/VolumeControlService.java | 148 +++++------ .../vc/VolumeControlInputDescriptorTest.java | 238 +++++++++--------- 3 files changed, 238 insertions(+), 347 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java index e5324ae1c55..3d961666ce8 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java @@ -16,56 +16,47 @@ package com.android.bluetooth.vc; -import android.bluetooth.BluetoothVolumeControl; import android.util.Log; import com.android.bluetooth.btservice.ProfileService; -import java.util.HashMap; -import java.util.Map; - class VolumeControlInputDescriptor { - private static final String TAG = "VolumeControlInputDescriptor"; - final Map mVolumeInputs = new HashMap<>(); - - public static final int AUDIO_INPUT_TYPE_UNSPECIFIED = 0x00; - public static final int AUDIO_INPUT_TYPE_BLUETOOTH = 0x01; - public static final int AUDIO_INPUT_TYPE_MICROPHONE = 0x02; - public static final int AUDIO_INPUT_TYPE_ANALOG = 0x03; - public static final int AUDIO_INPUT_TYPE_DIGITAL = 0x04; - public static final int AUDIO_INPUT_TYPE_RADIO = 0x05; - public static final int AUDIO_INPUT_TYPE_STREAMING = 0x06; - public static final int AUDIO_INPUT_TYPE_AMBIENT = 0x07; + private static final String TAG = VolumeControlInputDescriptor.class.getSimpleName(); + + final Descriptor[] mVolumeInputs; + + VolumeControlInputDescriptor(int numberOfExternalInputs) { + mVolumeInputs = new Descriptor[numberOfExternalInputs]; + // Stack delivers us number of audio inputs. ids are countinous from [0;n[ + for (int i = 0; i < numberOfExternalInputs; i++) { + mVolumeInputs[i] = new Descriptor(); + } + } private static class Descriptor { - /* True when input is active, false otherwise */ - boolean mIsActive = false; + int mStatus = 0; // AudioInputStatus.INACTIVE; - /* Defined as in Assigned Numbers in the BluetoothVolumeControl.AUDIO_INPUT_TYPE_ */ - int mType = AUDIO_INPUT_TYPE_UNSPECIFIED; + int mType = 0; // AudioInputType.UNSPECIFIED; int mGainValue = 0; - /* As per AICS 1.0 - * 3.1.3. Gain_Mode field - * The Gain_Mode field shall be set to a value that reflects whether gain modes are - * manual or automatic. - * - * If the Gain_Mode field value is Manual Only, the server allows only manual gain. - * If the Gain_Mode field is Automatic Only, the server allows only automatic gain. + /* See AICS 1.0 - 3.1.3. Gain_Mode field + * The Gain_Mode field shall be set to a value that reflects whether gain modes are manual + * or automatic. + * - Manual Only, the server allows only manual gain. + * - Automatic Only, the server allows only automatic gain. * - * For all other Gain_Mode field values, the server allows switchable - * automatic/manual gain. + * For all other Gain_Mode field values, the server allows switchable automatic/manual gain. */ int mGainMode = 0; boolean mIsMute = false; - /* As per AICS 1.0 - * The Gain_Setting (mGainValue) field is a signed value for which a single increment - * or decrement should result in a corresponding increase or decrease of the input - * amplitude by the value of the Gain_Setting_Units (mGainSettingsUnits) - * field of the Gain Setting Properties characteristic value. + /* See AICS 1.0 + * The Gain_Setting (mGainValue) field is a signed value for which a single increment or + * decrement should result in a corresponding increase or decrease of the input amplitude by + * the value of the Gain_Setting_Units (mGainSettingsUnits) field of the Gain Setting + * Properties characteristic value. */ int mGainSettingsUnits = 0; @@ -76,147 +67,87 @@ class VolumeControlInputDescriptor { } int size() { - return mVolumeInputs.size(); + return mVolumeInputs.length; } - void add(int id) { - if (!mVolumeInputs.containsKey(id)) { - mVolumeInputs.put(id, new Descriptor()); - } - } - - boolean setActive(int id, boolean active) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "setActive, Id " + id + " is unknown"); + private boolean isValidId(int id) { + if (id >= size() || id < 0) { + Log.e(TAG, "Request fail. Illegal id argument: " + id); return false; } - desc.mIsActive = active; return true; } - boolean isActive(int id) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "isActive, Id " + id + " is unknown"); - return false; - } - return desc.mIsActive; + void setStatus(int id, int status) { + if (!isValidId(id)) return; + mVolumeInputs[id].mStatus = status; } - boolean setDescription(int id, String description) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "setDescription, Id " + id + " is unknown"); - return false; - } - desc.mDescription = description; - return true; + int getStatus(int id) { + if (!isValidId(id)) return 0; // AudioInputStatus.INACTIVE; + return mVolumeInputs[id].mStatus; } - String getDescription(int id) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "getDescription, Id " + id + " is unknown"); - return null; - } - return desc.mDescription; + void setDescription(int id, String description) { + if (!isValidId(id)) return; + mVolumeInputs[id].mDescription = description; } - boolean setType(int id, int type) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "setType, Id " + id + " is unknown"); - return false; - } - - if (type > AUDIO_INPUT_TYPE_AMBIENT) { - Log.e(TAG, "setType, Type " + type + "for id " + id + " is invalid"); - return false; - } + String getDescription(int id) { + if (!isValidId(id)) return null; + return mVolumeInputs[id].mDescription; + } - desc.mType = type; - return true; + void setType(int id, int type) { + if (!isValidId(id)) return; + mVolumeInputs[id].mType = type; } int getType(int id) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "getType, Id " + id + " is unknown"); - return AUDIO_INPUT_TYPE_UNSPECIFIED; - } - return desc.mType; + if (!isValidId(id)) return 0; // AudioInputType.UNSPECIFIED; + return mVolumeInputs[id].mType; } int getGain(int id) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "getGain, Id " + id + " is unknown"); - return 0; - } - return desc.mGainValue; + if (!isValidId(id)) return 0; + return mVolumeInputs[id].mGainValue; } boolean isMuted(int id) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "isMuted, Id " + id + " is unknown"); - return false; - } - return desc.mIsMute; + if (!isValidId(id)) return false; + return mVolumeInputs[id].mIsMute; } - boolean setPropSettings(int id, int gainUnit, int gainMin, int gainMax) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "setPropSettings, Id " + id + " is unknown"); - return false; - } + void setPropSettings(int id, int gainUnit, int gainMin, int gainMax) { + if (!isValidId(id)) return; - desc.mGainSettingsUnits = gainUnit; - desc.mGainSettingsMinSetting = gainMin; - desc.mGainSettingsMaxSetting = gainMax; - - return true; + mVolumeInputs[id].mGainSettingsUnits = gainUnit; + mVolumeInputs[id].mGainSettingsMinSetting = gainMin; + mVolumeInputs[id].mGainSettingsMaxSetting = gainMax; } - boolean setState(int id, int gainValue, int gainMode, boolean mute) { - Descriptor desc = mVolumeInputs.get(id); - if (desc == null) { - Log.e(TAG, "Id " + id + " is unknown"); - return false; - } + void setState(int id, int gainValue, int gainMode, boolean mute) { + if (!isValidId(id)) return; + + Descriptor desc = mVolumeInputs[id]; if (gainValue > desc.mGainSettingsMaxSetting || gainValue < desc.mGainSettingsMinSetting) { - Log.e(TAG, "Invalid gainValue " + gainValue); - return false; + Log.e(TAG, "Request fail. Illegal gainValue argument: " + gainValue); + return; } desc.mGainValue = gainValue; desc.mGainMode = gainMode; desc.mIsMute = mute; - - return true; - } - - void remove(int id) { - Log.d(TAG, "remove, id: " + id); - mVolumeInputs.remove(id); - } - - void clear() { - Log.d(TAG, "clear all inputs"); - mVolumeInputs.clear(); } void dump(StringBuilder sb) { - for (Map.Entry entry : mVolumeInputs.entrySet()) { - Descriptor desc = entry.getValue(); - Integer id = entry.getKey(); - ProfileService.println(sb, " id: " + id); + for (int i = 0; i < mVolumeInputs.length; i++) { + Descriptor desc = mVolumeInputs[i]; + ProfileService.println(sb, " id: " + i); ProfileService.println(sb, " description: " + desc.mDescription); ProfileService.println(sb, " type: " + desc.mType); - ProfileService.println(sb, " isActive: " + desc.mIsActive); + ProfileService.println(sb, " status: " + desc.mStatus); ProfileService.println(sb, " gainValue: " + desc.mGainValue); ProfileService.println(sb, " gainMode: " + desc.mGainMode); ProfileService.println(sb, " mute: " + desc.mIsMute); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 0efd36f6bef..11bd5c84987 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -935,22 +935,11 @@ public class VolumeControlService extends ProfileService { void handleExternalInputs(BluetoothDevice device, int numberOfExternalInputs) { if (numberOfExternalInputs == 0) { Log.i(TAG, "Volume offset not available"); + mAudioInputs.remove(device); return; } - VolumeControlInputDescriptor inputs = mAudioInputs.get(device); - if (inputs == null) { - inputs = new VolumeControlInputDescriptor(); - mAudioInputs.put(device, inputs); - } else if (inputs.size() != numberOfExternalInputs) { - Log.i(TAG, "Number of inputs changed: "); - inputs.clear(); - } - - // Stack delivers us number of audio inputs. ids are countinous from [0;n[ - for (int i = 0; i < numberOfExternalInputs; i++) { - inputs.add(i); - } + mAudioInputs.put(device, new VolumeControlInputDescriptor(numberOfExternalInputs)); } void handleDeviceAvailable( @@ -1034,133 +1023,112 @@ public class VolumeControlService extends ProfileService { void handleDeviceExtInputStateChanged( BluetoothDevice device, int id, int gainValue, int gainMode, boolean mute) { - Log.d( - TAG, - ("handleDeviceExtInputStateChanged, device: " + device) - + (" inputId: " + id) + String logInfo = + "handleDeviceExtInputStateChanged(" + + ("device:" + device) + + (", id" + id) + (" gainValue: " + gainValue) + (" gainMode: " + gainMode) - + (" mute: " + mute)); + + (" mute: " + mute) + + ")"; VolumeControlInputDescriptor input = mAudioInputs.get(device); if (input == null) { - Log.e( - TAG, - ("handleDeviceExtInputStateChanged, inputId: " + id) - + (" not found for device: " + device)); + Log.e(TAG, logInfo + " This device has no audio input control"); return; } - if (!input.setState(id, gainValue, gainMode, mute)) { - Log.e( - TAG, - ("handleDeviceExtInputStateChanged, error while setting inputId: " + id) - + ("for: " + device)); - } + + Log.d(TAG, logInfo); + input.setState(id, gainValue, gainMode, mute); } void handleDeviceExtInputStatusChanged(BluetoothDevice device, int id, int status) { - Log.d(TAG, " device: " + device + " inputId: " + id + " status: " + status); + String logInfo = + "handleDeviceExtInputStatusChanged(" + + ("device:" + device) + + (", id" + id) + + (", status" + status) + + ")"; VolumeControlInputDescriptor input = mAudioInputs.get(device); if (input == null) { - Log.e(TAG, " inputId: " + id + " not found for device: " + device); + Log.e(TAG, logInfo + " This device has no audio input control"); return; } - /* - * As per ACIS 1.0. Status - * Inactive: 0x00 - * Active: 0x01 - */ - if (status > 1 || status < 0) { - Log.e( - TAG, - ("handleDeviceExtInputStatusChanged, invalid status: " + status) - + (" for: " + device)); + if (status != 0 && status != 1) { + Log.e(TAG, logInfo + ": Invalid status argument"); return; } - boolean active = (status == 0x01); - if (!input.setActive(id, active)) { - Log.e( - TAG, - ("handleDeviceExtInputStatusChanged, error while setting inputId: " + id) - + ("for: " + device)); - } + Log.d(TAG, logInfo); + input.setStatus(id, status); } void handleDeviceExtInputTypeChanged(BluetoothDevice device, int id, int type) { - Log.d( - TAG, - ("handleDeviceExtInputTypeChanged, device: " + device) - + (" inputId: " + id) - + (" type: " + type)); + String logInfo = + "handleDeviceExtInputTypeChanged(" + + ("device:" + device) + + (", id" + id) + + (", type" + type) + + ")"; VolumeControlInputDescriptor input = mAudioInputs.get(device); if (input == null) { - Log.e( - TAG, - ("handleDeviceExtInputTypeChanged, inputId: " + id) - + (" not found for device: " + device)); + Log.e(TAG, logInfo + ": This device has no audio input control"); return; } - if (!input.setType(id, type)) { - Log.e( - TAG, - ("handleDeviceExtInputTypeChanged, error while setting inputId: " + id) - + ("for: " + device)); + if (type > 7) { // AudioInputType.AMBIENT) { + Log.e(TAG, logInfo + ": Invalid type argument"); + return; } + + Log.d(TAG, logInfo); + input.setType(id, type); } void handleDeviceExtInputDescriptionChanged( BluetoothDevice device, int id, String description) { - Log.d( - TAG, - ("handleDeviceExtInputDescriptionChanged, device: " + device) - + (" inputId: " + id) - + (" description: " + description)); + String logInfo = + "handleDeviceExtInputDescriptionChanged(" + + ("device:" + device) + + (", id" + id) + + (", description" + description) + + ")"; VolumeControlInputDescriptor input = mAudioInputs.get(device); if (input == null) { - Log.e( - TAG, - ("handleDeviceExtInputDescriptionChanged, inputId: " + id) - + (" not found for device: " + device)); + Log.e(TAG, logInfo + ": This device has no audio input control"); return; } - if (!input.setDescription(id, description)) { - Log.e( - TAG, - ("handleDeviceExtInputDescriptionChanged, error while setting inputId: " + id) - + ("for: " + device)); + if (description == null) { + Log.e(TAG, logInfo + ": Invalid description argument"); + return; } + + Log.d(TAG, logInfo); + input.setDescription(id, description); } void handleDeviceExtInputGainPropsChanged( BluetoothDevice device, int id, int unit, int min, int max) { - Log.d( - TAG, - ("handleDeviceExtInputGainPropsChanged, device: " + device) - + (" inputId: " + id) - + (" unit: " + unit + " min" + min + " max:" + max)); + String logInfo = + "handleDeviceExtInputGainPropsChanged(" + + ("device:" + device) + + (", id" + id) + + (" unit: " + unit + " min" + min + " max:" + max) + + ")"; VolumeControlInputDescriptor input = mAudioInputs.get(device); if (input == null) { - Log.e( - TAG, - ("handleDeviceExtInputGainPropsChanged, inputId: " + id) - + (" not found for device: " + device)); + Log.e(TAG, logInfo + ": This device has no audio input control"); return; } - if (!input.setPropSettings(id, unit, min, max)) { - Log.e( - TAG, - ("handleDeviceExtInputGainPropsChanged, error while setting inputId: " + id) - + ("for: " + device)); - } + Log.d(TAG, logInfo); + input.setPropSettings(id, unit, min, max); } void messageFromNative(VolumeControlStackEvent stackEvent) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java index 61db244b6d4..68f1c437b7f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java @@ -19,167 +19,159 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.*; -import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; -import androidx.test.filters.MediumTest; +import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.bluetooth.flags.Flags; - -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -@MediumTest +@SmallTest @RunWith(AndroidJUnit4.class) public class VolumeControlInputDescriptorTest { + private static final int NUMBER_OF_INPUT = 3; + private static final int NUMBER_OF_FIELD_IN_STRUCT = 9; + private static final int VALID_ID = 1; + private static final int INVALID_ID = NUMBER_OF_INPUT; + private static final int INVALID_ID2 = -1; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private VolumeControlInputDescriptor mDescriptor; + @Before - public void setUp() throws Exception { - // placeholder + public void setUp() { + mDescriptor = new VolumeControlInputDescriptor(NUMBER_OF_INPUT); } - @After - public void tearDown() throws Exception { - // placeholder + @Test + public void dump_noCrash() { + StringBuilder sb = new StringBuilder(); + + mDescriptor.dump(sb); + int nLines = NUMBER_OF_INPUT * (NUMBER_OF_FIELD_IN_STRUCT + 1); // +1 for the id + assertThat(sb.toString()).containsMatch("( .*\n){" + nLines + "}"); } @Test - @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT) - public void testVolumeControlInputDescriptorInvalidIdOperations() throws Exception { - VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor(); - - int invalidId = 1; - int testGainValue = 100; - int testGainMode = 1; - boolean testGainMute = true; - String testDesc = "testDescription"; - int testType = VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_AMBIENT; - int testGainSettingsMax = 100; - int testGainSettingsMin = 0; - int testGainSettingsUnit = 1; - - // Test adding all props using invalid ID - assertThat(descriptor.isActive(invalidId)).isFalse(); - assertThat(descriptor.setActive(invalidId, true)).isFalse(); - assertThat(descriptor.setDescription(invalidId, testDesc)).isFalse(); - assertThat(descriptor.getDescription(invalidId)).isNull(); - assertThat(descriptor.setType(invalidId, testType)).isFalse(); - assertThat(descriptor.getType(invalidId)) - .isEqualTo(VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_UNSPECIFIED); - - assertThat(descriptor.getGain(invalidId)).isEqualTo(0); - assertThat(descriptor.isMuted(invalidId)).isFalse(); - assertThat( - descriptor.setPropSettings( - invalidId, - testGainSettingsUnit, - testGainSettingsMin, - testGainSettingsMax)) - .isFalse(); - assertThat(descriptor.setState(invalidId, testGainValue, testGainMode, testGainMute)) - .isFalse(); + public void setFoo_withAllValidId_valuesAreUpdated() { + for (int i = 0; i < NUMBER_OF_INPUT; i++) { + assertThat(mDescriptor.getStatus(i)).isEqualTo(0); // AudioInputStatus.INACTIVE); + mDescriptor.setStatus(i, 1); // AudioInputStatus.ACTIVE); + assertThat(mDescriptor.getStatus(i)).isEqualTo(1); // AudioInputStatus.ACTIVE); + } } @Test - @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT) - public void testVolumeControlInputDescriptorMultipleInstanceAdded() throws Exception { + public void getStatus_whenNeverSet_defaultToInactive() { + assertThat(mDescriptor.getStatus(VALID_ID)).isEqualTo(0); // AudioInputStatus.INACTIVE); + } - VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor(); + @Test + public void setStatus_withValidId_valueIsUpdated() { + int newStatus = 1; // AudioInputStatus.ACTIVE; + mDescriptor.setStatus(VALID_ID, newStatus); - int validId = 10; + assertThat(mDescriptor.getStatus(VALID_ID)).isEqualTo(newStatus); + } - // Verify that adding descriptor works increase descriptor size - assertThat(descriptor.size()).isEqualTo(0); - descriptor.add(validId); - assertThat(descriptor.size()).isEqualTo(1); + @Test + public void setStatus_withInvalidId_valueIsNotUpdated() { + int newStatus = 1; // AudioInputStatus.ACTIVE; + mDescriptor.setStatus(INVALID_ID, newStatus); - // Check if adding same id will not increase descriptor count. - descriptor.add(validId); - assertThat(descriptor.size()).isEqualTo(1); + assertThat(mDescriptor.getStatus(INVALID_ID)).isNotEqualTo(newStatus); } @Test - @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT) - public void testVolumeControlInputDescriptorInstanceRemoveAndClear() throws Exception { + public void getType_whenNeverSet_defaultToUnspecified() { + assertThat(mDescriptor.getType(VALID_ID)).isEqualTo(0); // AudioInputType.UNSPECIFIED); + } - VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor(); + @Test + public void setType_withValidId_valueIsUpdated() { + int newType = 7; // AudioInputType.AMBIENT; + mDescriptor.setType(VALID_ID, newType); - int id_1 = 10; - int id_2 = 20; - int invalidId = 1; + assertThat(mDescriptor.getType(VALID_ID)).isEqualTo(newType); + } - // Verify that adding descriptor works increase descriptor size - assertThat(descriptor.size()).isEqualTo(0); - descriptor.add(id_1); - assertThat(descriptor.size()).isEqualTo(1); - descriptor.add(id_2); + @Test + public void setType_withInvalidId_valueIsNotUpdated() { + int newType = 1; // AudioInputType.BLUETOOTH; + mDescriptor.setType(INVALID_ID2, newType); - // Remove valid id - descriptor.remove(id_1); - assertThat(descriptor.size()).isEqualTo(1); + assertThat(mDescriptor.getType(INVALID_ID2)).isNotEqualTo(newType); + } - // Remove invalid id not change number of descriptors - descriptor.remove(invalidId); - assertThat(descriptor.size()).isEqualTo(1); + @Test + public void setState_withValidIdButIncorrectSettings_valueIsNotUpdated() { + int newGainValue = 42; + int newGainMode = 42; + boolean isMute = true; + mDescriptor.setState(VALID_ID, newGainMode, newGainMode, isMute); + + assertThat(mDescriptor.getGain(VALID_ID)).isNotEqualTo(newGainValue); + // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); + assertThat(mDescriptor.isMuted(VALID_ID)).isFalse(); + } - // Check clear API - descriptor.clear(); - assertThat(descriptor.size()).isEqualTo(0); + @Test + public void setState_withValidIdAndCorrectSettings_valueIsUpdated() { + int newMax = 100; + int newMin = 0; + int newUnit = 1; + mDescriptor.setPropSettings(VALID_ID, newUnit, newMin, newMax); + + int newGainValue = 42; + int newGainMode = 42; + boolean isMute = true; + mDescriptor.setState(VALID_ID, newGainMode, newGainMode, isMute); + + assertThat(mDescriptor.getGain(VALID_ID)).isEqualTo(newGainValue); + // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); + assertThat(mDescriptor.isMuted(VALID_ID)).isTrue(); } @Test - @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT) - public void testVolumeControlInputDescriptorAllValidApiCalls() throws Exception { - - VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor(); - - int validId = 10; - int testGainValue = 100; - int testGainMode = 1; - boolean testGainMute = true; - String defaultDesc = ""; - String testDesc = "testDescription"; - int testType = VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_AMBIENT; - int testGainSettingsMax = 100; - int testGainSettingsMin = 0; - int testGainSettingsUnit = 1; - - descriptor.add(validId); - - // Active state - assertThat(descriptor.isActive(validId)).isFalse(); - assertThat(descriptor.setActive(validId, true)).isTrue(); - assertThat(descriptor.isActive(validId)).isTrue(); - - // Descriptor - assertThat(descriptor.getDescription(validId)).isEqualTo(defaultDesc); - assertThat(descriptor.setDescription(validId, testDesc)).isTrue(); - assertThat(descriptor.getDescription(validId)).isEqualTo(testDesc); - - // Type - assertThat(descriptor.getType(validId)) - .isEqualTo(VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_UNSPECIFIED); - assertThat(descriptor.setType(validId, testType)).isTrue(); - assertThat(descriptor.getType(validId)).isEqualTo(testType); - - // Properties - assertThat( - descriptor.setPropSettings( - validId, - testGainSettingsUnit, - testGainSettingsMin, - testGainSettingsMax)) - .isTrue(); - - // State - assertThat(descriptor.setState(validId, testGainValue, testGainMode, testGainMute)) - .isTrue(); - assertThat(descriptor.getGain(validId)).isEqualTo(testGainValue); + public void setState_withInvalidId_valueIsNotUpdated() { + int newMax = 100; + int newMin = 0; + int newUnit = 1; + // Should be no-op but we want to copy the working case test, just with an invalid id + mDescriptor.setPropSettings(INVALID_ID, newUnit, newMin, newMax); + + int newGainValue = 42; + int newGainMode = 42; + boolean isMute = true; + mDescriptor.setState(INVALID_ID, newGainMode, newGainMode, isMute); + + assertThat(mDescriptor.getGain(INVALID_ID)).isNotEqualTo(newGainValue); + // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); + assertThat(mDescriptor.isMuted(INVALID_ID)).isFalse(); + } + + @Test + public void getDescription_whenNeverSet_defaultToEmptyString() { + assertThat(mDescriptor.getDescription(VALID_ID)).isEmpty(); + } + + @Test + public void setDescription_withValidId_valueIsUpdated() { + String newDescription = "what a nice description"; + mDescriptor.setDescription(VALID_ID, newDescription); + + assertThat(mDescriptor.getDescription(VALID_ID)).isEqualTo(newDescription); + } + + @Test + public void setDescription_withInvalidId_valueIsNotUpdated() { + String newDescription = "what a nice description"; + mDescriptor.setDescription(INVALID_ID, newDescription); + + assertThat(mDescriptor.getDescription(INVALID_ID)).isNotEqualTo(newDescription); } } -- GitLab From ffb0d7f0dd80232148c08a168b1325800a686c7b Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 18 Oct 2024 17:50:20 -0700 Subject: [PATCH 501/875] AICS: Check mute value and update to int type Bug: 361263965 Test: atest vc_test Flag: com.android.bluetooth.flags.leaudio_add_aics_support Change-Id: I7b0a28408752dcb16d68c36d9ed9693c2c5579e5 --- android/app/jni/com_android_bluetooth_vc.cpp | 6 +++--- .../vc/VolumeControlInputDescriptor.java | 14 ++++++------- .../vc/VolumeControlNativeInterface.java | 4 ++-- .../bluetooth/vc/VolumeControlService.java | 4 ++-- .../bluetooth/vc/VolumeControlStackEvent.java | 3 ++- .../vc/VolumeControlInputDescriptorTest.java | 18 ++++++++-------- .../vc/VolumeControlNativeInterfaceTest.java | 2 +- system/bta/vc/types.h | 2 +- system/bta/vc/vc.cc | 13 +++++++++--- system/bta/vc/vc_test.cc | 21 +++++++++++++++---- system/btif/src/btif_vc.cc | 2 +- system/gd/rust/topshim/vc/vc_shim.cc | 2 +- system/include/hardware/bt_vc.h | 2 +- 13 files changed, 57 insertions(+), 36 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp index 39bd355dadc..adb9b78c778 100644 --- a/android/app/jni/com_android_bluetooth_vc.cpp +++ b/android/app/jni/com_android_bluetooth_vc.cpp @@ -218,7 +218,7 @@ public: } void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode, bool mute) override { + uint8_t gain_mode, uint8_t mute) override { log::info(""); std::shared_lock lock(callbacks_mutex); @@ -237,7 +237,7 @@ public: sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), reinterpret_cast(&bd_addr)); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInStateChanged, (jint)ext_input_id, - (jint)gain_val, (jint)gain_mode, (jboolean)mute, addr.get()); + (jint)gain_val, (jint)gain_mode, (jint)mute, addr.get()); } void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id, @@ -893,7 +893,7 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { {"onExtAudioOutLocationChanged", "(II[B)V", &method_onExtAudioOutLocationChanged}, {"onExtAudioOutDescriptionChanged", "(ILjava/lang/String;[B)V", &method_onExtAudioOutDescriptionChanged}, - {"onExtAudioInStateChanged", "(IIIZ[B)V", &method_onExtAudioInStateChanged}, + {"onExtAudioInStateChanged", "(IIII[B)V", &method_onExtAudioInStateChanged}, {"onExtAudioInStatusChanged", "(II[B)V", &method_onExtAudioInStatusChanged}, {"onExtAudioInTypeChanged", "(II[B)V", &method_onExtAudioInTypeChanged}, {"onExtAudioInGainPropsChanged", "(IIII[B)V", &method_onExtAudioInGainPropsChanged}, diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java index 3d961666ce8..759655cf9d4 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java @@ -50,7 +50,7 @@ class VolumeControlInputDescriptor { */ int mGainMode = 0; - boolean mIsMute = false; + int mMute = 2; // DISABLED /* See AICS 1.0 * The Gain_Setting (mGainValue) field is a signed value for which a single increment or @@ -113,9 +113,9 @@ class VolumeControlInputDescriptor { return mVolumeInputs[id].mGainValue; } - boolean isMuted(int id) { - if (!isValidId(id)) return false; - return mVolumeInputs[id].mIsMute; + int getMute(int id) { + if (!isValidId(id)) return 2; // MuteField.DISABLED + return mVolumeInputs[id].mMute; } void setPropSettings(int id, int gainUnit, int gainMin, int gainMax) { @@ -126,7 +126,7 @@ class VolumeControlInputDescriptor { mVolumeInputs[id].mGainSettingsMaxSetting = gainMax; } - void setState(int id, int gainValue, int gainMode, boolean mute) { + void setState(int id, int gainValue, int gainMode, int mute) { if (!isValidId(id)) return; Descriptor desc = mVolumeInputs[id]; @@ -138,7 +138,7 @@ class VolumeControlInputDescriptor { desc.mGainValue = gainValue; desc.mGainMode = gainMode; - desc.mIsMute = mute; + desc.mMute = mute; } void dump(StringBuilder sb) { @@ -150,7 +150,7 @@ class VolumeControlInputDescriptor { ProfileService.println(sb, " status: " + desc.mStatus); ProfileService.println(sb, " gainValue: " + desc.mGainValue); ProfileService.println(sb, " gainMode: " + desc.mGainMode); - ProfileService.println(sb, " mute: " + desc.mIsMute); + ProfileService.println(sb, " mute: " + desc.mMute); ProfileService.println(sb, " units:" + desc.mGainSettingsUnits); ProfileService.println(sb, " minGain:" + desc.mGainSettingsMinSetting); ProfileService.println(sb, " maxGain:" + desc.mGainSettingsMaxSetting); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java index 7167293a26d..f7e22828b9c 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java @@ -454,7 +454,7 @@ public class VolumeControlNativeInterface { @VisibleForTesting void onExtAudioInStateChanged( - int externalInputId, int gainValue, int gainMode, boolean mute, byte[] address) { + int externalInputId, int gainValue, int gainMode, int mute, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); @@ -462,7 +462,7 @@ public class VolumeControlNativeInterface { event.valueInt1 = externalInputId; event.valueInt2 = gainValue; event.valueInt3 = gainMode; - event.valueBool1 = mute; + event.valueInt4 = mute; Log.d(TAG, "onExtAudioInStateChanged: " + event); sendMessageToService(event); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 11bd5c84987..4d0c44adf2e 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -1022,7 +1022,7 @@ public class VolumeControlService extends ProfileService { } void handleDeviceExtInputStateChanged( - BluetoothDevice device, int id, int gainValue, int gainMode, boolean mute) { + BluetoothDevice device, int id, int gainValue, int gainMode, int mute) { String logInfo = "handleDeviceExtInputStateChanged(" + ("device:" + device) @@ -1177,7 +1177,7 @@ public class VolumeControlService extends ProfileService { stackEvent.valueInt1, stackEvent.valueInt2, stackEvent.valueInt3, - stackEvent.valueBool1); + stackEvent.valueInt4); return; } diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index d102952d272..5b5fe0d36ae 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -159,6 +159,8 @@ public class VolumeControlStackEvent { switch (type) { case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: return "{gain set max:" + value + "}"; + case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED: + return "{mute:" + value + "}"; default: break; } @@ -168,7 +170,6 @@ public class VolumeControlStackEvent { private static String eventTypeValueBool1ToString(int type, boolean value) { switch (type) { case EVENT_TYPE_VOLUME_STATE_CHANGED: - case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED: return "{muted:" + value + "}"; default: break; diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java index 68f1c437b7f..37f52cc4fb4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java @@ -111,12 +111,12 @@ public class VolumeControlInputDescriptorTest { public void setState_withValidIdButIncorrectSettings_valueIsNotUpdated() { int newGainValue = 42; int newGainMode = 42; - boolean isMute = true; - mDescriptor.setState(VALID_ID, newGainMode, newGainMode, isMute); + int mute = 0; // NOT_MUTED + mDescriptor.setState(VALID_ID, newGainMode, newGainMode, mute); assertThat(mDescriptor.getGain(VALID_ID)).isNotEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); - assertThat(mDescriptor.isMuted(VALID_ID)).isFalse(); + assertThat(mDescriptor.getMute(VALID_ID)).isNotEqualTo(mute); } @Test @@ -128,12 +128,12 @@ public class VolumeControlInputDescriptorTest { int newGainValue = 42; int newGainMode = 42; - boolean isMute = true; - mDescriptor.setState(VALID_ID, newGainMode, newGainMode, isMute); + int mute = 1; // MUTED + mDescriptor.setState(VALID_ID, newGainMode, newGainMode, mute); assertThat(mDescriptor.getGain(VALID_ID)).isEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); - assertThat(mDescriptor.isMuted(VALID_ID)).isTrue(); + assertThat(mDescriptor.getMute(VALID_ID)).isEqualTo(1); // MUTED } @Test @@ -146,12 +146,12 @@ public class VolumeControlInputDescriptorTest { int newGainValue = 42; int newGainMode = 42; - boolean isMute = true; - mDescriptor.setState(INVALID_ID, newGainMode, newGainMode, isMute); + int mute = 1; + mDescriptor.setState(INVALID_ID, newGainMode, newGainMode, mute); assertThat(mDescriptor.getGain(INVALID_ID)).isNotEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); - assertThat(mDescriptor.isMuted(INVALID_ID)).isFalse(); + assertThat(mDescriptor.getMute(INVALID_ID)).isEqualTo(2); // DISABLED } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java index 9b0aa48c62d..de7b405c2f1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java @@ -168,7 +168,7 @@ public class VolumeControlNativeInterfaceTest { int externalInputId = 2; int gainValue = 1; int gainMode = 0; - boolean mute = false; + int mute = 0; byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; mNativeInterface.onExtAudioInStateChanged( diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h index bdb242bb20f..d896137eef3 100644 --- a/system/bta/vc/types.h +++ b/system/bta/vc/types.h @@ -136,7 +136,7 @@ struct GainSettings { struct VolumeAudioInput { /* const */ uint8_t id; - bool mute = false; + uint8_t mute = 0x02; // DISABLED int8_t gain_value = 0; VolumeInputStatus status = VolumeInputStatus::Inactive; VolumeInputType type = VolumeInputType::Unspecified; diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index 2c415a59c0b..cd6f477b297 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -581,7 +581,14 @@ public: uint8_t* pp = value; STREAM_TO_INT8(input->gain_value, pp); - STREAM_TO_UINT8(input->mute, pp); + uint8_t mute; + STREAM_TO_UINT8(mute, pp); + if (mute > 0x02 /*Mute::DISABLED*/) { + bluetooth::log::error("{} Invalid mute value: {:#x}", device->address, mute); + return; + } + input->mute = mute; + STREAM_TO_UINT8(input->mode, pp); STREAM_TO_UINT8(input->change_counter, pp); @@ -589,7 +596,7 @@ public: bluetooth::log::info( "{} id={:#x}gain_value {:#x}, mute: {:#x}, mode: {:#x}, " "change_counter: {}", - device->address, input->id, input->gain_value, input->mute, input->mode, + device->address, input->id, input->gain_value, mute, input->mode, input->change_counter); if (!device->device_ready) { @@ -1503,7 +1510,7 @@ private: if (position + len >= total_len) { bluetooth::log::warn( - "Multi read was too long, value truncated conn_id: {:#x} handle: {:#x}, possition: " + "Multi read was too long, value truncated conn_id: {:#x} handle: {:#x}, position: " "{:#x}, len: {:#x}, total_len: {:#x}, data: {}", conn_id, hdl, position, len, total_len, base::HexEncode(value, total_len)); break; diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index f75cdbf3cf1..6684c1e10b1 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -104,7 +104,7 @@ public: (const RawAddress& address, uint8_t ext_output_id, std::string descr), (override)); MOCK_METHOD((void), OnExtAudioInStateChanged, (const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode_auto, bool mute), + uint8_t gain_mode_auto, uint8_t mute), (override)); MOCK_METHOD((void), OnExtAudioInStatusChanged, (const RawAddress& address, uint8_t ext_input_id, VolumeInputStatus status), @@ -1333,9 +1333,22 @@ TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) { GetNotificationEvent(0x0021, too_long); } -TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed) { +TEST_F(VolumeControlCallbackTest, audio_input_state_changed__invalid_mute__is_rejected) { + uint8_t invalid_mute = 0x03; + std::vector value({0x03, invalid_mute, 0x02, 0x04}); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(_, _, _, _, _)).Times(0); + GetNotificationEvent(0x0032, value); +} + +TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__muted) { std::vector value({0x03, 0x01, 0x02, 0x04}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, true)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, 0x01)); + GetNotificationEvent(0x0032, value); +} + +TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__disabled) { + std::vector value({0x03, 0x02, 0x02, 0x04}); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, 0x02)); GetNotificationEvent(0x0032, value); } @@ -1475,7 +1488,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_state) { VolumeControl::Get()->GetExtAudioInState(test_address, 1); EXPECT_TRUE(cb); std::vector value({0x01, 0x00, 0x02, 0x03}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, false)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, 0x00)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc index e106aed5165..e18da7a2d65 100644 --- a/system/btif/src/btif_vc.cc +++ b/system/btif/src/btif_vc.cc @@ -103,7 +103,7 @@ class VolumeControlInterfaceImpl : public VolumeControlInterface, public VolumeC /* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */ void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode, bool mute) override { + uint8_t gain_mode, uint8_t mute) override { do_in_jni_thread(Bind(&VolumeControlCallbacks::OnExtAudioInStateChanged, Unretained(callbacks_), address, ext_input_id, gain_val, gain_mode, mute)); } diff --git a/system/gd/rust/topshim/vc/vc_shim.cc b/system/gd/rust/topshim/vc/vc_shim.cc index f7f68d5af25..ab0edd975b2 100644 --- a/system/gd/rust/topshim/vc/vc_shim.cc +++ b/system/gd/rust/topshim/vc/vc_shim.cc @@ -136,7 +136,7 @@ public: } void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode_auto, bool mute) { + uint8_t gain_mode_auto, uint8_t mute) { log::info("address={}, ext_input_id={}, gain_val={}, gain_mode_auto={}, mute={}", address, ext_input_id, gain_val, gain_mode_auto, mute); log::info("Not implemented"); diff --git a/system/include/hardware/bt_vc.h b/system/include/hardware/bt_vc.h index 7d24a075438..6b45b48bf48 100644 --- a/system/include/hardware/bt_vc.h +++ b/system/include/hardware/bt_vc.h @@ -73,7 +73,7 @@ public: /* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */ virtual void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, - int8_t gain_val, uint8_t gain_mode_auto, bool mute) = 0; + int8_t gain_val, uint8_t gain_mode_auto, uint8_t mute) = 0; virtual void OnExtAudioInStatusChanged(const RawAddress& address, uint8_t ext_input_id, VolumeInputStatus status) = 0; -- GitLab From 772b68e868b031cb341e5286d54ce52e9e3ff5ec Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 29 Oct 2024 17:16:15 -0700 Subject: [PATCH 502/875] HapClientService: use looper in test Test: atest BluetoothInstrumentationTests Flag: Exempt refactor no-op Bug: 311772251 Change-Id: I68fee88ac0dbb72dd503a84d5c21bc553e45de07 --- .../bluetooth/hap/HapClientService.java | 143 +++-- .../bluetooth/hap/HapClientStackEvent.java | 25 +- .../bluetooth/hap/HapClientStateMachine.java | 531 ++++++--------- .../bluetooth/hap/HapClientServiceTest.java | 605 ++++++------------ .../hap/HapClientStackEventTest.java | 22 - .../hap/HapClientStateMachineTest.java | 518 ++++++--------- system/include/hardware/bt_has.h | 1 + 7 files changed, 672 insertions(+), 1173 deletions(-) diff --git a/android/app/src/com/android/bluetooth/hap/HapClientService.java b/android/app/src/com/android/bluetooth/hap/HapClientService.java index a4896f20f7e..facb63f891e 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientService.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientService.java @@ -19,6 +19,8 @@ package com.android.bluetooth.hap; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElseGet; @@ -76,8 +78,9 @@ public class HapClientService extends ProfileService { private final AdapterService mAdapterService; private final DatabaseManager mDatabaseManager; private final Handler mHandler; + private final Looper mStateMachinesLooper; private final HandlerThread mStateMachinesThread; - private final HapClientNativeInterface mHapClientNativeInterface; + private final HapClientNativeInterface mNativeInterface; @VisibleForTesting @GuardedBy("mCallbacks") @@ -114,14 +117,17 @@ public class HapClientService extends ProfileService { } public HapClientService(AdapterService adapterService) { - this(adapterService, null); + this(adapterService, null, null); } @VisibleForTesting - HapClientService(AdapterService adapterService, HapClientNativeInterface nativeInterface) { + HapClientService( + AdapterService adapterService, + Looper looper, + HapClientNativeInterface nativeInterface) { super(adapterService); mAdapterService = requireNonNull(adapterService); - mHapClientNativeInterface = + mNativeInterface = requireNonNullElseGet( nativeInterface, () -> @@ -129,14 +135,19 @@ public class HapClientService extends ProfileService { new HapClientNativeCallback(adapterService, this))); mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); - // Start handler thread for state machines - mHandler = new Handler(Looper.getMainLooper()); - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("HapClientService.StateMachines"); - mStateMachinesThread.start(); + if (looper == null) { + mHandler = new Handler(requireNonNull(Looper.getMainLooper())); + mStateMachinesThread = new HandlerThread("HapClientService.StateMachines"); + mStateMachinesThread.start(); + mStateMachinesLooper = mStateMachinesThread.getLooper(); + } else { + mHandler = new Handler(looper); + mStateMachinesThread = null; + mStateMachinesLooper = looper; + } // Initialize native interface - mHapClientNativeInterface.init(); + mNativeInterface.init(); // Mark service as started setHapClient(this); @@ -162,23 +173,24 @@ public class HapClientService extends ProfileService { synchronized (mStateMachines) { for (HapClientStateMachine sm : mStateMachines.values()) { sm.doQuit(); - sm.cleanup(); } mStateMachines.clear(); } - try { - mStateMachinesThread.quitSafely(); - mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); - } catch (InterruptedException e) { - // Do not rethrow as we are shutting down anyway + if (mStateMachinesThread != null) { + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } } // Unregister Handler and stop all queued messages. mHandler.removeCallbacksAndMessages(null); // Cleanup GATT interface - mHapClientNativeInterface.cleanup(); + mNativeInterface.cleanup(); // Cleanup the internals mDeviceCurrentPresetMap.clear(); @@ -233,7 +245,6 @@ public class HapClientService extends ProfileService { } Log.i(TAG, "removeStateMachine: removing state machine for device: " + device); sm.doQuit(); - sm.cleanup(); mStateMachines.remove(device); } } @@ -423,7 +434,7 @@ public class HapClientService extends ProfileService { if (smConnect == null) { Log.e(TAG, "Cannot connect to " + device + " : no state machine"); } - smConnect.sendMessage(HapClientStateMachine.CONNECT); + smConnect.sendMessage(HapClientStateMachine.MESSAGE_CONNECT); } return true; @@ -444,7 +455,7 @@ public class HapClientService extends ProfileService { synchronized (mStateMachines) { HapClientStateMachine sm = mStateMachines.get(device); if (sm != null) { - sm.sendMessage(HapClientStateMachine.DISCONNECT); + sm.sendMessage(HapClientStateMachine.MESSAGE_DISCONNECT); } } @@ -470,12 +481,7 @@ public class HapClientService extends ProfileService { return null; } Log.d(TAG, "Creating a new state machine for " + device); - sm = - HapClientStateMachine.make( - device, - this, - mHapClientNativeInterface, - mStateMachinesThread.getLooper()); + sm = new HapClientStateMachine(this, device, mNativeInterface, mStateMachinesLooper); mStateMachines.put(device, sm); return sm; } @@ -542,7 +548,7 @@ public class HapClientService extends ProfileService { return; } - mHapClientNativeInterface.selectActivePreset(device, presetIndex); + mNativeInterface.selectActivePreset(device, presetIndex); } @VisibleForTesting @@ -558,23 +564,23 @@ public class HapClientService extends ProfileService { return; } - mHapClientNativeInterface.groupSelectActivePreset(groupId, presetIndex); + mNativeInterface.groupSelectActivePreset(groupId, presetIndex); } void switchToNextPreset(BluetoothDevice device) { - mHapClientNativeInterface.nextActivePreset(device); + mNativeInterface.nextActivePreset(device); } void switchToNextPresetForGroup(int groupId) { - mHapClientNativeInterface.groupNextActivePreset(groupId); + mNativeInterface.groupNextActivePreset(groupId); } void switchToPreviousPreset(BluetoothDevice device) { - mHapClientNativeInterface.previousActivePreset(device); + mNativeInterface.previousActivePreset(device); } void switchToPreviousPresetForGroup(int groupId) { - mHapClientNativeInterface.groupPreviousActivePreset(groupId); + mNativeInterface.groupPreviousActivePreset(groupId); } BluetoothHapPresetInfo getPresetInfo(BluetoothDevice device, int presetIndex) { @@ -585,7 +591,7 @@ public class HapClientService extends ProfileService { /* We want native to be called for PTS testing even we have all * the data in the cache here */ - mHapClientNativeInterface.getPresetInfo(device, presetIndex); + mNativeInterface.getPresetInfo(device, presetIndex); } List current_presets = mPresetsMap.get(device); if (current_presets != null) { @@ -614,20 +620,19 @@ public class HapClientService extends ProfileService { } private int stackEventPresetInfoReasonToProfileStatus(int statusCode) { - switch (statusCode) { - case HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO: - return BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST; - case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE: - return BluetoothStatusCodes.REASON_REMOTE_REQUEST; - case HapClientStackEvent.PRESET_INFO_REASON_PRESET_DELETED: - return BluetoothStatusCodes.REASON_REMOTE_REQUEST; - case HapClientStackEvent.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED: - return BluetoothStatusCodes.REASON_REMOTE_REQUEST; - case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE: - return BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST; - default: - return BluetoothStatusCodes.ERROR_UNKNOWN; - } + return switch (statusCode) { + case HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO -> + BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE -> + BluetoothStatusCodes.REASON_REMOTE_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_DELETED -> + BluetoothStatusCodes.REASON_REMOTE_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED -> + BluetoothStatusCodes.REASON_REMOTE_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE -> + BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST; + default -> BluetoothStatusCodes.ERROR_UNKNOWN; + }; } private void notifyPresetInfoChanged(BluetoothDevice device, int infoReason) { @@ -643,24 +648,23 @@ public class HapClientService extends ProfileService { } private int stackEventStatusToProfileStatus(int statusCode) { - switch (statusCode) { - case HapClientStackEvent.STATUS_SET_NAME_NOT_ALLOWED: - return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED; - case HapClientStackEvent.STATUS_OPERATION_NOT_SUPPORTED: - return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED; - case HapClientStackEvent.STATUS_OPERATION_NOT_POSSIBLE: - return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED; - case HapClientStackEvent.STATUS_INVALID_PRESET_NAME_LENGTH: - return BluetoothStatusCodes.ERROR_HAP_PRESET_NAME_TOO_LONG; - case HapClientStackEvent.STATUS_INVALID_PRESET_INDEX: - return BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX; - case HapClientStackEvent.STATUS_GROUP_OPERATION_NOT_SUPPORTED: - return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED; - case HapClientStackEvent.STATUS_PROCEDURE_ALREADY_IN_PROGRESS: - return BluetoothStatusCodes.ERROR_UNKNOWN; - default: - return BluetoothStatusCodes.ERROR_UNKNOWN; - } + return switch (statusCode) { + case HapClientStackEvent.STATUS_SET_NAME_NOT_ALLOWED -> + BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED; + case HapClientStackEvent.STATUS_OPERATION_NOT_SUPPORTED -> + BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED; + case HapClientStackEvent.STATUS_OPERATION_NOT_POSSIBLE -> + BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED; + case HapClientStackEvent.STATUS_INVALID_PRESET_NAME_LENGTH -> + BluetoothStatusCodes.ERROR_HAP_PRESET_NAME_TOO_LONG; + case HapClientStackEvent.STATUS_INVALID_PRESET_INDEX -> + BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX; + case HapClientStackEvent.STATUS_GROUP_OPERATION_NOT_SUPPORTED -> + BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED; + case HapClientStackEvent.STATUS_PROCEDURE_ALREADY_IN_PROGRESS -> + BluetoothStatusCodes.ERROR_UNKNOWN; + default -> BluetoothStatusCodes.ERROR_UNKNOWN; + }; } private boolean isPresetIndexValid(BluetoothDevice device, int presetIndex) { @@ -717,7 +721,7 @@ public class HapClientService extends ProfileService { // WARNING: We should check cache if preset exists and is writable, but then we would still // need a way to trigger this action with an invalid index or on a non-writable // preset for tests purpose. - mHapClientNativeInterface.setPresetName(device, presetIndex, name); + mNativeInterface.setPresetName(device, presetIndex, name); } @VisibleForTesting @@ -733,7 +737,7 @@ public class HapClientService extends ProfileService { return; } - mHapClientNativeInterface.groupSetPresetName(groupId, presetIndex, name); + mNativeInterface.groupSetPresetName(groupId, presetIndex, name); } @Override @@ -912,8 +916,7 @@ public class HapClientService extends ProfileService { if (sm == null) { if (stackEvent.type == HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { switch (stackEvent.valueInt1) { - case HapClientStackEvent.CONNECTION_STATE_CONNECTED, - HapClientStackEvent.CONNECTION_STATE_CONNECTING -> { + case STATE_CONNECTED, STATE_CONNECTING -> { sm = getOrCreateStateMachine(device); } default -> {} @@ -924,7 +927,7 @@ public class HapClientService extends ProfileService { Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); return; } - sm.sendMessage(HapClientStateMachine.STACK_EVENT, stackEvent); + sm.sendMessage(HapClientStateMachine.MESSAGE_STACK_EVENT, stackEvent); } } diff --git a/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java b/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java index 841baafe2a5..a0e978ef1db 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java @@ -17,6 +17,8 @@ package com.android.bluetooth.hap; +import static android.bluetooth.BluetoothProfile.getConnectionStateName; + import android.bluetooth.BluetoothDevice; import android.bluetooth.IBluetoothHapClient; @@ -40,12 +42,6 @@ public class HapClientStackEvent { public static final int EVENT_TYPE_ON_PRESET_NAME_SET_ERROR = 7; public static final int EVENT_TYPE_ON_PRESET_INFO_ERROR = 8; - // Connection state values as defined in bt_has.h - static final int CONNECTION_STATE_DISCONNECTED = 0; - static final int CONNECTION_STATE_CONNECTING = 1; - static final int CONNECTION_STATE_CONNECTED = 2; - static final int CONNECTION_STATE_DISCONNECTING = 3; - // Possible operation results /* WARNING: Matches status codes defined in bta_has.h */ static final int STATUS_NO_ERROR = 0; @@ -117,7 +113,7 @@ public class HapClientStackEvent { private String eventTypeValueInt1ToString(int type, int value) { switch (type) { case EVENT_TYPE_CONNECTION_STATE_CHANGED: - return "{state: " + connectionStateValueToString(value) + "}"; + return "{state: " + getConnectionStateName(value) + "}"; case EVENT_TYPE_DEVICE_AVAILABLE: return "{features: " + featuresToString(value) + "}"; case EVENT_TYPE_DEVICE_FEATURES: @@ -181,21 +177,6 @@ public class HapClientStackEvent { } } - private String connectionStateValueToString(int value) { - switch (value) { - case CONNECTION_STATE_DISCONNECTED: - return "CONNECTION_STATE_DISCONNECTED"; - case CONNECTION_STATE_CONNECTING: - return "CONNECTION_STATE_CONNECTING"; - case CONNECTION_STATE_CONNECTED: - return "CONNECTION_STATE_CONNECTED"; - case CONNECTION_STATE_DISCONNECTING: - return "CONNECTION_STATE_DISCONNECTING"; - default: - return "CONNECTION_STATE_UNKNOWN!"; - } - } - private String statusCodeValueToString(int value) { switch (value) { case STATUS_NO_ERROR: diff --git a/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java b/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java index e0b6dedf46b..4695103bde1 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java @@ -15,23 +15,39 @@ * limitations under the License. */ -/** - * Bluetooth Hap Client StateMachine. There is one instance per remote device. - "Disconnected" and - * "Connected" are steady states. - "Connecting" and "Disconnecting" are transient states until the - * connection / disconnection is completed. - * - *

    (Disconnected) | ^ CONNECT | | DISCONNECTED V | (Connecting)<--->(Disconnecting) | ^ CONNECTED - * | | DISCONNECT V | (Connected) NOTES: - If state machine is in "Connecting" state and the remote - * device sends DISCONNECT request, the state machine transitions to "Disconnecting" state. - - * Similarly, if the state machine is in "Disconnecting" state and the remote device sends CONNECT - * request, the state machine transitions to "Connecting" state. - * - *

    DISCONNECT (Connecting) ---------------> (Disconnecting) <--------------- CONNECT - */ +// Bluetooth Hap Client StateMachine. There is one instance per remote device. +// - "Disconnected" and "Connected" are steady states. +// - "Connecting" and "Disconnecting" are transient states until the +// connection / disconnection is completed. + +// (Disconnected) +// | ^ +// CONNECT | | DISCONNECTED +// V | +// (Connecting)<--->(Disconnecting) +// | ^ +// CONNECTED | | DISCONNECT +// V | +// (Connected) +// NOTES: +// - If state machine is in "Connecting" state and the remote device sends +// DISCONNECT request, the state machine transitions to "Disconnecting" state. +// - Similarly, if the state machine is in "Disconnecting" state and the remote device +// sends CONNECT request, the state machine transitions to "Connecting" state. + +// DISCONNECT +// (Connecting) ---------------> (Disconnecting) +// <--------------- +// CONNECT package com.android.bluetooth.hap; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; +import static android.bluetooth.BluetoothProfile.getConnectionStateName; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHapClient; @@ -49,40 +65,40 @@ import com.android.internal.util.StateMachine; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Duration; import java.util.Scanner; final class HapClientStateMachine extends StateMachine { - static final int CONNECT = 1; - static final int DISCONNECT = 2; - @VisibleForTesting static final int STACK_EVENT = 101; - private static final String TAG = "HapClientStateMachine"; - @VisibleForTesting static final int CONNECT_TIMEOUT = 201; + private static final String TAG = HapClientStateMachine.class.getSimpleName(); - // NOTE: the value is not "final" - it is modified in the unit tests - @VisibleForTesting static int sConnectTimeoutMs = 30000; // 30s + static final int MESSAGE_CONNECT = 1; + static final int MESSAGE_DISCONNECT = 2; + static final int MESSAGE_STACK_EVENT = 101; + @VisibleForTesting static final int MESSAGE_CONNECT_TIMEOUT = 201; + + @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(30); private final Disconnected mDisconnected; private final Connecting mConnecting; private final Disconnecting mDisconnecting; private final Connected mConnected; - private int mConnectionState = BluetoothProfile.STATE_DISCONNECTED; + + private int mConnectionState = STATE_DISCONNECTED; private int mLastConnectionState = -1; private final HapClientService mService; private final HapClientNativeInterface mNativeInterface; - private final BluetoothDevice mDevice; HapClientStateMachine( - BluetoothDevice device, HapClientService svc, + BluetoothDevice device, HapClientNativeInterface gattInterface, Looper looper) { super(TAG, looper); mDevice = device; mService = svc; mNativeInterface = gattInterface; - mDisconnected = new Disconnected(); mConnecting = new Connecting(); mDisconnecting = new Disconnecting(); @@ -94,61 +110,24 @@ final class HapClientStateMachine extends StateMachine { addState(mConnected); setInitialState(mDisconnected); - } - - static HapClientStateMachine make( - BluetoothDevice device, - HapClientService svc, - HapClientNativeInterface gattInterface, - Looper looper) { - Log.i(TAG, "make for device " + device); - HapClientStateMachine hearingAccessSm = - new HapClientStateMachine(device, svc, gattInterface, looper); - hearingAccessSm.start(); - return hearingAccessSm; + start(); } private static String messageWhatToString(int what) { - switch (what) { - case CONNECT: - return "CONNECT"; - case DISCONNECT: - return "DISCONNECT"; - case STACK_EVENT: - return "STACK_EVENT"; - case CONNECT_TIMEOUT: - return "CONNECT_TIMEOUT"; - default: - break; - } - return Integer.toString(what); - } - - private static String profileStateToString(int state) { - switch (state) { - case BluetoothProfile.STATE_DISCONNECTED: - return "DISCONNECTED"; - case BluetoothProfile.STATE_CONNECTING: - return "CONNECTING"; - case BluetoothProfile.STATE_CONNECTED: - return "CONNECTED"; - case BluetoothProfile.STATE_DISCONNECTING: - return "DISCONNECTING"; - default: - break; - } - return Integer.toString(state); + return switch (what) { + case MESSAGE_CONNECT -> "CONNECT"; + case MESSAGE_DISCONNECT -> "DISCONNECT"; + case MESSAGE_STACK_EVENT -> "STACK_EVENT"; + case MESSAGE_CONNECT_TIMEOUT -> "CONNECT_TIMEOUT"; + default -> Integer.toString(what); + }; } public void doQuit() { - log("doQuit for device " + mDevice); + Log.d(TAG, "doQuit for " + mDevice); quitNow(); } - public void cleanup() { - log("cleanup for device " + mDevice); - } - int getConnectionState() { return mConnectionState; } @@ -158,24 +137,22 @@ final class HapClientStateMachine extends StateMachine { } synchronized boolean isConnected() { - return (getConnectionState() == BluetoothProfile.STATE_CONNECTED); + return (getConnectionState() == STATE_CONNECTED); } - // This method does not check for error condition (newState == prevState) - private void broadcastConnectionState(int newState, int prevState) { - log( - "Connection state " - + mDevice - + ": " - + profileStateToString(prevState) + private void broadcastConnectionState() { + Log.d( + TAG, + ("Connection state " + mDevice + ": ") + + getConnectionStateName(mLastConnectionState) + "->" - + profileStateToString(newState)); + + getConnectionStateName(mConnectionState)); - mService.connectionStateChanged(mDevice, prevState, newState); + mService.connectionStateChanged(mDevice, mLastConnectionState, mConnectionState); Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED) - .putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState) - .putExtra(BluetoothProfile.EXTRA_STATE, newState) + .putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, mLastConnectionState) + .putExtra(BluetoothProfile.EXTRA_STATE, mConnectionState) .putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice) .addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT @@ -202,86 +179,60 @@ final class HapClientStateMachine extends StateMachine { scanner.close(); } - @Override - protected void log(String msg) { - super.log(msg); - } - @VisibleForTesting class Disconnected extends State { + private final String mStateLog = "Disconnected(" + mDevice + "): "; + @Override public void enter() { - Log.i( - TAG, - "Enter Disconnected(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - mConnectionState = BluetoothProfile.STATE_DISCONNECTED; - - removeDeferredMessages(DISCONNECT); - - if (mLastConnectionState != -1) { - // Don't broadcast during startup - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED, mLastConnectionState); + Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what)); + + removeDeferredMessages(MESSAGE_DISCONNECT); + + mConnectionState = STATE_DISCONNECTED; + if (mLastConnectionState != -1) { // Don't broadcast during startup + broadcastConnectionState(); } } @Override public void exit() { - log( - "Exit Disconnected(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; + Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what)); + mLastConnectionState = STATE_DISCONNECTED; } @Override public boolean processMessage(Message message) { - log( - "Disconnected: process message(" - + mDevice - + "): " - + messageWhatToString(message.what)); + Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - log("Connecting to " + mDevice); + case MESSAGE_CONNECT -> { if (!mNativeInterface.connectHapClient(mDevice)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); + Log.e(TAG, mStateLog + "native cannot connect"); break; } if (mService.okToConnect(mDevice)) { transitionTo(mConnecting); } else { - // Reject the request and stay in Disconnected state - Log.w( - TAG, - "Outgoing HearingAccess Connecting request rejected: " + mDevice); + Log.w(TAG, mStateLog + "outgoing connect request rejected"); } - break; - case DISCONNECT: - Log.d(TAG, "Disconnected: DISCONNECT: call native disconnect for " + mDevice); + } + case MESSAGE_DISCONNECT -> { mNativeInterface.disconnectHapClient(mDevice); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { HapClientStackEvent event = (HapClientStackEvent) message.obj; - Log.d(TAG, "Disconnected: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } switch (event.type) { - case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event); } - break; - default: + } + default -> { + Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } @@ -289,114 +240,83 @@ final class HapClientStateMachine extends StateMachine { // in Disconnected state private void processConnectionEvent(int state) { switch (state) { - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Ignore HearingAccess DISCONNECTED event: " + mDevice); - break; - case HapClientStackEvent.CONNECTION_STATE_CONNECTING: + case STATE_CONNECTING -> { if (mService.okToConnect(mDevice)) { - Log.i( - TAG, - "Incoming HearingAccess Connecting request accepted: " + mDevice); + Log.i(TAG, mStateLog + "Incoming connecting request accepted"); transitionTo(mConnecting); } else { - // Reject the connection and stay in Disconnected state itself - Log.w( - TAG, - "Incoming HearingAccess Connecting request rejected: " + mDevice); + Log.w(TAG, mStateLog + "Incoming connecting request rejected"); mNativeInterface.disconnectHapClient(mDevice); } - break; - case HapClientStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { Log.w(TAG, "HearingAccess Connected from Disconnected state: " + mDevice); if (mService.okToConnect(mDevice)) { - Log.i(TAG, "Incoming HearingAccess Connected request accepted: " + mDevice); + Log.w(TAG, mStateLog + "Incoming connected transition accepted"); transitionTo(mConnected); } else { - // Reject the connection and stay in Disconnected state itself - Log.w(TAG, "Incoming HearingAccess Connected request rejected: " + mDevice); + Log.w(TAG, mStateLog + "Incoming connected transition rejected"); mNativeInterface.disconnectHapClient(mDevice); } - break; - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Ignore HearingAccess DISCONNECTING event: " + mDevice); - break; - default: - Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); - break; + } + default -> Log.e(TAG, mStateLog + "Incorrect state: " + state); } } } @VisibleForTesting class Connecting extends State { + private final String mStateLog = "Connecting(" + mDevice + "): "; + @Override public void enter() { - Log.i( - TAG, - "Enter Connecting(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - mConnectionState = BluetoothProfile.STATE_CONNECTING; - broadcastConnectionState(BluetoothProfile.STATE_CONNECTING, mLastConnectionState); + Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what)); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + mConnectionState = STATE_CONNECTING; + broadcastConnectionState(); } @Override public void exit() { - log( - "Exit Connecting(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; - removeMessages(CONNECT_TIMEOUT); + Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what)); + mLastConnectionState = STATE_CONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override public boolean processMessage(Message message) { - log( - "Connecting: process message(" - + mDevice - + "): " - + messageWhatToString(message.what)); + Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - Log.w(TAG, "Connecting connection timeout: " + mDevice); + case MESSAGE_CONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { + Log.w(TAG, mStateLog + "connection timeout"); mNativeInterface.disconnectHapClient(mDevice); HapClientStackEvent disconnectEvent = new HapClientStackEvent( HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - case DISCONNECT: - log("Connecting: connection canceled to " + mDevice); + disconnectEvent.valueInt1 = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, disconnectEvent); + } + case MESSAGE_DISCONNECT -> { + Log.d(TAG, mStateLog + "connection canceled"); mNativeInterface.disconnectHapClient(mDevice); transitionTo(mDisconnected); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { HapClientStackEvent event = (HapClientStackEvent) message.obj; - log("Connecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } switch (event.type) { - case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Connecting: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event); } - break; - default: + } + default -> { + Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } @@ -404,98 +324,69 @@ final class HapClientStateMachine extends StateMachine { // in Connecting state private void processConnectionEvent(int state) { switch (state) { - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Connecting device disconnected: " + mDevice); + case STATE_DISCONNECTED -> { + Log.i(TAG, mStateLog + "device disconnected"); transitionTo(mDisconnected); - break; - case HapClientStackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case HapClientStackEvent.CONNECTION_STATE_CONNECTING: - break; - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice); + } + case STATE_CONNECTED -> transitionTo(mConnected); + case STATE_DISCONNECTING -> { + Log.i(TAG, mStateLog + "device disconnecting"); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; + } + default -> Log.e(TAG, mStateLog + "Incorrect state: " + state); } } } @VisibleForTesting class Disconnecting extends State { + private final String mStateLog = "Disconnecting(" + mDevice + "): "; + @Override public void enter() { - Log.i( - TAG, - "Enter Disconnecting(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - mConnectionState = BluetoothProfile.STATE_DISCONNECTING; - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTING, mLastConnectionState); + Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what)); + sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis()); + mConnectionState = STATE_DISCONNECTING; + broadcastConnectionState(); } @Override public void exit() { - log( - "Exit Disconnecting(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); + Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what)); + mLastConnectionState = STATE_DISCONNECTING; + removeMessages(MESSAGE_CONNECT_TIMEOUT); } @Override public boolean processMessage(Message message) { - log( - "Disconnecting: process message(" - + mDevice - + "): " - + messageWhatToString(message.what)); + Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - { - Log.w(TAG, "Disconnecting connection timeout: " + mDevice); - mNativeInterface.disconnectHapClient(mDevice); + case MESSAGE_CONNECT, MESSAGE_DISCONNECT -> deferMessage(message); + case MESSAGE_CONNECT_TIMEOUT -> { + Log.w(TAG, mStateLog + "connection timeout"); + mNativeInterface.disconnectHapClient(mDevice); - HapClientStackEvent disconnectEvent = - new HapClientStackEvent( - HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = - HapClientStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - } - case DISCONNECT: - deferMessage(message); - break; - case STACK_EVENT: + HapClientStackEvent disconnectEvent = + new HapClientStackEvent( + HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + disconnectEvent.device = mDevice; + disconnectEvent.valueInt1 = STATE_DISCONNECTED; + sendMessage(MESSAGE_STACK_EVENT, disconnectEvent); + } + case MESSAGE_STACK_EVENT -> { HapClientStackEvent event = (HapClientStackEvent) message.obj; - log("Disconnecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } switch (event.type) { - case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: + case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnecting: ignoring stack event: " + event); - break; + } + default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event); } - break; - default: + } + default -> { + Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } @@ -503,105 +394,79 @@ final class HapClientStateMachine extends StateMachine { // in Disconnecting state private void processConnectionEvent(int state) { switch (state) { - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.i(TAG, "Disconnected: " + mDevice); + case STATE_DISCONNECTED -> { + Log.i(TAG, mStateLog + "Disconnected"); transitionTo(mDisconnected); - break; - case HapClientStackEvent.CONNECTION_STATE_CONNECTED: + } + case STATE_CONNECTED -> { if (mService.okToConnect(mDevice)) { - Log.w(TAG, "Disconnecting interrupted: device is connected: " + mDevice); + Log.w(TAG, mStateLog + "interrupted: device is connected"); transitionTo(mConnected); } else { // Reject the connection and stay in Disconnecting state - Log.w(TAG, "Incoming HearingAccess Connected request rejected: " + mDevice); + Log.w(TAG, mStateLog + "Incoming connect request rejected"); mNativeInterface.disconnectHapClient(mDevice); } - break; - case HapClientStackEvent.CONNECTION_STATE_CONNECTING: + } + case STATE_CONNECTING -> { if (mService.okToConnect(mDevice)) { - Log.i(TAG, "Disconnecting interrupted: try to reconnect: " + mDevice); + Log.i(TAG, mStateLog + "interrupted: device try to reconnect"); transitionTo(mConnecting); } else { // Reject the connection and stay in Disconnecting state - Log.w( - TAG, - "Incoming HearingAccess Connecting request rejected: " + mDevice); + Log.w(TAG, mStateLog + "Incoming connecting request rejected"); mNativeInterface.disconnectHapClient(mDevice); } - break; - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING: - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; + } + default -> Log.e(TAG, mStateLog + "Incorrect state: " + state); } } } @VisibleForTesting class Connected extends State { + private final String mStateLog = "Connected(" + mDevice + "): "; + @Override public void enter() { - Log.i( - TAG, - "Enter Connected(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - mConnectionState = BluetoothProfile.STATE_CONNECTED; - removeDeferredMessages(CONNECT); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTED, mLastConnectionState); + Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what)); + removeDeferredMessages(MESSAGE_CONNECT); + mConnectionState = STATE_CONNECTED; + broadcastConnectionState(); } @Override public void exit() { - log( - "Exit Connected(" - + mDevice - + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; + Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what)); + mLastConnectionState = STATE_CONNECTED; } @Override public boolean processMessage(Message message) { - log( - "Connected: process message(" - + mDevice - + "): " - + messageWhatToString(message.what)); + Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what)); switch (message.what) { - case CONNECT: - Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); - break; - case DISCONNECT: - log("Disconnecting from " + mDevice); + case MESSAGE_DISCONNECT -> { if (!mNativeInterface.disconnectHapClient(mDevice)) { // If error in the native stack, transition directly to Disconnected state. - Log.e(TAG, "Connected: error disconnecting from " + mDevice); + Log.e(TAG, mStateLog + "native cannot disconnect"); transitionTo(mDisconnected); break; } transitionTo(mDisconnecting); - break; - case STACK_EVENT: + } + case MESSAGE_STACK_EVENT -> { HapClientStackEvent event = (HapClientStackEvent) message.obj; - log("Connected: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } switch (event.type) { - case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Connected: ignoring stack event: " + event); - break; + case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> + processConnectionEvent(event.valueInt1); + default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event); } - break; - default: + } + default -> { + Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what)); return NOT_HANDLED; + } } return HANDLED; } @@ -609,17 +474,15 @@ final class HapClientStateMachine extends StateMachine { // in Connected state private void processConnectionEvent(int state) { switch (state) { - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.i(TAG, "Disconnected from " + mDevice + " but still in Allowlist"); + case STATE_DISCONNECTED -> { + Log.i(TAG, mStateLog + "Disconnected but still in allowlist"); transitionTo(mDisconnected); - break; - case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.i(TAG, "Disconnecting from " + mDevice); + } + case STATE_DISCONNECTING -> { + Log.i(TAG, mStateLog + "Disconnecting"); transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state); - break; + } + default -> Log.e(TAG, mStateLog + "Incorrect state: " + state); } } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java index 4f26e51db2a..81c4865b847 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java @@ -17,8 +17,14 @@ package com.android.bluetooth.hap; -import static android.bluetooth.BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED; +import static android.bluetooth.BluetoothDevice.BOND_BONDED; +import static android.bluetooth.BluetoothDevice.BOND_BONDING; +import static android.bluetooth.BluetoothDevice.BOND_NONE; import static android.bluetooth.BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE; +import static android.bluetooth.BluetoothHapClient.PRESET_INDEX_UNAVAILABLE; +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.EXTRA_PREVIOUS_STATE; import static android.bluetooth.BluetoothProfile.EXTRA_STATE; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; @@ -31,13 +37,12 @@ import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; import static com.google.common.truth.Truth.assertThat; import static org.hamcrest.core.AllOf.allOf; -import static org.mockito.Mockito.after; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -51,8 +56,11 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothHapClientCallback; +import android.content.Intent; import android.os.Binder; import android.os.ParcelUuid; +import android.os.RemoteException; +import android.os.test.TestLooper; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; @@ -64,8 +72,9 @@ import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.csip.CsipSetCoordinatorService; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -74,6 +83,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -82,17 +92,10 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.concurrent.TimeoutException; @MediumTest @RunWith(AndroidJUnit4.class) public class HapClientServiceTest { - private static final int TIMEOUT_MS = 1000; - private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); - private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 0); - private final BluetoothDevice mDevice2 = TestUtils.getTestDevice(mAdapter, 1); - private final BluetoothDevice mDevice3 = TestUtils.getTestDevice(mAdapter, 2); - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @@ -103,22 +106,34 @@ public class HapClientServiceTest { @Mock private IBluetoothHapClientCallback mFrameworkCallback; @Mock private Binder mBinder; + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 0); + private final BluetoothDevice mDevice2 = TestUtils.getTestDevice(mAdapter, 1); + private final BluetoothDevice mDevice3 = TestUtils.getTestDevice(mAdapter, 2); + private HapClientService mService; private HapClientNativeCallback mNativeCallback; + private InOrder mInOrder; + private TestLooper mLooper; @Before - public void setUp() throws Exception { - HapClientStateMachine.sConnectTimeoutMs = TIMEOUT_MS; - - doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); + public void setUp() { doReturn(mDevice).when(mAdapterService).getDeviceFromByte(eq(getByteAddress(mDevice))); doReturn(mDevice2).when(mAdapterService).getDeviceFromByte(eq(getByteAddress(mDevice2))); doReturn(mDevice3).when(mAdapterService).getDeviceFromByte(eq(getByteAddress(mDevice3))); + doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); + + doReturn(CONNECTION_POLICY_ALLOWED) + .when(mDatabaseManager) + .getProfileConnectionPolicy(any(), anyInt()); doReturn(mCsipService).when(mServiceFactory).getCsipSetCoordinatorService(); doReturn(mBinder).when(mFrameworkCallback).asBinder(); + doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class)); + doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); + /* Prepare CAS groups */ doReturn(List.of(0x02, 0x03)).when(mCsipService).getAllGroupIds(BluetoothUuid.CAP); @@ -147,8 +162,13 @@ public class HapClientServiceTest { .getRemoteUuids(any(BluetoothDevice.class)); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); - startService(); + mInOrder = inOrder(mAdapterService); + mLooper = new TestLooper(); + + mService = new HapClientService(mAdapterService, mLooper.getLooper(), mNativeInterface); + mService.setAvailable(true); mNativeCallback = new HapClientNativeCallback(mAdapterService, mService); + mService.mFactory = mServiceFactory; synchronized (mService.mCallbacks) { mService.mCallbacks.register(mFrameworkCallback); @@ -156,257 +176,114 @@ public class HapClientServiceTest { } @After - public void tearDown() throws Exception { - if (mService == null) { - return; - } - + public void tearDown() { synchronized (mService.mCallbacks) { mService.mCallbacks.unregister(mFrameworkCallback); } - stopService(); - } - - private void startService() throws TimeoutException { - mService = new HapClientService(mAdapterService, mNativeInterface); - mService.start(); - mService.setAvailable(true); - } - - private void stopService() throws TimeoutException { mService.stop(); - mService = HapClientService.getHapClientService(); - Assert.assertNull(mService); - } - - @Test - public void testGetHapService() { - Assert.assertEquals(mService, HapClientService.getHapClientService()); + assertThat(HapClientService.getHapClientService()).isNull(); } @Test - public void testGetSetPolicy() throws Exception { - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - Assert.assertEquals( - "Initial device policy", - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - mService.getConnectionPolicy(mDevice)); - - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - Assert.assertEquals( - "Setting device policy to POLICY_FORBIDDEN", - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - mService.getConnectionPolicy(mDevice)); - - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - int policy = mService.getConnectionPolicy(mDevice); - Assert.assertEquals( - "Setting device policy to POLICY_ALLOWED", - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - policy); + public void getHapService() { + assertThat(HapClientService.getHapClientService()).isEqualTo(mService); } @Test - public void testGetPolicyAfterStopped() { - mService.stop(); - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - Assert.assertEquals( - "Initial device policy", - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - mService.getConnectionPolicy(mDevice)); + public void getConnectionPolicy() { + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.getConnectionPolicy(mDevice)).isEqualTo(policy); + } } @Test - public void testOkToConnect() { + public void canConnect_whenNotBonded_returnFalse() { int badPolicyValue = 1024; int badBondState = 42; - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_NONE, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testOkToConnectCase(mDevice, BluetoothDevice.BOND_NONE, badPolicyValue, false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDING, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - false); - testOkToConnectCase(mDevice, BluetoothDevice.BOND_BONDING, badPolicyValue, false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - true); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, - false); - testOkToConnectCase( - mDevice, - BluetoothDevice.BOND_BONDED, - BluetoothProfile.CONNECTION_POLICY_ALLOWED, - true); - testOkToConnectCase(mDevice, BluetoothDevice.BOND_BONDED, badPolicyValue, false); - testOkToConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, false); - testOkToConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, false); - testOkToConnectCase( - mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_ALLOWED, false); - testOkToConnectCase(mDevice, badBondState, badPolicyValue, false); + for (int bondState : List.of(BOND_NONE, BOND_BONDING, badBondState)) { + for (int policy : + List.of( + CONNECTION_POLICY_UNKNOWN, + CONNECTION_POLICY_FORBIDDEN, + CONNECTION_POLICY_ALLOWED, + badPolicyValue)) { + doReturn(bondState).when(mAdapterService).getBondState(any()); + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mDevice)).isEqualTo(false); + } + } } @Test - public void testOutgoingConnectMissingHasUuid() { - // Update the device policy so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); - - // Return No UUID - doReturn(new ParcelUuid[] {}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); + public void canConnect_whenBonded() { + int badPolicyValue = 1024; + doReturn(BOND_BONDED).when(mAdapterService).getBondState(any()); - // Send a connect request - Assert.assertFalse("Connect expected to fail", mService.connect(mDevice)); + for (int policy : List.of(CONNECTION_POLICY_FORBIDDEN, badPolicyValue)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mDevice)).isEqualTo(false); + } + for (int policy : List.of(CONNECTION_POLICY_UNKNOWN, CONNECTION_POLICY_ALLOWED)) { + doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt()); + assertThat(mService.okToConnect(mDevice)).isEqualTo(true); + } } @Test - public void testOutgoingConnectExistingHasUuid() { - // Update the device policy so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); - - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) + public void connectToDevice_whenUuidIsMissing_returnFalse() { + doReturn(new ParcelUuid[] {}) .when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - // Send a connect request - Assert.assertTrue("Connect expected to succeed", mService.connect(mDevice)); - - verify(mAdapterService, timeout(TIMEOUT_MS)).sendBroadcastMultiplePermissions(any(), any()); + assertThat(mService.connect(mDevice)).isFalse(); } @Test - public void testOutgoingConnectPolicyForbidden() { - doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); - - // Set the device policy to POLICY_FORBIDDEN so connect() should fail - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); + public void connectToDevice_whenPolicyForbid_returnFalse() { + doReturn(CONNECTION_POLICY_FORBIDDEN) + .when(mDatabaseManager) + .getProfileConnectionPolicy(any(), anyInt()); - // Send a connect request - Assert.assertFalse("Connect expected to fail", mService.connect(mDevice)); + assertThat(mService.connect(mDevice)).isFalse(); } @Test - public void testOutgoingConnectTimeout() throws Exception { - InOrder order = inOrder(mAdapterService); - - // Update the device policy so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); + public void outgoingConnect_whenTimeOut_isDisconnected() { + assertThat(mService.connect(mDevice)).isTrue(); + mLooper.dispatchAll(); - // Send a connect request - Assert.assertTrue("Connect failed", mService.connect(mDevice)); + verifyConnectionStateIntent(mDevice, STATE_CONNECTING, STATE_DISCONNECTED); - order.verify(mAdapterService, timeout(TIMEOUT_MS)) - .sendBroadcastMultiplePermissions( - argThat( - allOf( - hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(EXTRA_STATE, STATE_CONNECTING), - hasExtra(EXTRA_PREVIOUS_STATE, STATE_DISCONNECTED))), - any()); + mLooper.moveTimeForward(HapClientStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(mDevice)); - - // Verify the connection state broadcast, and that we are in Disconnected state via binder - order.verify(mAdapterService, timeout(HapClientStateMachine.sConnectTimeoutMs * 2L)) - .sendBroadcastMultiplePermissions( - argThat( - allOf( - hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(EXTRA_STATE, STATE_DISCONNECTED), - hasExtra(EXTRA_PREVIOUS_STATE, STATE_CONNECTING))), - any()); - - int state = mService.getConnectionState(mDevice); - Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, state); + verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTING); } @Test - public void testConnectTwo() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); + public void connectTwoDevices() { + testConnectingDevice(mDevice); + testConnectingDevice(mDevice2); - // Send a connect request for the 1st device - testConnectingDevice(order, mDevice); - - // Send a connect request for the 2nd device - BluetoothDevice Device2 = TestUtils.getTestDevice(mAdapter, 1); - testConnectingDevice(order, Device2); - - List devices = mService.getConnectedDevices(); - Assert.assertTrue(devices.contains(mDevice)); - Assert.assertTrue(devices.contains(Device2)); - Assert.assertNotEquals(mDevice, Device2); + assertThat(mService.getConnectedDevices()).containsExactly(mDevice, mDevice2); } @Test - public void testCallsForNotConnectedDevice() { - Assert.assertEquals( - BluetoothHapClient.PRESET_INDEX_UNAVAILABLE, - mService.getActivePresetIndex(mDevice)); + public void getActivePresetIndex_whenNoConnected_isUnavailable() { + assertThat(mService.getActivePresetIndex(mDevice)).isEqualTo(PRESET_INDEX_UNAVAILABLE); } @Test - public void testGetHapGroupCoordinatedOps() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice); - testConnectingDevice(order, mDevice2); - testConnectingDevice(order, mDevice3); + public void testGetHapGroupCoordinatedOps() { + testConnectingDevice(mDevice); + testConnectingDevice(mDevice2); + testConnectingDevice(mDevice3); mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice), 0x04); mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice3), 0x04); @@ -418,26 +295,22 @@ public class HapClientServiceTest { mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice2), 0); /* Two devices support coordinated operations thus shall report valid group ID */ - Assert.assertEquals(2, mService.getHapGroup(mDevice)); - Assert.assertEquals(3, mService.getHapGroup(mDevice3)); + assertThat(mService.getHapGroup(mDevice)).isEqualTo(2); + assertThat(mService.getHapGroup(mDevice3)).isEqualTo(3); /* Third one has no coordinated operations support but is part of the group */ int hapGroup = mService.getHapGroup(mDevice2); - Assert.assertEquals(2, hapGroup); + assertThat(hapGroup).isEqualTo(2); } @Test - public void testSelectPresetNative() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice); + public void testSelectPresetNative() throws RemoteException { + testConnectingDevice(mDevice); // Verify Native Interface call mService.selectPreset(mDevice, 0x00); verify(mNativeInterface, never()).selectActivePreset(eq(mDevice), eq(0x00)); - verify(mFrameworkCallback, after(TIMEOUT_MS)) + verify(mFrameworkCallback) .onPresetSelectionFailed( eq(mDevice), eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); @@ -446,19 +319,15 @@ public class HapClientServiceTest { } @Test - public void testGroupSelectActivePresetNative() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice3); + public void testGroupSelectActivePresetNative() throws RemoteException { + testConnectingDevice(mDevice3); int flags = 0x01; mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice3), flags); // Verify Native Interface call mService.selectPresetForGroup(0x03, 0x00); - verify(mFrameworkCallback, after(TIMEOUT_MS)) + verify(mFrameworkCallback) .onPresetSelectionForGroupFailed( eq(0x03), eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); @@ -468,11 +337,7 @@ public class HapClientServiceTest { @Test public void testSwitchToNextPreset() { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice); + testConnectingDevice(mDevice); // Verify Native Interface call mService.switchToNextPreset(mDevice); @@ -481,11 +346,7 @@ public class HapClientServiceTest { @Test public void testSwitchToNextPresetForGroup() { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice3); + testConnectingDevice(mDevice3); int flags = 0x01; mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice3), flags); @@ -496,11 +357,7 @@ public class HapClientServiceTest { @Test public void testSwitchToPreviousPreset() { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice); + testConnectingDevice(mDevice); // Verify Native Interface call mService.switchToPreviousPreset(mDevice); @@ -509,12 +366,8 @@ public class HapClientServiceTest { @Test public void testSwitchToPreviousPresetForGroup() { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice); - testConnectingDevice(order, mDevice2); + testConnectingDevice(mDevice); + testConnectingDevice(mDevice2); int flags = 0x01; mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice), flags); @@ -525,56 +378,40 @@ public class HapClientServiceTest { } @Test - public void testGetActivePresetIndex() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice); + public void testGetActivePresetIndex() throws RemoteException { + testConnectingDevice(mDevice); testOnPresetSelected(mDevice, 0x01); - // Verify cached value via binder - int presetIndex = mService.getActivePresetIndex(mDevice); - Assert.assertEquals(0x01, presetIndex); + assertThat(mService.getActivePresetIndex(mDevice)).isEqualTo(0x01); } @Test - public void testGetPresetInfoAndActivePresetInfo() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice2); + public void testGetPresetInfoAndActivePresetInfo() throws RemoteException { + testConnectingDevice(mDevice2); // Check when active preset is not known yet List presetList = mService.getAllPresetInfo(mDevice2); BluetoothHapPresetInfo presetInfo = mService.getPresetInfo(mDevice2, 0x01); - Assert.assertTrue(presetList.contains(presetInfo)); - Assert.assertEquals(0x01, presetInfo.getIndex()); + assertThat(presetList).contains(presetInfo); + assertThat(presetInfo.getIndex()).isEqualTo(0x01); - Assert.assertEquals( - BluetoothHapClient.PRESET_INDEX_UNAVAILABLE, - mService.getActivePresetIndex(mDevice2)); - Assert.assertEquals(null, mService.getActivePresetInfo(mDevice2)); + assertThat(mService.getActivePresetIndex(mDevice2)).isEqualTo(PRESET_INDEX_UNAVAILABLE); + assertThat(mService.getActivePresetInfo(mDevice2)).isNull(); // Inject active preset change event testOnPresetSelected(mDevice2, 0x01); // Check when active preset is known - Assert.assertEquals(0x01, mService.getActivePresetIndex(mDevice2)); + assertThat(mService.getActivePresetIndex(mDevice2)).isEqualTo(0x01); BluetoothHapPresetInfo info = mService.getActivePresetInfo(mDevice2); - Assert.assertNotNull(info); - Assert.assertEquals("One", info.getName()); + assertThat(info).isNotNull(); + assertThat(info.getName()).isEqualTo("One"); } @Test - public void testSetPresetNameNative() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(order, mDevice); + public void testSetPresetNameNative() throws RemoteException { + testConnectingDevice(mDevice); mService.setPresetName(mDevice, 0x00, "ExamplePresetName"); verify(mNativeInterface, never()) @@ -589,26 +426,22 @@ public class HapClientServiceTest { } @Test - public void testSetPresetNameForGroup() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); + public void testSetPresetNameForGroup() throws RemoteException { int test_group = 0x02; - testConnectingDevice(order, mDevice); - testConnectingDevice(order, mDevice2); + testConnectingDevice(mDevice); + testConnectingDevice(mDevice2); int flags = 0x21; mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice), flags); mService.setPresetNameForGroup(test_group, 0x00, "ExamplePresetName"); - verify(mFrameworkCallback, after(TIMEOUT_MS)) + verify(mFrameworkCallback) .onSetPresetNameForGroupFailed( eq(test_group), eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); mService.setPresetNameForGroup(-1, 0x01, "ExamplePresetName"); - verify(mFrameworkCallback, after(TIMEOUT_MS)) + verify(mFrameworkCallback) .onSetPresetNameForGroupFailed( eq(-1), eq(BluetoothStatusCodes.ERROR_CSIP_INVALID_GROUP_ID)); @@ -635,7 +468,7 @@ public class HapClientServiceTest { } @Test - public void testStackEventOnPresetSelected() throws Exception { + public void testStackEventOnPresetSelected() throws RemoteException { int presetIndex = 0x01; mNativeCallback.onActivePresetSelected(getByteAddress(mDevice), presetIndex); @@ -649,7 +482,7 @@ public class HapClientServiceTest { } @Test - public void testStackEventOnActivePresetSelectError() throws Exception { + public void testStackEventOnActivePresetSelectError() throws RemoteException { mNativeCallback.onActivePresetSelectError(getByteAddress(mDevice), 0x05); verify(mFrameworkCallback) @@ -658,14 +491,8 @@ public class HapClientServiceTest { } @Test - public void testStackEventOnPresetInfo() throws Exception { - InOrder order = inOrder(mAdapterService); - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - - // Connect and inject initial presets - testConnectingDevice(order, mDevice); + public void testStackEventOnPresetInfo() throws RemoteException { + testConnectingDevice(mDevice); int infoReason = HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE; BluetoothHapPresetInfo[] info = { @@ -686,17 +513,18 @@ public class HapClientServiceTest { eq(BluetoothStatusCodes.REASON_REMOTE_REQUEST)); List presets = presetsCaptor.getValue(); - Assert.assertEquals(3, presets.size()); + assertThat(presets.size()).isEqualTo(3); Optional preset = presetsCaptor.getValue().stream().filter(p -> 0x01 == p.getIndex()).findFirst(); - Assert.assertEquals("OneChangedToUnavailable", preset.get().getName()); - Assert.assertFalse(preset.get().isAvailable()); - Assert.assertTrue(preset.get().isWritable()); + assertThat(preset.get().getName()).isEqualTo("OneChangedToUnavailable"); + assertThat(preset.get().isAvailable()).isFalse(); + ; + assertThat(preset.get().isWritable()).isTrue(); } @Test - public void testStackEventOnPresetNameSetError() throws Exception { + public void testStackEventOnPresetNameSetError() throws RemoteException { /* Not a valid name length */ mNativeCallback.onPresetNameSetError( getByteAddress(mDevice), @@ -736,7 +564,7 @@ public class HapClientServiceTest { } @Test - public void testStackEventOnGroupPresetNameSetError() throws Exception { + public void testStackEventOnGroupPresetNameSetError() throws RemoteException { int groupId = 0x01; int presetIndex = 0x04; /* Not a valid name length */ @@ -776,30 +604,25 @@ public class HapClientServiceTest { } @Test - public void testServiceBinderGetDevicesMatchingConnectionStates() throws Exception { - List devices = mService.getDevicesMatchingConnectionStates(null); - Assert.assertEquals(0, devices.size()); + public void getDevicesMatchingConnectionStates_whenNull_isEmpty() { + assertThat(mService.getDevicesMatchingConnectionStates(null)).isEmpty(); } @Test - public void testServiceBinderSetConnectionPolicy() throws Exception { - Assert.assertTrue( - mService.setConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN)); + public void setConnectionPolicy() { + assertThat(mService.setConnectionPolicy(mDevice, CONNECTION_POLICY_UNKNOWN)).isTrue(); verify(mDatabaseManager) .setProfileConnectionPolicy( - mDevice, - BluetoothProfile.HAP_CLIENT, - BluetoothProfile.CONNECTION_POLICY_UNKNOWN); + mDevice, BluetoothProfile.HAP_CLIENT, CONNECTION_POLICY_UNKNOWN); } @Test - public void testServiceBinderGetFeatures() throws Exception { - int features = mService.getFeatures(mDevice); - Assert.assertEquals(0x00, features); + public void getFeatures() { + assertThat(mService.getFeatures(mDevice)).isEqualTo(0x00); } @Test - public void testServiceBinderRegisterUnregisterCallback() throws Exception { + public void registerUnregisterCallback() { IBluetoothHapClientCallback callback = Mockito.mock(IBluetoothHapClientCallback.class); Binder binder = Mockito.mock(Binder.class); when(callback.asBinder()).thenReturn(binder); @@ -807,101 +630,51 @@ public class HapClientServiceTest { synchronized (mService.mCallbacks) { int size = mService.mCallbacks.getRegisteredCallbackCount(); mService.registerCallback(callback); - Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1); mService.unregisterCallback(callback); - Assert.assertEquals(size, mService.mCallbacks.getRegisteredCallbackCount()); + assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size); } } @Test - public void testDumpDoesNotCrash() { - // Update the device policy so okToConnect() returns true - when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); - - doReturn(new ParcelUuid[] {BluetoothUuid.HAS}) - .when(mAdapterService) - .getRemoteUuids(any(BluetoothDevice.class)); - + public void dumpDoesNotCrash() { // Add state machine for testing dump() mService.connect(mDevice); - - verify(mAdapterService, timeout(TIMEOUT_MS)).sendBroadcastMultiplePermissions(any(), any()); + mLooper.dispatchAll(); mService.dump(new StringBuilder()); } /** Helper function to test device connecting */ - private void prepareConnectingDevice(BluetoothDevice device) { - // Prepare intent queue and all the mocks - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HAP_CLIENT)) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); + private void testConnectingDevice(BluetoothDevice device) { + assertThat(mService.connect(device)).isTrue(); + mLooper.dispatchAll(); + verifyConnectingDevice(device); } /** Helper function to test device connecting */ - private void testConnectingDevice(InOrder order, BluetoothDevice device) { - prepareConnectingDevice(device); - // Send a connect request - Assert.assertTrue("Connect expected to succeed", mService.connect(device)); - verifyConnectingDevice(order, device); - } + private void verifyConnectingDevice(BluetoothDevice device) { + verifyConnectionStateIntent(device, STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(device, STATE_CONNECTED, STATE_CONNECTING); - /** Helper function to test device connecting */ - private void verifyConnectingDevice(InOrder order, BluetoothDevice device) { - // Verify the connection state broadcast, and that we are in Connecting state - order.verify(mAdapterService, timeout(TIMEOUT_MS)) - .sendBroadcastMultiplePermissions( - argThat( - allOf( - hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, device), - hasExtra(EXTRA_STATE, STATE_CONNECTING), - hasExtra(EXTRA_PREVIOUS_STATE, STATE_DISCONNECTED))), - any()); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(device)); - - // Send a message to trigger connection completed HapClientStackEvent evt = - new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - evt.device = device; - evt.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED; - mService.messageFromNative(evt); - - // Verify the connection state broadcast, and that we are in Connected state - order.verify(mAdapterService, timeout(TIMEOUT_MS)) - .sendBroadcastMultiplePermissions( - argThat( - allOf( - hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, device), - hasExtra(EXTRA_STATE, STATE_CONNECTED), - hasExtra(EXTRA_PREVIOUS_STATE, STATE_CONNECTING))), - any()); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(device)); - - evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); + new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); evt.device = device; evt.valueInt1 = 0x01; // features mService.messageFromNative(evt); + mLooper.dispatchAll(); - order.verify(mAdapterService, timeout(TIMEOUT_MS)) - .sendBroadcastMultiplePermissions( - argThat( - allOf( - hasAction(ACTION_HAP_DEVICE_AVAILABLE), - hasExtra(BluetoothDevice.EXTRA_DEVICE, device), - hasExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x01))), - any()); + verifyIntentSent( + hasAction(ACTION_HAP_DEVICE_AVAILABLE), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x01)); evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_FEATURES); evt.device = device; evt.valueInt1 = 0x01; // features mService.messageFromNative(evt); + mLooper.dispatchAll(); // Inject some initial presets List presets = @@ -923,29 +696,21 @@ public class HapClientServiceTest { device, HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO, presets); } - private void testOnPresetSelected(BluetoothDevice device, int index) throws Exception { + private void testOnPresetSelected(BluetoothDevice device, int index) throws RemoteException { HapClientStackEvent evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED); evt.device = device; evt.valueInt1 = index; mService.messageFromNative(evt); + mLooper.dispatchAll(); - verify(mFrameworkCallback, after(TIMEOUT_MS)) + verify(mFrameworkCallback) .onPresetSelected( eq(device), eq(evt.valueInt1), eq(BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST)); } - /** Helper function to test okToConnect() method */ - private void testOkToConnectCase( - BluetoothDevice device, int bondState, int policy, boolean expected) { - doReturn(bondState).when(mAdapterService).getBondState(device); - when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HAP_CLIENT)) - .thenReturn(policy); - Assert.assertEquals(expected, mService.okToConnect(device)); - } - /** Helper function to get byte array for a device address */ private byte[] getByteAddress(BluetoothDevice device) { if (device == null) { @@ -953,4 +718,32 @@ public class HapClientServiceTest { } return Utils.getBytesFromAddress(device.getAddress()); } + + @SafeVarargs + private void verifyIntentSent(Matcher... matchers) { + mInOrder.verify(mAdapterService) + .sendBroadcastMultiplePermissions( + MockitoHamcrest.argThat(AllOf.allOf(matchers)), any()); + } + + private void verifyConnectionStateIntent(BluetoothDevice device, int newState, int prevState) { + verifyIntentSent( + hasAction(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(EXTRA_STATE, newState), + hasExtra(EXTRA_PREVIOUS_STATE, prevState)); + assertThat(mService.getConnectionState(device)).isEqualTo(newState); + } + + private void generateConnectionMessageFromNative( + BluetoothDevice device, int newState, int oldState) { + HapClientStackEvent event = + new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + event.device = device; + event.valueInt1 = newState; + mService.messageFromNative(event); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(device, newState, oldState); + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java index d307a5ce9e0..249914b6443 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java @@ -37,28 +37,6 @@ public final class HapClientStackEventTest { eventStr = event.toString(); assertThat(eventStr).contains("EVENT_TYPE_UNKNOWN"); - event = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.valueInt1 = -1; - eventStr = event.toString(); - assertThat(eventStr).contains("EVENT_TYPE_CONNECTION_STATE_CHANGED"); - assertThat(eventStr).contains("CONNECTION_STATE_UNKNOWN"); - - event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTED; - eventStr = event.toString(); - assertThat(eventStr).contains("CONNECTION_STATE_DISCONNECTED"); - - event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING; - eventStr = event.toString(); - assertThat(eventStr).contains("CONNECTION_STATE_CONNECTING"); - - event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED; - eventStr = event.toString(); - assertThat(eventStr).contains("CONNECTION_STATE_CONNECTED"); - - event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTING; - eventStr = event.toString(); - assertThat(eventStr).contains("CONNECTION_STATE_DISCONNECTING"); - event = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); eventStr = event.toString(); assertThat(eventStr).contains("EVENT_TYPE_DEVICE_AVAILABLE"); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java index a61e4ea5035..1c25fad6376 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java @@ -17,373 +17,253 @@ package com.android.bluetooth.hap; +import static android.bluetooth.BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED; +import static android.bluetooth.BluetoothProfile.EXTRA_PREVIOUS_STATE; +import static android.bluetooth.BluetoothProfile.EXTRA_STATE; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; + +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; + +import static com.android.bluetooth.hap.HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; +import static com.android.bluetooth.hap.HapClientStateMachine.CONNECT_TIMEOUT; +import static com.android.bluetooth.hap.HapClientStateMachine.MESSAGE_CONNECT; +import static com.android.bluetooth.hap.HapClientStateMachine.MESSAGE_DISCONNECT; +import static com.android.bluetooth.hap.HapClientStateMachine.MESSAGE_STACK_EVENT; + +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.after; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; import android.content.Intent; -import android.os.HandlerThread; -import android.os.Message; +import android.os.test.TestLooper; -import androidx.test.filters.MediumTest; +import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.bluetooth.TestUtils; -import com.android.bluetooth.btservice.AdapterService; - -import org.hamcrest.core.IsInstanceOf; -import org.junit.After; -import org.junit.Assert; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; 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.Mockito; +import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -@MediumTest +@SmallTest @RunWith(AndroidJUnit4.class) public class HapClientStateMachineTest { - private BluetoothAdapter mAdapter; - private HandlerThread mHandlerThread; - private HapClientStateMachine mHapClientStateMachine; - private BluetoothDevice mTestDevice; - private static final int TIMEOUT_MS = 1000; - boolean mIsAdapterServiceSet; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock private AdapterService mAdapterService; - @Mock private HapClientService mHapClientService; - @Mock private HapClientNativeInterface mHearingAccessGattClientInterface; + @Mock private HapClientService mService; + @Mock private HapClientNativeInterface mNativeInterface; + + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); + + private HapClientStateMachine mStateMachine; + private InOrder mInOrder; + private TestLooper mLooper; @Before public void setUp() throws Exception { - TestUtils.setAdapterService(mAdapterService); - mIsAdapterServiceSet = true; - - mAdapter = BluetoothAdapter.getDefaultAdapter(); - - // Get a device for testing - mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); - - // Set up thread and looper - mHandlerThread = new HandlerThread("HapClientStateMachineTestHandlerThread"); - mHandlerThread.start(); - mHapClientStateMachine = - new HapClientStateMachine( - mTestDevice, - mHapClientService, - mHearingAccessGattClientInterface, - mHandlerThread.getLooper()); - // Override the timeout value to speed up the test - HapClientStateMachine.sConnectTimeoutMs = 1000; // 1s - mHapClientStateMachine.start(); + doReturn(true).when(mService).okToConnect(any()); + + doReturn(true).when(mNativeInterface).connectHapClient(any()); + doReturn(true).when(mNativeInterface).disconnectHapClient(any()); + + mInOrder = inOrder(mService); + mLooper = new TestLooper(); + + mStateMachine = + new HapClientStateMachine(mService, mDevice, mNativeInterface, mLooper.getLooper()); } - @After - public void tearDown() throws Exception { - if (!mIsAdapterServiceSet) { - return; - } - if (mHapClientStateMachine != null) { - mHapClientStateMachine.doQuit(); - mHandlerThread.quit(); - } - TestUtils.clearAdapterService(mAdapterService); + @Test + public void initialState_isDisconnected() { + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } - /** Test that default state is disconnected */ @Test - public void testDefaultDisconnectedState() { - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mHapClientStateMachine.getConnectionState()); + public void incomingConnect_whenNotOkToConnect_isRejected() { + doReturn(false).when(mService).okToConnect(any()); + + generateUnexpectedConnectionMessageFromNative(STATE_CONNECTED); + + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Disconnected.class); + assertThat(mLooper.nextMessage()).isNull(); } - /** - * Allow/disallow connection to any device. - * - * @param allow if true, connection is allowed - */ - private void allowConnection(boolean allow) { - doReturn(allow).when(mHapClientService).okToConnect(any(BluetoothDevice.class)); + @Test + public void incomingConnect_whenOkToConnect_isConnected() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Connecting.class); + + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Connected.class); } - /** Test that an incoming connection with policy forbidding connection is rejected */ @Test - public void testIncomingPolicyReject() { - allowConnection(false); - - // Inject an event for when incoming connection is requested - HapClientStackEvent connStCh = - new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED; - mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connStCh); - - // Verify that no connection state broadcast is executed - verify(mHapClientService, after(TIMEOUT_MS).never()) - .sendBroadcast(any(Intent.class), anyString()); - // Check that we are in Disconnected state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class)); + public void outgoingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { + sendAndDispatchMessage(MESSAGE_CONNECT); + verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Connecting.class); + + mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Disconnected.class); } - /** Test that an incoming connection with policy allowing connection is accepted */ @Test - public void testIncomingPolicyAccept() { - allowConnection(true); - - // Inject an event for when incoming connection is requested - HapClientStackEvent connStCh = - new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING; - mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connStCh); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHapClientService, timeout(TIMEOUT_MS)) - .sendBroadcastWithMultiplePermissions( - intentArgument1.capture(), any(String[].class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Connecting.class)); - - // Send a message to trigger connection completed - HapClientStackEvent connCompletedEvent = - new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connCompletedEvent.device = mTestDevice; - connCompletedEvent.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED; - mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connCompletedEvent); - - // Verify that the expected number of broadcasts are executed: - // - two calls to broadcastConnectionState(): Disconnected -> Connecting -> Connected - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mHapClientService, timeout(TIMEOUT_MS).times(2)) - .sendBroadcastWithMultiplePermissions( - intentArgument2.capture(), any(String[].class)); - // Check that we are in Connected state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Connected.class)); + public void incomingConnect_whenTimeOut_isDisconnectedAndInAcceptList() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Connecting.class); + + mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Disconnected.class); } - /** Test that an outgoing connection times out */ @Test - public void testOutgoingTimeout() { - allowConnection(true); - doReturn(true) - .when(mHearingAccessGattClientInterface) - .connectHapClient(any(BluetoothDevice.class)); - doReturn(true) - .when(mHearingAccessGattClientInterface) - .disconnectHapClient(any(BluetoothDevice.class)); - - // Send a connect request - mHapClientStateMachine.sendMessage(HapClientStateMachine.CONNECT, mTestDevice); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHapClientService, timeout(TIMEOUT_MS)) - .sendBroadcastWithMultiplePermissions( - intentArgument1.capture(), any(String[].class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Connecting.class)); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mHapClientService, timeout(HapClientStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcastWithMultiplePermissions( - intentArgument2.capture(), any(String[].class)); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Disconnected state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class)); - verify(mHearingAccessGattClientInterface).disconnectHapClient(eq(mTestDevice)); + public void disconnect_whenDisconnected_callNativeDisconnect() { + mStateMachine.sendMessage(HapClientStateMachine.MESSAGE_DISCONNECT); + mLooper.dispatchAll(); + + verify(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class)); } - /** Test that an incoming connection times out */ @Test - public void testIncomingTimeout() { - allowConnection(true); - doReturn(true) - .when(mHearingAccessGattClientInterface) - .connectHapClient(any(BluetoothDevice.class)); - doReturn(true) - .when(mHearingAccessGattClientInterface) - .disconnectHapClient(any(BluetoothDevice.class)); - - // Inject an event for when incoming connection is requested - HapClientStackEvent connStCh = - new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING; - mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connStCh); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); - verify(mHapClientService, timeout(TIMEOUT_MS)) - .sendBroadcastWithMultiplePermissions( - intentArgument1.capture(), any(String[].class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Connecting state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Connecting.class)); - - // Verify that one connection state broadcast is executed - ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); - verify(mHapClientService, timeout(HapClientStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcastWithMultiplePermissions( - intentArgument2.capture(), any(String[].class)); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - - // Check that we are in Disconnected state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class)); - verify(mHearingAccessGattClientInterface).disconnectHapClient(eq(mTestDevice)); + public void timeout_whenOutgoingConnect_isDisconnected() { + sendAndDispatchMessage(MESSAGE_CONNECT); + verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Connecting.class); + + mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Disconnected.class); } @Test - public void testStatesChangesWithMessages() { - allowConnection(true); - doReturn(true) - .when(mHearingAccessGattClientInterface) - .connectHapClient(any(BluetoothDevice.class)); - - // Check that we are in Disconnected state - Assert.assertThat( - mHapClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class)); - - mHapClientStateMachine.sendMessage(HapClientStateMachine.DISCONNECT); - // verify disconnectHapClient was called - verify(mHearingAccessGattClientInterface, timeout(TIMEOUT_MS).times(1)) - .disconnectHapClient(any(BluetoothDevice.class)); - - // disconnected -> connecting - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT), - HapClientStateMachine.Connecting.class); - // connecting -> disconnected - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT_TIMEOUT), - HapClientStateMachine.Disconnected.class); - - // disconnected -> connecting - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT), - HapClientStateMachine.Connecting.class); - // connecting -> disconnected - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.DISCONNECT), - HapClientStateMachine.Disconnected.class); - - // disconnected -> connecting - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT), - HapClientStateMachine.Connecting.class); - // connecting -> disconnecting - HapClientStackEvent connStCh = - new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTING; - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh), - HapClientStateMachine.Disconnecting.class); - // disconnecting -> connecting - connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING; - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh), - HapClientStateMachine.Connecting.class); - // connecting -> connected - connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED; - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh), - HapClientStateMachine.Connected.class); - // connected -> disconnecting - connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTING; - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh), - HapClientStateMachine.Disconnecting.class); - // disconnecting -> disconnected - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT_TIMEOUT), - HapClientStateMachine.Disconnected.class); - - // disconnected -> connected - connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED; - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh), - HapClientStateMachine.Connected.class); - // connected -> disconnected - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.DISCONNECT), - HapClientStateMachine.Disconnected.class); - - // disconnected -> connected - connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED; - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh), - HapClientStateMachine.Connected.class); - // connected -> disconnected - connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - connStCh.device = mTestDevice; - connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessageAndVerifyTransition( - mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh), - HapClientStateMachine.Disconnected.class); + public void disconnect_whenConnecting_isDisconnected() { + sendAndDispatchMessage(MESSAGE_CONNECT); + verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Connecting.class); + + sendAndDispatchMessage(MESSAGE_DISCONNECT); + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Disconnected.class); } - private void sendMessageAndVerifyTransition(Message msg, Class type) { - Mockito.clearInvocations(mHapClientService); - mHapClientStateMachine.sendMessage(msg); - // Verify that one connection state broadcast is executed - verify(mHapClientService, timeout(TIMEOUT_MS)) - .sendBroadcastWithMultiplePermissions(any(Intent.class), any(String[].class)); - Assert.assertThat(mHapClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); + @Test + public void remoteToggleDisconnect_whenConnecting_isDisconnected() { + sendAndDispatchMessage(MESSAGE_CONNECT); + verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Connecting.class); + + generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTING); + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTING); + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTED); + + mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Disconnected.class); + } + + @Test + public void timeout_whenOutgoingDisConnect_isDisconnected() { + generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED); + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING); + generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTED); + + mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_DISCONNECTING); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(HapClientStateMachine.Disconnected.class); + } + + @Test + public void incomingConnect_whenDisconnected_isConnected() { + generateConnectionMessageFromNative(STATE_CONNECTED, STATE_DISCONNECTED); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTED); + } + + private void sendAndDispatchMessage(int what) { + mStateMachine.sendMessage(what); + mLooper.dispatchAll(); + } + + @SafeVarargs + private void verifyIntentSent(Matcher... matchers) { + mInOrder.verify(mService) + .sendBroadcastWithMultiplePermissions( + MockitoHamcrest.argThat(AllOf.allOf(matchers)), any()); + } + + private void verifyConnectionStateIntent(int newState, int oldState) { + verifyIntentSent( + hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(EXTRA_STATE, newState), + hasExtra(EXTRA_PREVIOUS_STATE, oldState)); + assertThat(mStateMachine.getConnectionState()).isEqualTo(newState); + } + + private void generateConnectionMessageFromNative(int newState, int oldState) { + HapClientStackEvent event = new HapClientStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED); + event.device = mDevice; + event.valueInt1 = newState; + + mStateMachine.sendMessage(MESSAGE_STACK_EVENT, event); + mLooper.dispatchAll(); + + verifyConnectionStateIntent(newState, oldState); + } + + private void generateUnexpectedConnectionMessageFromNative(int newConnectionState) { + HapClientStackEvent event = new HapClientStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED); + event.device = mDevice; + event.valueInt1 = newConnectionState; + + mStateMachine.sendMessage(MESSAGE_STACK_EVENT, event); + mLooper.dispatchAll(); + + mInOrder.verify(mService, never()).sendBroadcast(any(), any(), any()); } } diff --git a/system/include/hardware/bt_has.h b/system/include/hardware/bt_has.h index 631ca656d2c..c5e17445eba 100644 --- a/system/include/hardware/bt_has.h +++ b/system/include/hardware/bt_has.h @@ -26,6 +26,7 @@ namespace bluetooth { namespace has { /** Connection State */ +// Must be kept in sync with BluetoothProfile.java enum class ConnectionState : uint8_t { DISCONNECTED = 0, CONNECTING, -- GitLab From ca3326e752018b23924d395dcbba84e710313f1e Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 30 Oct 2024 18:21:05 +0000 Subject: [PATCH 503/875] system/stack/acl: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: Iab5d284bcd3d6099a80a113a2f4e712cc221124b --- system/stack/acl/ble_acl.cc | 4 +- system/stack/acl/btm_acl.cc | 38 +----- system/stack/acl/btm_pm.cc | 14 +-- system/stack/btm/btm_devctl.cc | 2 +- system/stack/include/acl_hci_link_interface.h | 1 + system/stack/test/btm/stack_btm_test.cc | 21 ---- system/test/mock/mock_stack_acl.cc | 71 +---------- system/test/mock/mock_stack_acl.h | 114 ------------------ system/test/mock/mock_stack_acl_ble.cc | 4 +- system/test/mock/mock_stack_acl_btm_pm.cc | 9 +- 10 files changed, 23 insertions(+), 255 deletions(-) diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index fb26beab708..683e4801cd8 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -27,15 +27,13 @@ #include "stack/btm/btm_sec.h" #include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" +#include "stack/include/ble_acl_interface.h" #include "stack/include/btm_ble_addr.h" #include "stack/include/btm_ble_privacy.h" #include "stack/include/gatt_api.h" #include "stack/include/l2cap_hci_link_interface.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; extern tBTM_CB btm_cb; diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 0c52e80bb6a..fecf7b9547a 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -73,6 +73,7 @@ #include "stack/include/btm_status.h" #include "stack/include/hci_error_code.h" #include "stack/include/hcimsgs.h" +#include "stack/include/inq_hci_link_interface.h" #include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cdefs.h" #include "stack/include/main_thread.h" @@ -88,9 +89,6 @@ #define PROPERTY_AUTO_FLUSH_TIMEOUT "bluetooth.core.classic.auto_flush_timeout" #endif -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; using bluetooth::legacy::hci::GetInterface; @@ -212,27 +210,6 @@ void StackAclBtmAcl::hci_start_role_switch_to_central(tACL_CONN& p_acl) { p_acl.rs_disc_pending = BTM_SEC_RS_PENDING; } -void hci_btm_set_link_supervision_timeout(tACL_CONN& link, uint16_t timeout) { - if (link.link_role != HCI_ROLE_CENTRAL) { - /* Only send if current role is Central; 2.0 spec requires this */ - log::warn("Can only set link supervision timeout if central role:{}", RoleText(link.link_role)); - return; - } - - if (!bluetooth::shim::GetController()->IsSupported( - bluetooth::hci::OpCode::WRITE_LINK_SUPERVISION_TIMEOUT)) { - log::warn( - "UNSUPPORTED by controller write link supervision timeout:{:.2f}ms " - "bd_addr:{}", - supervision_timeout_to_seconds(timeout), link.RemoteAddress()); - return; - } - log::debug("Setting link supervision timeout:{:.2f}s peer:{}", double(timeout) * 0.01, - link.RemoteAddress()); - link.link_super_tout = timeout; - btsnd_hcic_write_link_super_tout(link.Handle(), timeout); -} - /* 3 seconds timeout waiting for responses */ #define BTM_DEV_REPLY_TIMEOUT_MS (3 * 1000) @@ -302,10 +279,6 @@ tACL_CONN* StackAclBtmAcl::btm_bda_to_acl(const RawAddress& bda, tBT_TRANSPORT t return nullptr; } -tACL_CONN* acl_get_connection_from_address(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - return internal_.btm_bda_to_acl(bd_addr, transport); -} - void StackAclBtmAcl::btm_acl_consolidate(const RawAddress& identity_addr, const RawAddress& rpa) { tACL_CONN* p_acl = &btm_cb.acl_cb_.acl_db[0]; for (uint8_t index = 0; index < MAX_L2CAP_LINKS; index++, p_acl++) { @@ -356,7 +329,7 @@ tACL_CONN* StackAclBtmAcl::acl_get_connection_from_handle(uint16_t hci_handle) { return &btm_cb.acl_cb_.acl_db[index]; } -tACL_CONN* acl_get_connection_from_handle(uint16_t handle) { +static tACL_CONN* acl_get_connection_from_handle(uint16_t handle) { return internal_.acl_get_connection_from_handle(handle); } @@ -803,8 +776,9 @@ static void maybe_chain_more_commands_after_read_remote_version_complete(uint8_t btm_iot_save_remote_versions(p_acl_cb); } -void btm_process_remote_version_complete(uint8_t status, uint16_t handle, uint8_t lmp_version, - uint16_t manufacturer, uint16_t lmp_subversion) { +static void btm_process_remote_version_complete(uint8_t status, uint16_t handle, + uint8_t lmp_version, uint16_t manufacturer, + uint16_t lmp_subversion) { tACL_CONN* p_acl_cb = internal_.acl_get_connection_from_handle(handle); if (p_acl_cb == nullptr) { log::warn("Received remote version complete for unknown acl"); @@ -2376,7 +2350,7 @@ void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason, std::string // 7.1.6 Disconnect command // Only a subset of reasons are valid and will be accepted // by the controller -bool is_disconnect_reason_valid(const tHCI_REASON& reason) { +static bool is_disconnect_reason_valid(const tHCI_REASON& reason) { switch (reason) { case HCI_ERR_AUTH_FAILURE: case HCI_ERR_PEER_USER: diff --git a/system/stack/acl/btm_pm.cc b/system/stack/acl/btm_pm.cc index c34e776a1f9..1914f30a382 100644 --- a/system/stack/acl/btm_pm.cc +++ b/system/stack/acl/btm_pm.cc @@ -44,19 +44,17 @@ #include "main/shim/entry.h" #include "osi/include/stack_power_telemetry.h" #include "stack/btm/btm_int_types.h" +#include "stack/include/acl_api.h" +#include "stack/include/acl_hci_link_interface.h" #include "stack/include/bt_types.h" #include "stack/include/btm_log_history.h" #include "stack/include/btm_status.h" +#include "stack/include/l2cap_hci_link_interface.h" +#include "stack/include/sco_hci_link_interface.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; -void l2c_OnHciModeChangeSendPendingPackets(RawAddress remote); -void btm_sco_chk_pend_unpark(tHCI_STATUS status, uint16_t handle); -void btm_cont_rswitch_from_handle(uint16_t hci_handle); extern tBTM_CB btm_cb; namespace { @@ -750,8 +748,8 @@ void btm_pm_proc_mode_change(tHCI_STATUS hci_status, uint16_t hci_handle, tHCI_M * Returns none. * ******************************************************************************/ -void process_ssr_event(tHCI_STATUS status, uint16_t handle, uint16_t /* max_tx_lat */, - uint16_t max_rx_lat) { +static void process_ssr_event(tHCI_STATUS status, uint16_t handle, uint16_t /* max_tx_lat */, + uint16_t max_rx_lat) { if (pm_mode_db.count(handle) == 0) { log::warn("Received sniff subrating event with no active ACL"); return; diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc index d22fba73c77..953487b183d 100644 --- a/system/stack/btm/btm_devctl.cc +++ b/system/stack/btm/btm_devctl.cc @@ -41,6 +41,7 @@ #include "stack/connection_manager/connection_manager.h" #include "stack/include/acl_api.h" #include "stack/include/acl_api_types.h" +#include "stack/include/acl_hci_link_interface.h" #include "stack/include/bt_types.h" #include "stack/include/btm_ble_privacy.h" #include "stack/include/btm_inq.h" @@ -57,7 +58,6 @@ using namespace ::bluetooth; extern tBTM_CB btm_cb; void btm_inq_db_reset(void); -void btm_pm_reset(void); /******************************************************************************/ /* L O C A L D A T A D E F I N I T I O N S */ /******************************************************************************/ diff --git a/system/stack/include/acl_hci_link_interface.h b/system/stack/include/acl_hci_link_interface.h index 561d56ad900..ac17f0dbaf8 100644 --- a/system/stack/include/acl_hci_link_interface.h +++ b/system/stack/include/acl_hci_link_interface.h @@ -58,6 +58,7 @@ void acl_packets_completed(uint16_t handle, uint16_t num_packets); void acl_process_supported_features(uint16_t handle, uint64_t features); void acl_process_extended_features(uint16_t handle, uint8_t current_page_number, uint8_t max_page_number, uint64_t features); +void btm_pm_reset(); void btm_pm_on_mode_change(tHCI_STATUS status, uint16_t handle, tHCI_MODE current_mode, uint16_t interval); void btm_pm_on_sniff_subrating(tHCI_STATUS status, uint16_t handle, diff --git a/system/stack/test/btm/stack_btm_test.cc b/system/stack/test/btm/stack_btm_test.cc index c1b90eeef9e..c308911bce6 100644 --- a/system/stack/test/btm/stack_btm_test.cc +++ b/system/stack/test/btm/stack_btm_test.cc @@ -277,25 +277,4 @@ TEST_F(StackBtmTest, sco_state_text) { .c_str()); } -bool is_disconnect_reason_valid(const tHCI_REASON& reason); -TEST_F(StackBtmWithInitFreeTest, is_disconnect_reason_valid) { - std::set valid_reason_set{ - HCI_ERR_AUTH_FAILURE, - HCI_ERR_PEER_USER, - HCI_ERR_REMOTE_LOW_RESOURCE, - HCI_ERR_REMOTE_POWER_OFF, - HCI_ERR_UNSUPPORTED_REM_FEATURE, - HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED, - HCI_ERR_UNACCEPT_CONN_INTERVAL, - }; - for (unsigned u = 0; u < 256; u++) { - const tHCI_REASON reason = static_cast(u); - if (valid_reason_set.count(reason)) { - ASSERT_TRUE(is_disconnect_reason_valid(reason)); - } else { - ASSERT_FALSE(is_disconnect_reason_valid(reason)); - } - } -} - TEST_F(StackBtmWithInitFreeTest, Init) { ASSERT_FALSE(btm_cb.rnr.remname_active); } diff --git a/system/test/mock/mock_stack_acl.cc b/system/test/mock/mock_stack_acl.cc index 1e85c50ee33..d4504baf541 100644 --- a/system/test/mock/mock_stack_acl.cc +++ b/system/test/mock/mock_stack_acl.cc @@ -27,17 +27,19 @@ #include #include "hci/class_of_device.h" +#include "stack/include/acl_api.h" #include "stack/include/acl_client_callbacks.h" +#include "stack/include/acl_hci_link_interface.h" #include "stack/include/bt_hdr.h" +#include "stack/include/btm_ble_api.h" +#include "stack/include/inq_hci_link_interface.h" +#include "stack/include/l2cap_acl_interface.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" // Mocked compile conditionals, if any // Mocked internal structures, if any -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - namespace test { namespace mock { namespace stack_acl { @@ -63,9 +65,7 @@ struct acl_peer_supports_ble_connection_subrating_host acl_peer_supports_ble_connection_subrating_host; struct acl_refresh_remote_address acl_refresh_remote_address; struct acl_set_peer_le_features_from_handle acl_set_peer_le_features_from_handle; -struct acl_get_connection_from_address acl_get_connection_from_address; struct btm_acl_for_bda btm_acl_for_bda; -struct acl_get_connection_from_handle acl_get_connection_from_handle; struct BTM_ReadFailedContactCounter BTM_ReadFailedContactCounter; struct BTM_ReadTxPower BTM_ReadTxPower; struct BTM_SetLinkSuperTout BTM_SetLinkSuperTout; @@ -98,28 +98,18 @@ struct btm_acl_notif_conn_collision btm_acl_notif_conn_collision; struct btm_acl_process_sca_cmpl_pkt btm_acl_process_sca_cmpl_pkt; struct btm_acl_removed btm_acl_removed; struct btm_acl_role_changed btm_acl_role_changed; -struct btm_acl_update_conn_addr btm_acl_update_conn_addr; -struct btm_ble_refresh_local_resolvable_private_addr btm_ble_refresh_local_resolvable_private_addr; struct btm_cont_rswitch_from_handle btm_cont_rswitch_from_handle; struct btm_establish_continue_from_address btm_establish_continue_from_address; -struct btm_process_remote_ext_features btm_process_remote_ext_features; -struct btm_process_remote_version_complete btm_process_remote_version_complete; struct btm_read_automatic_flush_timeout_complete btm_read_automatic_flush_timeout_complete; struct btm_read_failed_contact_counter_complete btm_read_failed_contact_counter_complete; -struct btm_read_failed_contact_counter_timeout btm_read_failed_contact_counter_timeout; -struct btm_read_remote_ext_features btm_read_remote_ext_features; struct btm_read_remote_ext_features_complete btm_read_remote_ext_features_complete; struct btm_read_remote_ext_features_complete_raw btm_read_remote_ext_features_complete_raw; struct btm_read_remote_ext_features_failed btm_read_remote_ext_features_failed; struct btm_read_remote_version_complete btm_read_remote_version_complete; struct btm_read_rssi_complete btm_read_rssi_complete; -struct btm_read_rssi_timeout btm_read_rssi_timeout; struct btm_read_tx_power_complete btm_read_tx_power_complete; -struct btm_read_tx_power_timeout btm_read_tx_power_timeout; struct btm_rejectlist_role_change_device btm_rejectlist_role_change_device; -struct btm_set_link_policy btm_set_link_policy; struct btm_set_packet_types_from_address btm_set_packet_types_from_address; -struct hci_btm_set_link_supervision_timeout hci_btm_set_link_supervision_timeout; struct on_acl_br_edr_connected on_acl_br_edr_connected; struct on_acl_br_edr_failed on_acl_br_edr_failed; struct BTM_unblock_role_switch_and_sniff_mode_for BTM_unblock_role_switch_and_sniff_mode_for; @@ -210,18 +200,10 @@ void acl_send_data_packet_br_edr(const RawAddress& bd_addr, BT_HDR* p_buf) { inc_func_call_count(__func__); test::mock::stack_acl::acl_send_data_packet_br_edr(bd_addr, p_buf); } -tACL_CONN* acl_get_connection_from_address(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - inc_func_call_count(__func__); - return test::mock::stack_acl::acl_get_connection_from_address(bd_addr, transport); -} tACL_CONN* btm_acl_for_bda(const RawAddress& bd_addr, tBT_TRANSPORT transport) { inc_func_call_count(__func__); return test::mock::stack_acl::btm_acl_for_bda(bd_addr, transport); } -tACL_CONN* acl_get_connection_from_handle(uint16_t handle) { - inc_func_call_count(__func__); - return test::mock::stack_acl::acl_get_connection_from_handle(handle); -} tBTM_STATUS BTM_ReadFailedContactCounter(const RawAddress& remote_bda, tBTM_CMPL_CB* p_cb) { inc_func_call_count(__func__); return test::mock::stack_acl::BTM_ReadFailedContactCounter(remote_bda, p_cb); @@ -354,15 +336,6 @@ void btm_acl_role_changed(tHCI_STATUS hci_status, const RawAddress& bd_addr, tHC inc_func_call_count(__func__); test::mock::stack_acl::btm_acl_role_changed(hci_status, bd_addr, new_role); } -void btm_acl_update_conn_addr(uint16_t handle, const RawAddress& address) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_acl_update_conn_addr(handle, address); -} -void btm_ble_refresh_local_resolvable_private_addr(const RawAddress& pseudo_addr, - const RawAddress& local_rpa) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_ble_refresh_local_resolvable_private_addr(pseudo_addr, local_rpa); -} void btm_cont_rswitch_from_handle(uint16_t hci_handle) { inc_func_call_count(__func__); test::mock::stack_acl::btm_cont_rswitch_from_handle(hci_handle); @@ -371,16 +344,6 @@ void btm_establish_continue_from_address(const RawAddress& bda, tBT_TRANSPORT tr inc_func_call_count(__func__); test::mock::stack_acl::btm_establish_continue_from_address(bda, transport); } -void btm_process_remote_ext_features(tACL_CONN* p_acl_cb, uint8_t max_page_number) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_process_remote_ext_features(p_acl_cb, max_page_number); -} -void btm_process_remote_version_complete(uint8_t status, uint16_t handle, uint8_t lmp_version, - uint16_t manufacturer, uint16_t lmp_subversion) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_process_remote_version_complete(status, handle, lmp_version, - manufacturer, lmp_subversion); -} void btm_read_automatic_flush_timeout_complete(uint8_t* p) { inc_func_call_count(__func__); test::mock::stack_acl::btm_read_automatic_flush_timeout_complete(p); @@ -389,14 +352,6 @@ void btm_read_failed_contact_counter_complete(uint8_t* p) { inc_func_call_count(__func__); test::mock::stack_acl::btm_read_failed_contact_counter_complete(p); } -void btm_read_failed_contact_counter_timeout(void* data) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_read_failed_contact_counter_timeout(data); -} -void btm_read_remote_ext_features(uint16_t handle, uint8_t page_number) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_read_remote_ext_features(handle, page_number); -} void btm_read_remote_ext_features_complete(uint16_t handle, uint8_t page_num, uint8_t max_page, uint8_t* features) { inc_func_call_count(__func__); @@ -421,34 +376,18 @@ void btm_read_rssi_complete(uint8_t* p, uint16_t evt_len) { inc_func_call_count(__func__); test::mock::stack_acl::btm_read_rssi_complete(p, evt_len); } -void btm_read_rssi_timeout(void* data) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_read_rssi_timeout(data); -} void btm_read_tx_power_complete(uint8_t* p, uint16_t evt_len, bool is_ble) { inc_func_call_count(__func__); test::mock::stack_acl::btm_read_tx_power_complete(p, evt_len, is_ble); } -void btm_read_tx_power_timeout(void* data) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_read_tx_power_timeout(data); -} void btm_rejectlist_role_change_device(const RawAddress& bd_addr, uint8_t hci_status) { inc_func_call_count(__func__); test::mock::stack_acl::btm_rejectlist_role_change_device(bd_addr, hci_status); } -void btm_set_link_policy(tACL_CONN* conn, tLINK_POLICY policy) { - inc_func_call_count(__func__); - test::mock::stack_acl::btm_set_link_policy(conn, policy); -} void btm_set_packet_types_from_address(const RawAddress& bd_addr, uint16_t pkt_types) { inc_func_call_count(__func__); test::mock::stack_acl::btm_set_packet_types_from_address(bd_addr, pkt_types); } -void hci_btm_set_link_supervision_timeout(tACL_CONN& link, uint16_t timeout) { - inc_func_call_count(__func__); - test::mock::stack_acl::hci_btm_set_link_supervision_timeout(link, timeout); -} void btm_connection_request(const RawAddress& bda, const bluetooth::hci::ClassOfDevice& cod) { test::mock::stack_acl::btm_connection_request(bda, cod); } diff --git a/system/test/mock/mock_stack_acl.h b/system/test/mock/mock_stack_acl.h index a454f7ff3db..8e123f3f8c8 100644 --- a/system/test/mock/mock_stack_acl.h +++ b/system/test/mock/mock_stack_acl.h @@ -221,17 +221,6 @@ struct acl_set_peer_le_features_from_handle { bool operator()(uint16_t hci_handle, const uint8_t* p) { return body(hci_handle, p); } }; extern struct acl_set_peer_le_features_from_handle acl_set_peer_le_features_from_handle; -// Name: acl_get_connection_from_address -// Params: const RawAddress& bd_addr, tBT_TRANSPORT transport -// Returns: tACL_CONN* -struct acl_get_connection_from_address { - std::function body{ - [](const RawAddress& /* bd_addr */, tBT_TRANSPORT /* transport */) { return nullptr; }}; - tACL_CONN* operator()(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - return body(bd_addr, transport); - } -}; -extern struct acl_get_connection_from_address acl_get_connection_from_address; // Name: btm_acl_for_bda // Params: const RawAddress& bd_addr, tBT_TRANSPORT transport // Returns: tACL_CONN* @@ -243,14 +232,6 @@ struct btm_acl_for_bda { } }; extern struct btm_acl_for_bda btm_acl_for_bda; -// Name: acl_get_connection_from_handle -// Params: uint16_t handle -// Returns: tACL_CONN* -struct acl_get_connection_from_handle { - std::function body{[](uint16_t /* handle */) { return nullptr; }}; - tACL_CONN* operator()(uint16_t handle) { return body(handle); } -}; -extern struct acl_get_connection_from_handle acl_get_connection_from_handle; // Name: BTM_ReadFailedContactCounter // Params: const RawAddress& remote_bda, tBTM_CMPL_CB* p_cb // Returns: tBTM_STATUS @@ -578,27 +559,6 @@ struct btm_acl_role_changed { } }; extern struct btm_acl_role_changed btm_acl_role_changed; -// Name: btm_acl_update_conn_addr -// Params: uint16_t handle, const RawAddress& address -// Returns: void -struct btm_acl_update_conn_addr { - std::function body{ - [](uint16_t /* handle */, const RawAddress& /* address */) { ; }}; - void operator()(uint16_t handle, const RawAddress& address) { body(handle, address); } -}; -extern struct btm_acl_update_conn_addr btm_acl_update_conn_addr; -// Name: btm_ble_refresh_local_resolvable_private_addr -// Params: const RawAddress& pseudo_addr, const RawAddress& local_rpa -// Returns: void -struct btm_ble_refresh_local_resolvable_private_addr { - std::function body{ - [](const RawAddress& /* pseudo_addr */, const RawAddress& /* local_rpa */) { ; }}; - void operator()(const RawAddress& pseudo_addr, const RawAddress& local_rpa) { - body(pseudo_addr, local_rpa); - } -}; -extern struct btm_ble_refresh_local_resolvable_private_addr - btm_ble_refresh_local_resolvable_private_addr; // Name: btm_cont_rswitch_from_handle // Params: uint16_t hci_handle // Returns: void @@ -616,29 +576,6 @@ struct btm_establish_continue_from_address { void operator()(const RawAddress& bda, tBT_TRANSPORT transport) { body(bda, transport); } }; extern struct btm_establish_continue_from_address btm_establish_continue_from_address; -// Name: btm_process_remote_ext_features -// Params: tACL_CONN* p_acl_cb, uint8_t max_page_number -// Returns: void -struct btm_process_remote_ext_features { - std::function body{ - [](tACL_CONN* /* p_acl_cb */, uint8_t /* max_page_number */) { ; }}; - void operator()(tACL_CONN* p_acl_cb, uint8_t max_page_number) { body(p_acl_cb, max_page_number); } -}; -extern struct btm_process_remote_ext_features btm_process_remote_ext_features; -// Name: btm_process_remote_version_complete -// Params: uint8_t status, uint16_t handle, uint8_t lmp_version, uint16_t -// manufacturer, uint16_t lmp_subversion Returns: void -struct btm_process_remote_version_complete { - std::function - body{[](uint8_t /* status */, uint16_t /* handle */, uint8_t /* lmp_version */, - uint16_t /* manufacturer */, uint16_t /* lmp_subversion */) { ; }}; - void operator()(uint8_t status, uint16_t handle, uint8_t lmp_version, uint16_t manufacturer, - uint16_t lmp_subversion) { - body(status, handle, lmp_version, manufacturer, lmp_subversion); - } -}; -extern struct btm_process_remote_version_complete btm_process_remote_version_complete; // Name: btm_read_automatic_flush_timeout_complete // Params: uint8_t* p // Returns: void @@ -655,23 +592,6 @@ struct btm_read_failed_contact_counter_complete { void operator()(uint8_t* p) { body(p); } }; extern struct btm_read_failed_contact_counter_complete btm_read_failed_contact_counter_complete; -// Name: btm_read_failed_contact_counter_timeout -// Params: void* data -// Returns: void -struct btm_read_failed_contact_counter_timeout { - std::function body{[](void* /* data */) { ; }}; - void operator()(void* data) { body(data); } -}; -extern struct btm_read_failed_contact_counter_timeout btm_read_failed_contact_counter_timeout; -// Name: btm_read_remote_ext_features -// Params: uint16_t handle, uint8_t page_number -// Returns: void -struct btm_read_remote_ext_features { - std::function body{ - [](uint16_t /* handle */, uint8_t /* page_number */) { ; }}; - void operator()(uint16_t handle, uint8_t page_number) { body(handle, page_number); } -}; -extern struct btm_read_remote_ext_features btm_read_remote_ext_features; // Name: btm_read_remote_ext_features_complete // Params: uint16_t handle, uint8_t page_num, uint8_t max_page, uint8_t* // features Returns: void @@ -725,14 +645,6 @@ struct btm_read_rssi_complete { void operator()(uint8_t* p, uint16_t evt_len) { body(p, evt_len); } }; extern struct btm_read_rssi_complete btm_read_rssi_complete; -// Name: btm_read_rssi_timeout -// Params: void* data -// Returns: void -struct btm_read_rssi_timeout { - std::function body{[](void* /* data */) { ; }}; - void operator()(void* data) { body(data); } -}; -extern struct btm_read_rssi_timeout btm_read_rssi_timeout; // Name: btm_read_tx_power_complete // Params: uint8_t* p, bool is_ble // Returns: void @@ -742,14 +654,6 @@ struct btm_read_tx_power_complete { void operator()(uint8_t* p, uint16_t evt_len, bool is_ble) { body(p, evt_len, is_ble); } }; extern struct btm_read_tx_power_complete btm_read_tx_power_complete; -// Name: btm_read_tx_power_timeout -// Params: void* data -// Returns: void -struct btm_read_tx_power_timeout { - std::function body{[](void* /* data */) { ; }}; - void operator()(void* data) { body(data); } -}; -extern struct btm_read_tx_power_timeout btm_read_tx_power_timeout; // Name: btm_rejectlist_role_change_device // Params: const RawAddress& bd_addr, uint8_t hci_status // Returns: void @@ -759,15 +663,6 @@ struct btm_rejectlist_role_change_device { void operator()(const RawAddress& bd_addr, uint8_t hci_status) { body(bd_addr, hci_status); } }; extern struct btm_rejectlist_role_change_device btm_rejectlist_role_change_device; -// Name: btm_set_link_policy -// Params: tACL_CONN* conn, tLINK_POLICY policy -// Returns: void -struct btm_set_link_policy { - std::function body{ - [](tACL_CONN* /* conn */, tLINK_POLICY /* policy */) { ; }}; - void operator()(tACL_CONN* conn, tLINK_POLICY policy) { body(conn, policy); } -}; -extern struct btm_set_link_policy btm_set_link_policy; // Name: btm_set_packet_types_from_address // Params: const RawAddress& bd_addr, uint16_t pkt_types // Returns: void @@ -777,15 +672,6 @@ struct btm_set_packet_types_from_address { void operator()(const RawAddress& bd_addr, uint16_t pkt_types) { body(bd_addr, pkt_types); } }; extern struct btm_set_packet_types_from_address btm_set_packet_types_from_address; -// Name: hci_btm_set_link_supervision_timeout -// Params: tACL_CONN& link, uint16_t timeout -// Returns: void -struct hci_btm_set_link_supervision_timeout { - std::function body{ - [](tACL_CONN& /* link */, uint16_t /* timeout */) { ; }}; - void operator()(tACL_CONN& link, uint16_t timeout) { body(link, timeout); } -}; -extern struct hci_btm_set_link_supervision_timeout hci_btm_set_link_supervision_timeout; // Name: on_acl_br_edr_connected // Params: const RawAddress& bda, uint16_t handle, uint8_t enc_mode, bool // locally_initiated Returns: void diff --git a/system/test/mock/mock_stack_acl_ble.cc b/system/test/mock/mock_stack_acl_ble.cc index e403a923e3a..8f888dc17bf 100644 --- a/system/test/mock/mock_stack_acl_ble.cc +++ b/system/test/mock/mock_stack_acl_ble.cc @@ -21,15 +21,13 @@ #include +#include "stack/include/ble_acl_interface.h" #include "stack/include/hci_error_code.h" #include "test/common/mock_functions.h" #include "types/ble_address_with_type.h" #include "types/hci_role.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - void acl_ble_connection_fail(const tBLE_BD_ADDR& /* address_with_type */, uint16_t /* handle */, bool /* enhanced */, tHCI_STATUS /* status */) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_acl_btm_pm.cc b/system/test/mock/mock_stack_acl_btm_pm.cc index 8ae9f01c631..bc1d3de8954 100644 --- a/system/test/mock/mock_stack_acl_btm_pm.cc +++ b/system/test/mock/mock_stack_acl_btm_pm.cc @@ -22,13 +22,12 @@ #include #include "stack/btm/power_mode.h" +#include "stack/include/acl_api.h" +#include "stack/include/acl_hci_link_interface.h" #include "stack/include/btm_status.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - bool BTM_ReadPowerMode(const RawAddress& /* remote_bda */, tBTM_PM_MODE* /* p_mode */) { inc_func_call_count(__func__); return false; @@ -81,7 +80,3 @@ void btm_pm_proc_ssr_evt(uint8_t* /* p */, uint16_t /* evt_len */) { inc_func_call_count(__func__); } void btm_pm_reset(void) { inc_func_call_count(__func__); } -void process_ssr_event(tHCI_STATUS /* status */, uint16_t /* handle */, uint16_t /* max_tx_lat */, - uint16_t /* max_rx_lat */) { - inc_func_call_count(__func__); -} -- GitLab From b0fa765e3d11ea97601ac76872b523a248d8a417 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 30 Oct 2024 14:47:05 -0700 Subject: [PATCH 504/875] SystemServer: remove fast_bind_to_app Bug: 328698375 Flag: com.android.bluetooth.flags.fast_bind_to_app Test: m . | any test that turn on & off the Bluetooth Change-Id: I511123324f8eedbbe8ddcb886d6fc94e0d17775e --- .../bluetooth/btservice/AdapterService.java | 37 ++----------------- .../btservice/AdapterServiceTest.java | 8 +--- flags/system_service.aconfig | 7 ---- .../bluetooth/BluetoothManagerService.java | 13 +------ 4 files changed, 6 insertions(+), 59 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 961cb0d1bce..3c2ee4b80de 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -629,10 +629,6 @@ public class AdapterService extends Service { public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate()"); - if (!Flags.fastBindToApp()) { - init(); - return; - } // OnCreate must perform the minimum of infaillible and mandatory initialization mRemoteDevices = new RemoteDevices(this, mLooper); mAdapterProperties = new AdapterProperties(this, mRemoteDevices, mLooper); @@ -652,27 +648,10 @@ public class AdapterService extends Service { Config.init(this); mDeviceConfigListener.start(); - if (!Flags.fastBindToApp()) { - // Moved to OnCreate - mUserManager = getNonNullSystemService(UserManager.class); - mAppOps = getNonNullSystemService(AppOpsManager.class); - mPowerManager = getNonNullSystemService(PowerManager.class); - mBatteryStatsManager = getNonNullSystemService(BatteryStatsManager.class); - mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class); - mRemoteDevices = new RemoteDevices(this, mLooper); - } MetricsLogger.getInstance().init(this, mRemoteDevices); clearDiscoveringPackages(); - if (!Flags.fastBindToApp()) { - mBinder = new AdapterServiceBinder(this); - } mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (!Flags.fastBindToApp()) { - // Moved to OnCreate - mAdapterProperties = new AdapterProperties(this, mRemoteDevices, mLooper); - mAdapterStateMachine = new AdapterState(this, mLooper); - } boolean isCommonCriteriaMode = getNonNullSystemService(DevicePolicyManager.class) .isCommonCriteriaModeEnabled(null); @@ -719,11 +698,7 @@ public class AdapterService extends Service { "BluetoothQualityReportNativeInterface cannot be null when BQR starts"); mBluetoothQualityReportNativeInterface.init(); - if (Flags.fastBindToApp()) { - mSdpManager = new SdpManager(this, mLooper); - } else { - mSdpManager = new SdpManager(this); - } + mSdpManager = new SdpManager(this, mLooper); mDatabaseManager.start(MetadataDatabase.createDatabase(this)); @@ -765,10 +740,6 @@ public class AdapterService extends Service { mNativeInterface, mLooper, getSystemService(DisplayManager.class)); } - if (!Flags.fastBindToApp()) { - setAdapterService(this); - } - invalidateBluetoothCaches(); // First call to getSharedPreferences will result in a file read into @@ -4683,10 +4654,8 @@ public class AdapterService extends Service { Log.d(TAG, "offToBleOn() called when Bluetooth was disallowed"); return; } - if (Flags.fastBindToApp()) { - // The call to init must be done on the main thread - mHandler.post(() -> init()); - } + // The call to init must be done on the main thread + mHandler.post(() -> init()); Log.i(TAG, "offToBleOn() - Enable called with quiet mode status = " + quietMode); mQuietmode = quietMode; 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 f73e0f064e0..8a9cc0eae13 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 @@ -410,9 +410,7 @@ public class AdapterServiceTest { IBluetoothCallback callback, AdapterNativeInterface nativeInterface) { adapter.offToBleOn(false); - if (Flags.fastBindToApp()) { - TestUtils.syncHandler(looper, 0); // when fastBindToApp is enable init need to be run - } + TestUtils.syncHandler(looper, 0); // `init` need to be run first TestUtils.syncHandler(looper, AdapterState.BLE_TURN_ON); verifyStateChange(callback, STATE_OFF, STATE_BLE_TURNING_ON); @@ -625,9 +623,7 @@ public class AdapterServiceTest { assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); mAdapterService.offToBleOn(false); - if (Flags.fastBindToApp()) { - syncHandler(0); // when fastBindToApp is enable init need to be run - } + syncHandler(0); // `init` need to be run first syncHandler(AdapterState.BLE_TURN_ON); verifyStateChange(STATE_OFF, STATE_BLE_TURNING_ON); assertThat(mAdapterService.getBluetoothGatt()).isNotNull(); diff --git a/flags/system_service.aconfig b/flags/system_service.aconfig index 1c40504d979..3755c4f6166 100644 --- a/flags/system_service.aconfig +++ b/flags/system_service.aconfig @@ -21,13 +21,6 @@ flag { bug: "366273182" } -flag { - name: "fast_bind_to_app" - namespace: "bluetooth" - description: "Remove complexity and non necessary initialization when simply binding" - bug: "328698375" -} - flag { name: "get_state_from_system_server" namespace: "bluetooth" diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 709477e2eb4..35e0a61311f 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -1570,23 +1570,15 @@ class BluetoothManagerService { } } - // Register callback object try { mAdapter.registerCallback( mBluetoothCallback, mContext.getAttributionSource()); } catch (RemoteException e) { Log.e(TAG, "Unable to register BluetoothCallback", e); } - // Inform BluetoothAdapter instances that service is up - if (!Flags.fastBindToApp()) { - sendBluetoothServiceUpCallback(); - } - // Do enable request offToBleOn(); - if (Flags.fastBindToApp()) { - sendBluetoothServiceUpCallback(); - } + sendBluetoothServiceUpCallback(); if (!mEnable) { waitForState(STATE_ON); @@ -1892,9 +1884,6 @@ class BluetoothManagerService { private void handleEnable() { if (mAdapter == null && !isBinding()) { bindToAdapter(); - } else if (!Flags.fastBindToApp() && mAdapter != null) { - // Enable bluetooth - offToBleOn(); } } -- GitLab From 9237a1d09b14bfaaf110cfb07131a14a55834d86 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 30 Oct 2024 14:49:29 -0700 Subject: [PATCH 505/875] SystemServer: remove avoid_static_loading_of_native Bug: 339554081 Flag: com.android.bluetooth.flags.avoid_static_loading_of_native Test: m . | any test that turn on & off the Bluetooth Change-Id: I838a8a6574a48567e75c4e66b622bcabaf9c2203 --- .../bluetooth/btservice/AdapterService.java | 23 ++++--------------- flags/system_service.aconfig | 10 -------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 3c2ee4b80de..d1feef50d5c 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -369,17 +369,6 @@ public class AdapterService extends Service { } }; - static { - if (!Flags.avoidStaticLoadingOfNative()) { - Log.d(TAG, "Loading JNI Library"); - if (Utils.isInstrumentationTestMode()) { - Log.w(TAG, "App is instrumented. Skip loading the native"); - } else { - System.loadLibrary("bluetooth_jni"); - } - } - } - // Keep a constructor for ActivityThread.handleCreateService AdapterService() { this(Looper.getMainLooper()); @@ -669,13 +658,11 @@ public class AdapterService extends Service { getApplicationContext() .getPackageManager() .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY); - if (Flags.avoidStaticLoadingOfNative()) { - if (Utils.isInstrumentationTestMode()) { - Log.w(TAG, "This Bluetooth App is instrumented. ** Skip loading the native **"); - } else { - Log.d(TAG, "Loading JNI Library"); - System.loadLibrary("bluetooth_jni"); - } + if (Utils.isInstrumentationTestMode()) { + Log.w(TAG, "This Bluetooth App is instrumented. ** Skip loading the native **"); + } else { + Log.d(TAG, "Loading JNI Library"); + System.loadLibrary("bluetooth_jni"); } mNativeInterface.init( this, diff --git a/flags/system_service.aconfig b/flags/system_service.aconfig index 3755c4f6166..ab542121b9d 100644 --- a/flags/system_service.aconfig +++ b/flags/system_service.aconfig @@ -1,16 +1,6 @@ package: "com.android.bluetooth.flags" container: "com.android.btservices" -flag { - name: "avoid_static_loading_of_native" - namespace: "bluetooth" - description: "Prevent loading native during static initialization and prefer doing it during init" - metadata { - purpose: PURPOSE_BUGFIX - } - bug: "339554081" -} - flag { name: "enforce_resolve_system_service_behavior" namespace: "bluetooth" -- GitLab From 7f74d44cebf1cad4b3d7aa9b05236a41cb221e9e Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Wed, 30 Oct 2024 23:58:27 +0000 Subject: [PATCH 506/875] Fix incorrect logging in sdp_discovery In two locations in sdp_discovery.cc, log statements use structures that may, in exceptional cases, have been freed by preceding calls. This can lead to use after free and potentially to security vulnerabilities. Use local variables instead. Bug: 375408314 Bug: 375409435 Test: m libbluetooth Test: researcher POC Flag: EXEMPT trivial logic fix Ignore-AOSP-First: security Tag: #security Change-Id: I76e1ffa1fe463a5858d61d025447d855ff6b5b84 --- system/stack/sdp/sdp_discovery.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/stack/sdp/sdp_discovery.cc b/system/stack/sdp/sdp_discovery.cc index 2e5cd86da06..75cd5a7ea2a 100644 --- a/system/stack/sdp/sdp_discovery.cc +++ b/system/stack/sdp/sdp_discovery.cc @@ -183,7 +183,7 @@ static void sdp_snd_service_search_req(tCONN_CB* p_ccb, uint8_t cont_len, uint8_ if (stack::l2cap::get_interface().L2CA_DataWrite(p_ccb->connection_id, p_cmd) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_ccb->device_address, - p_ccb->connection_id, p_cmd->len); + p_ccb->connection_id, p - p_start); } /* Start inactivity timer */ @@ -711,7 +711,7 @@ static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, if (stack::l2cap::get_interface().L2CA_DataWrite(p_ccb->connection_id, p_msg) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_ccb->device_address, - p_ccb->connection_id, p_msg->len); + p_ccb->connection_id, p - p_start); } /* Start inactivity timer */ -- GitLab From d62bf15de2fb8161bab7067f6e8704452bd52460 Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Thu, 31 Oct 2024 00:05:16 +0000 Subject: [PATCH 507/875] Fix incorrect logging in sdp_server In the function process_service_search_attr_req of sdp_server.cc, a log statement uses a structure that may, in exceptional cases, have been freed by preceding calls. This can lead to use after free and potentially to security vulnerabilities. Use local variables instead. Bug: 375407167 Test: m libbluetooth Test: researcher POC Flag: EXEMPT trivial logic fix Ignore-AOSP-First: security Tag: #security Change-Id: I04a295f3c451267aaad0f0d22401b9f5b5510d83 --- system/stack/sdp/sdp_server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/stack/sdp/sdp_server.cc b/system/stack/sdp/sdp_server.cc index 58a17727cfa..0ebe890dd6a 100644 --- a/system/stack/sdp/sdp_server.cc +++ b/system/stack/sdp/sdp_server.cc @@ -924,7 +924,7 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, if (stack::l2cap::get_interface().L2CA_DataWrite(p_ccb->connection_id, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_ccb->device_address, - p_ccb->connection_id, p_buf->len); + p_ccb->connection_id, p_rsp - p_rsp_start); } } -- GitLab From 262d00f71f697f42c3f4ade3365cefd265b40828 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 30 Oct 2024 17:32:34 -0700 Subject: [PATCH 508/875] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ic6369ae32d56cd1f6d0f8aac611243edc497d61c --- android/app/res/values-bs/strings.xml | 2 +- android/app/res/values-sk/strings.xml | 2 +- android/app/res/values-sq/strings.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/app/res/values-bs/strings.xml b/android/app/res/values-bs/strings.xml index 9a3ba14c7fa..6a3e9f10bcc 100644 --- a/android/app/res/values-bs/strings.xml +++ b/android/app/res/values-bs/strings.xml @@ -117,7 +117,7 @@ "Bluetooth audio je isključen" "Bluetooth Audio" "Nije moguće prenijeti fajlove veće od 4 GB" - "Poveži se na Bluetooth" + "Poveži se s Bluetoothom" "Bluetooth je uključen u načinu rada u avionu" "Ako ostavite Bluetooth uključenim, uređaj će zapamtiti da treba biti uključen sljedeći put kada budete u načinu rada u avionu" "Bluetooth ostaje uključen" diff --git a/android/app/res/values-sk/strings.xml b/android/app/res/values-sk/strings.xml index b6a01f2eecd..6ce58ea4396 100644 --- a/android/app/res/values-sk/strings.xml +++ b/android/app/res/values-sk/strings.xml @@ -117,7 +117,7 @@ "Rozhranie Bluetooth Audio je odpojené" "Bluetooth Audio" "Súbory väčšie ako 4 GB sa nedajú preniesť" - "Pripojiť k zariadeniu Bluetooth" + "Pripojiť k rozhraniu Bluetooth" "Rozhranie Bluetooth bude v režime v lietadle zapnuté" "Ak ponecháte rozhranie Bluetooth zapnuté, vaše zariadenie si zapamätá, že ho má ponechať zapnuté pri ďalšom aktivovaní režimu v lietadle" "Rozhranie Bluetooth zostane zapnuté" diff --git a/android/app/res/values-sq/strings.xml b/android/app/res/values-sq/strings.xml index 50f94d2b88d..f86dd8bf497 100644 --- a/android/app/res/values-sq/strings.xml +++ b/android/app/res/values-sq/strings.xml @@ -16,12 +16,12 @@ - "Bluetooth" + "Bluetooth-i" "Qasu në menaxherin e shkarkimit." "Lejon aplikacionin të ketë qasje në menaxherin \"Shpërndarje përmes bluetooth-it\" (BluetoothShare) dhe ta përdorë për transferim skedarësh." "Autorizimi në listën e pranimit të pajisjes me Bluetooth." "Lejon aplikacionin të vërë përkohësisht në listën e miratimeve një pajisje me Bluetooth, duke i lejuar asaj t\'i dërgojë skedarë kësaj pajisjeje pa konfirmimin e përdoruesit." - "Bluetooth" + "Bluetooth-i" "Pajisje e panjohur" "I panjohur" "Nuk ofrohet" -- GitLab From a9ba7df78972ce42361a47f1816ac108abe71171 Mon Sep 17 00:00:00 2001 From: zhiweichen Date: Thu, 31 Oct 2024 03:30:33 +0000 Subject: [PATCH 509/875] BQR: Add Bluetooth Quality Report v7 feature - Controller health Monitor - Add Event Bitmask for health monitor stats. Bug: 376201850 Test: m libbtif-core Test Verified the BQR event for new added fields. Change-Id: I04a9f6079d4b51cc2ab0f1c6f5c507569f91456d --- system/btif/include/btif_bqr.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/btif/include/btif_bqr.h b/system/btif/include/btif_bqr.h index 71105ef9032..909335b4110 100644 --- a/system/btif/include/btif_bqr.h +++ b/system/btif/include/btif_bqr.h @@ -88,6 +88,8 @@ static constexpr uint32_t kQualityEventMaskLeAudioChoppy = 0x1 << 6; static constexpr uint32_t kQualityEventMaskConnectFail = 0x1 << 7; static constexpr uint32_t kQualityEventMaskAdvRFStatsEvent = 0x1 << 8; static constexpr uint32_t kQualityEventMaskAdvRFStatsMonitor = 0x1 << 9; +static constexpr uint32_t kQualityEventMaskHealthMonitorStatsEvent = 0x1 << 10; +static constexpr uint32_t kQualityEventMaskControllerHealthMonitor = 0x1 << 11; static constexpr uint32_t kQualityEventMaskVendorSpecificQuality = 0x1 << 15; static constexpr uint32_t kQualityEventMaskLmpMessageTrace = 0x1 << 16; static constexpr uint32_t kQualityEventMaskBtSchedulingTrace = 0x1 << 17; @@ -99,6 +101,7 @@ static constexpr uint32_t kQualityEventMaskAll = kQualityEventMaskRootInflammation | kQualityEventMaskEnergyMonitoring | kQualityEventMaskLeAudioChoppy | kQualityEventMaskConnectFail | kQualityEventMaskAdvRFStatsEvent | kQualityEventMaskAdvRFStatsMonitor | + kQualityEventMaskHealthMonitorStatsEvent | kQualityEventMaskControllerHealthMonitor | kQualityEventMaskVendorSpecificQuality | kQualityEventMaskLmpMessageTrace | kQualityEventMaskBtSchedulingTrace | kQualityEventMaskControllerDbgInfo | kQualityEventMaskVendorSpecificTrace; @@ -132,6 +135,7 @@ static constexpr uint8_t kLogDumpParamTotalLen = 3; static constexpr uint8_t kVersion5_0ParamsTotalLen = 7; // Added in BQR V6.0 static constexpr uint8_t kVersion6_0ParamsTotalLen = 6; + // Warning criteria of the RSSI value. static constexpr int8_t kCriWarnRssi = -80; // Warning criteria of the unused AFH channel count. @@ -176,7 +180,7 @@ static constexpr uint16_t kBqrVndLogVersion = 0x102; static constexpr uint16_t kBqrVersion5_0 = 0x103; // The REPORT_ACTION_QUERY and BQR_Report_interval starting v1.04(260) static constexpr uint16_t kBqrVersion6_0 = 0x104; - +static constexpr uint16_t kBqrVersion7_0 = 0x105; // Action definition // // Action to Add, Delete or Clear the reporting of quality event(s). -- GitLab From 9edacde0180f203a5f1116abb887e90b38173513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 28 Oct 2024 12:09:19 +0000 Subject: [PATCH 510/875] Pandora: add @match_description for IUT_SEND_WRITE_REQUEST in VCP Add @match_description to properly verify MMI's description and use it to determine action to take Test: atest pts-bot:VCP Bug: 376016632 Change-Id: I9db4b488590e2cd0fdc23e393e2f4d3568d3e512 --- android/pandora/mmi2grpc/mmi2grpc/vcp.py | 39 ++++++++++++------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/android/pandora/mmi2grpc/mmi2grpc/vcp.py b/android/pandora/mmi2grpc/mmi2grpc/vcp.py index fa869abbb66..95a1a068325 100644 --- a/android/pandora/mmi2grpc/mmi2grpc/vcp.py +++ b/android/pandora/mmi2grpc/mmi2grpc/vcp.py @@ -145,33 +145,32 @@ class VCPProxy(ProfileProxy): # After discovery Android subscribes by itself, after profile connection return "OK" - def IUT_SEND_WRITE_REQUEST(self, description: str, **kwargs): + @match_description + def IUT_SEND_WRITE_REQUEST(self, description: str, chr_name: str, op_code: str, **kwargs): r""" - Please send write request to handle 0xXXXX with following value. - Characteristic name: - Op Code: [X (0xXX)] Op code name - Change Counter: - Value: + Please send write request to handle 0x([0-9A-Fa-f]{4}) with following value. + (?P(Volume Control Point|Volume Offset Control Point)): + Op Code: (?P(()|(\[[0-9] \(0x0[0-9]\)\]\s([\w]*\s){1,3})))(.*) """ # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed) sleep(2) - if ("Set Absolute Volume" in description): - self.vcp.SetDeviceVolume(connection=self.connection, volume=42) - elif ("Unmute" in description): - # for now, there is no way to trigger this, and tests are skipped + if (chr_name == "Volume Control Point"): + if "Set Absolute Volume" in op_code: + self.vcp.SetDeviceVolume(connection=self.connection, volume=42) + elif ("Unmute" in op_code): + # for now, there is no way to trigger this, and tests are skipped + return "No" + elif ("" in op_code): + # Handles sending *any* OP Code on Volume Control Point + self.vcp.SetDeviceVolume(connection=self.connection, volume=42) + elif (chr_name == "Volume Offset Control Point"): + if ("Set Volume Offset" in op_code or + "" in op_code): + self.vcp.SetVolumeOffset(connection=self.connection, offset=42) + else: return "No" - elif ("Set Volume Offset" in description): - self.vcp.SetVolumeOffset(connection=self.connection, offset=42) - elif ("Volume Control Point" in description and - "Op Code: " in description): - # Handles sending *any* OP Code on Volume Control Point - self.vcp.SetDeviceVolume(connection=self.connection, volume=42) - elif ("Volume Offset Control Point" in description and - "Op Code: " in description): - self.vcp.SetVolumeOffset(connection=self.connection, offset=42) - return "OK" -- GitLab From 2e0d34a0150df0bf68527c55f941f0017880b96b Mon Sep 17 00:00:00 2001 From: Etienne Ruffieux Date: Thu, 31 Oct 2024 08:11:13 +0000 Subject: [PATCH 511/875] Add missing return in GetMediaPlayerListResponse There was a missing return in GetMediaPlayerListResponse resulting in two messages sent if no player was available (one with error code, the other with no error and empty players list). We should only return RANGE_OUT_OF_BOUNDS when it's the case. Bug: 328847183 Flag: exempt trivial Test: atest BluetoothInstrumentationTests Change-Id: I26637d4a310ba3b06c21d9d1d1f210351abd4f81 --- system/profile/avrcp/device.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index 76fb2f23193..aff640d6488 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -1364,6 +1364,7 @@ void Device::GetMediaPlayerListResponse(uint8_t label, std::shared_ptr Date: Tue, 29 Oct 2024 11:02:24 +0000 Subject: [PATCH 512/875] Handle active device when get the audio policy value from remote Bug: 359743806 Test: atest BluetoothInstrumentationTests:HeadsetStateMachineTest Flag: Exempt, trivial and obvious fix. Change-Id: Iaafeed6fad8d6b34e17cc344cab561766fda9ae0 --- .../com/android/bluetooth/hfp/HeadsetStateMachine.java | 9 +++++++++ .../android/bluetooth/hfp/HeadsetStateMachineTest.java | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java index 52cc028e9f7..c706e2cee70 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java @@ -2389,6 +2389,15 @@ class HeadsetStateMachine extends StateMachine { Log.d(TAG, "Processing command: " + atString); if (processAndroidAtSinkAudioPolicy(args, device)) { mNativeInterface.atResponseCode(device, HeadsetHalConstants.AT_RESPONSE_OK, 0); + if (getHfpCallAudioPolicy().getActiveDevicePolicyAfterConnection() + == BluetoothSinkAudioPolicy.POLICY_NOT_ALLOWED + && mDevice.equals(mHeadsetService.getActiveDevice())) { + Log.d( + TAG, + "Remove the active device because the active device policy after" + + " connection is not allowed"); + mHeadsetService.setActiveDevice(null); + } } else { Log.w(TAG, "Invalid SinkAudioPolicy parameters!"); mNativeInterface.atResponseCode( diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java index 34077ad0c1d..c82216a7c13 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java @@ -1923,6 +1923,14 @@ public class HeadsetStateMachineTest { .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); } + @Test + public void testCheckAndProcessAndroidAt_handleConnectingTimePolicyNotAllowed() { + when(mHeadsetService.getActiveDevice()).thenReturn(mTestDevice); + mHeadsetStateMachine.checkAndProcessAndroidAt( + "+ANDROID=SINKAUDIOPOLICY,0,2,2", mTestDevice); + verify(mHeadsetService).setActiveDevice(null); + } + @Test public void testCheckAndProcessAndroidAt_replyAndroidAtFeatureRequest() { // Commands that will be handled -- GitLab From f1accdda321b9f1c9a4c5bf3749c3ee89e8ff75c Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Thu, 31 Oct 2024 08:26:06 +0000 Subject: [PATCH 513/875] CS: Update defalut value of SyncAntennaSelection Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 369478354 Test: m com.android.btservice Change-Id: I4b3364b4c30836604e13f8306d85e96b35a82226 --- system/gd/hci/distance_measurement_manager.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 5dcd379647c..6caf6a46d6d 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -47,7 +47,8 @@ static constexpr uint16_t kIllegalConnectionHandle = 0xffff; static constexpr uint8_t kTxPowerNotAvailable = 0xfe; static constexpr int8_t kRSSIDropOffAt1M = 41; static constexpr uint8_t kCsMaxTxPower = 10; // 10 dBm -static constexpr CsSyncAntennaSelection kCsSyncAntennaSelection = CsSyncAntennaSelection::ANTENNA_2; +static constexpr CsSyncAntennaSelection kCsSyncAntennaSelection = + CsSyncAntennaSelection::ANTENNAS_IN_ORDER; static constexpr uint8_t kConfigId = 0x01; // Use 0x01 to create config and enable procedure static constexpr uint8_t kMinMainModeSteps = 0x02; static constexpr uint8_t kMaxMainModeSteps = 0x05; -- GitLab From 9f97e7bc51a4e744bc289342e349f212c57f2d78 Mon Sep 17 00:00:00 2001 From: Suqun Peng Date: Thu, 31 Oct 2024 17:50:55 +0800 Subject: [PATCH 514/875] AVRCP: Fix SET_ABSOLUTE_VOLUME label leak SetVolume() allocated a label, but not free it on VendorPacketHandler() Bug: 376616691 Change-Id: I3d6c49d0eab3bf2a91f95266686beba138799158 Test: m com.android.btservices --- system/profile/avrcp/device.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index 7c4b6b38889..797ad433b64 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -154,6 +154,7 @@ void Device::VendorPacketHandler(uint8_t label, std::shared_ptr pk // TODO (apanicke): Add a retry mechanism if the response has a // different volume than the one we set. For now, we don't care // about the response to this message. + active_labels_.erase(label); break; default: log::warn("{}: Unhandled Response: pdu={}", address_, pkt->GetCommandPdu()); -- GitLab From 773d3bfba2dc45116bc42f843a3a25d517809db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Y=C4=B1lmaz?= Date: Tue, 29 Oct 2024 08:22:27 +0000 Subject: [PATCH 515/875] For `scan_manager_refactor`, wait for the completion of `start_up_rust_module_async`. Bug: 313335632 Bug: 267361243 Bug: 327503826 Bug: 375476453 Bug: 356462170 Test: m com.android.btservices Change-Id: I4048ccb567864cd7b055794c050e0b9e292562d9 --- system/btif/include/stack_manager_t.h | 4 +++- system/btif/src/bluetooth.cc | 10 +++++++++- system/btif/src/stack_manager.cc | 10 ++++++---- system/test/mock/mock_bluetooth_interface.cc | 3 ++- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/system/btif/include/stack_manager_t.h b/system/btif/include/stack_manager_t.h index 0e7f00dfe2e..f319fff7a71 100644 --- a/system/btif/include/stack_manager_t.h +++ b/system/btif/include/stack_manager_t.h @@ -20,6 +20,8 @@ #include +#include + #include "core_callbacks.h" #include "osi/include/future.h" @@ -32,7 +34,7 @@ typedef struct { ProfileStopCallback); void (*shut_down_stack_async)(ProfileStopCallback); void (*clean_up_stack)(ProfileStopCallback); - void (*start_up_rust_module_async)(); + void (*start_up_rust_module_async)(std::promise promise); void (*shut_down_rust_module_async)(); bool (*get_stack_is_running)(void); diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 906a8bd732a..13c5328f51c 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -498,7 +498,15 @@ static int disable(void) { static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(&stop_profiles); } -static void start_rust_module(void) { stack_manager_get_interface()->start_up_rust_module_async(); } +static void start_rust_module(void) { + std::promise rust_up_promise; + auto rust_up_future = rust_up_promise.get_future(); + stack_manager_get_interface()->start_up_rust_module_async(std::move(rust_up_promise)); + auto status = rust_up_future.wait_for(std::chrono::milliseconds(1000)); + if (status != std::future_status::ready) { + log::error("Failed to wait for rust initialization in time. May lead to unpredictable crash"); + } +} static void stop_rust_module(void) { stack_manager_get_interface()->shut_down_rust_module_async(); } diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc index 93407fc08ca..ace7f8e7e2e 100644 --- a/system/btif/src/stack_manager.cc +++ b/system/btif/src/stack_manager.cc @@ -125,7 +125,7 @@ static void event_start_up_stack(bluetooth::core::CoreInterface* interface, ProfileStopCallback stopProfiles); static void event_shut_down_stack(ProfileStopCallback stopProfiles); static void event_clean_up_stack(std::promise promise, ProfileStopCallback stopProfiles); -static void event_start_up_rust_module(); +static void event_start_up_rust_module(std::promise promise); static void event_shut_down_rust_module(); static void event_signal_stack_up(void* context); @@ -183,8 +183,9 @@ static void clean_up_stack(ProfileStopCallback stopProfiles) { } } -static void start_up_rust_module_async() { - management_thread.DoInThread(FROM_HERE, base::BindOnce(event_start_up_rust_module)); +static void start_up_rust_module_async(std::promise promise) { + management_thread.DoInThread(FROM_HERE, + base::BindOnce(event_start_up_rust_module, std::move(promise))); } static void shut_down_rust_module_async() { @@ -391,9 +392,10 @@ static void event_shut_down_stack(ProfileStopCallback stopProfiles) { info("finished"); } -static void event_start_up_rust_module() { +static void event_start_up_rust_module(std::promise promise) { info("is bringing up the Rust module"); module_start_up(get_local_module(RUST_MODULE)); + promise.set_value(); info("finished"); } diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc index 8fb6163dba3..5937d4202a1 100644 --- a/system/test/mock/mock_bluetooth_interface.cc +++ b/system/test/mock/mock_bluetooth_interface.cc @@ -15,6 +15,7 @@ */ #include +#include #include "btif/include/stack_manager_t.h" #include "hardware/bluetooth.h" @@ -72,7 +73,7 @@ static void shut_down_stack_async(ProfileStopCallback /* stopProfiles */) {} static void clean_up_stack(ProfileStopCallback /* stopProfiles */) {} -static void start_up_rust_module_async() {} +static void start_up_rust_module_async(std::promise /* promise */) {} static void shut_down_rust_module_async() {} -- GitLab From cf71148256405446fc928e950bc0867bdf457188 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 31 Oct 2024 10:22:39 -0700 Subject: [PATCH 516/875] [MTK] [CONVERGENCE] [ALPS07745105] Fix SWT when switch codec [Detail] When switch codec, BT hal will calculate the elapsed time since last out_write to sleep. If don't set default value to last_write_time_us_, it may get a wrong time to sleep for a long time in out_write. It will cause Auidofinger work wrong. [Solution] Set default value to last_write_time_us_ Bug: 328847539 Fix: 328847539 Test: m com.android.btservices Flag: EXEMPT, minor bug fix Change-Id: I323586ab5fc207980f8c36b336d2ebc5b4c65b00 --- system/audio_bluetooth_hw/stream_apis.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/system/audio_bluetooth_hw/stream_apis.cc b/system/audio_bluetooth_hw/stream_apis.cc index 7b96f5aa51c..6854a61ff1b 100644 --- a/system/audio_bluetooth_hw/stream_apis.cc +++ b/system/audio_bluetooth_hw/stream_apis.cc @@ -775,6 +775,7 @@ int adev_open_output_stream(struct audio_hw_device* dev, audio_io_handle_t /*han out->frames_rendered_ = 0; out->frames_presented_ = 0; + out->last_write_time_us_ = 0; BluetoothStreamOut* out_ptr = out.release(); { -- GitLab From 91e0391c5eecfdefc91a59c38b6c851fd4659615 Mon Sep 17 00:00:00 2001 From: Bhakthavatsala Raghavendra Date: Wed, 16 Oct 2024 18:52:54 +0000 Subject: [PATCH 517/875] Trigger security procedure on l2cap connection request from remote Bug: 372305844 Bug: 376278485 Flag: com.android.bluetooth.flags.trigger_sec_proc_on_inc_access_req Test: mmm packages/module/Bluetooth Change-Id: I45aad0c9ce79f22a170aeafc23e19e0017535628 --- system/stack/btm/btm_sec.cc | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index e647715e40b..ea7efcb2c92 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -1566,22 +1566,27 @@ tBTM_STATUS btm_sec_l2cap_access_req_by_requirement(const RawAddress& bd_addr, "enc: x{:x}", p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED, p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED); - /* SM4, but we do not know for sure which level of security we need. - * as long as we have a link key, it's OK */ - if ((0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED)) || - (0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED))) { - rc = tBTM_STATUS::BTM_DELAY_CHECK; - /* - 2046 may report HCI_Encryption_Change and L2C Connection Request out of - sequence - because of data path issues. Delay this disconnect a little bit - */ - log::info("peer should have initiated security process by now (SM4 to SM4)"); - p_dev_rec->sec_rec.p_callback = p_callback; - p_dev_rec->sec_rec.classic_link = tSECURITY_STATE::DELAY_FOR_ENC; - (*p_callback)(bd_addr, transport, p_ref_data, rc); - return tBTM_STATUS::BTM_SUCCESS; + if (!com::android::bluetooth::flags::trigger_sec_proc_on_inc_access_req()) { + /* SM4, but we do not know for sure which level of security we need. + * as long as we have a link key, it's OK */ + if ((0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED)) || + (0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED))) { + rc = tBTM_STATUS::BTM_DELAY_CHECK; + /* + 2046 may report HCI_Encryption_Change and L2C Connection Request out of + sequence + because of data path issues. Delay this disconnect a little bit + */ + log::info("peer should have initiated security process by now (SM4 to SM4)"); + p_dev_rec->sec_rec.p_callback = p_callback; + p_dev_rec->sec_rec.classic_link = tSECURITY_STATE::DELAY_FOR_ENC; + (*p_callback)(bd_addr, transport, p_ref_data, rc); + + return tBTM_STATUS::BTM_SUCCESS; + } + } else { + log::debug("force fallthrough to trigger sec proceudure"); } } -- GitLab From 01852c343384584083185c99184533c6e401ecca Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 31 Oct 2024 15:20:39 -0700 Subject: [PATCH 518/875] Update baseline There is 1000 less lines that correspond to 102 less VisibleForTests being bypassed Bug: 311772251 Test: m . Flag: Exempt baseline update Change-Id: I7d52ebaa96f7679b96eab0aa5b23cc4dac4b0e8b --- android/app/lint-baseline.xml | 1438 ++++----------------------------- 1 file changed, 158 insertions(+), 1280 deletions(-) diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml index 1b2c4fed02e..c972c11b212 100644 --- a/android/app/lint-baseline.xml +++ b/android/app/lint-baseline.xml @@ -371,7 +371,7 @@ errorLine2=" ^"> @@ -382,7 +382,7 @@ errorLine2=" ^"> @@ -393,7 +393,7 @@ errorLine2=" ^"> @@ -448,7 +448,7 @@ errorLine2=" ^"> @@ -547,7 +547,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -558,7 +558,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -569,7 +569,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -580,7 +580,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -591,18 +591,18 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" sm.sendMessage(A2dpStateMachine.MESSAGE_STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -613,7 +613,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -624,7 +624,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -635,7 +635,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -646,7 +646,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -657,7 +657,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> @@ -668,7 +668,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -679,7 +679,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -690,7 +690,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -701,7 +701,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -942,1043 +942,86 @@ errorLine1=" mAvrcpController.onPlayStatusChanged(device, toPlaybackStateFromJni(playStatus));" errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="197" + column="26"/> + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleChangeFolderRsp(device, count);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="303" + column="26"/> + errorLine1=" mAvrcpController.handleSetBrowsedPlayerRsp(device, items, depth);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="310" + column="26"/> + errorLine1=" mAvrcpController.handleSetAddressedPlayerRsp(device, status);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="317" + column="26"/> + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.handleAddressedPlayerChanged(device, id);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="324" + column="26"/> + errorLine1=" mAvrcpController.handleNowPlayingContentChanged(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="330" + column="26"/> + message="This method should only be accessed from tests or within private scope" + errorLine1=" mAvrcpController.onAvailablePlayerChanged(device);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java" + line="336" + column="26"/> + errorLine1=" mDatabaseManager.setProfileConnectionPolicy(" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java" + line="1822" + column="34"/> @@ -4078,7 +3121,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -4089,7 +3132,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -4892,7 +3935,7 @@ errorLine2=" ~~~~~~~~"> @@ -4903,7 +3946,7 @@ errorLine2=" ~~~~~~~~~~"> @@ -4914,7 +3957,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -4925,7 +3968,7 @@ errorLine2=" ~~~~~~~~"> @@ -4936,7 +3979,7 @@ errorLine2=" ~~~~~~~~~~"> @@ -4947,7 +3990,7 @@ errorLine2=" ~~~~~~~~"> @@ -4958,7 +4001,7 @@ errorLine2=" ~~~~~~~~"> @@ -4969,7 +4012,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -4980,7 +4023,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -4991,7 +4034,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5002,7 +4045,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5013,7 +4056,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5024,7 +4067,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5035,7 +4078,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5046,7 +4089,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5057,7 +4100,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5068,7 +4111,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5079,7 +4122,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5090,7 +4133,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5101,7 +4144,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5112,7 +4155,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5123,7 +4166,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5134,7 +4177,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5145,7 +4188,7 @@ errorLine2=" ~~~~~~~~"> @@ -5156,7 +4199,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5167,7 +4210,7 @@ errorLine2=" ~~~~~~~~"> @@ -5178,7 +4221,7 @@ errorLine2=" ~~~~~~~~"> @@ -5189,7 +4232,7 @@ errorLine2=" ~~~~~~~~~~"> @@ -5200,7 +4243,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -5211,7 +4254,7 @@ errorLine2=" ~~~~~~~~"> @@ -5222,7 +4265,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -5585,7 +4628,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5596,7 +4639,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5607,7 +4650,7 @@ errorLine2=" ~~~~~~~"> @@ -5618,7 +4661,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -5629,7 +4672,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -5640,7 +4683,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -5651,7 +4694,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -5662,7 +4705,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -5673,7 +4716,7 @@ errorLine2=" ~~~~~~~~~"> @@ -5684,7 +4727,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -5695,7 +4738,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5706,7 +4749,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5717,7 +4760,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5728,18 +4771,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> - - - - @@ -5750,21 +4782,10 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> - - - - - - - - @@ -5805,7 +4815,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> @@ -5816,7 +4826,7 @@ errorLine2=" ~~~~~~~~"> @@ -5827,7 +4837,7 @@ errorLine2=" ~~~~~~~~~"> @@ -5838,32 +4848,10 @@ errorLine2=" ~~~~~~~~~~~~~~~"> - - - - - - - - - - - - @@ -5904,7 +4881,7 @@ errorLine2=" ~~~~~~~~~"> @@ -5915,7 +4892,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5926,7 +4903,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5937,7 +4914,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5948,7 +4925,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5959,7 +4936,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5970,7 +4947,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5981,7 +4958,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5992,7 +4969,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -6003,7 +4980,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -6014,7 +4991,7 @@ errorLine2=" ~~~~~~~~~~"> @@ -6025,7 +5002,7 @@ errorLine2=" ~~~~~~~~~~"> @@ -6036,7 +5013,7 @@ errorLine2=" ~~~~~~~~"> @@ -6047,7 +5024,7 @@ errorLine2=" ~~~~~~~~~"> @@ -6058,7 +5035,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -6069,7 +5046,7 @@ errorLine2=" ~~~~~~~~"> @@ -6080,21 +5057,10 @@ errorLine2=" ~~~~~~~~~"> - - - - @@ -6113,7 +5079,7 @@ errorLine2=" ~~~~~~~~~"> @@ -6124,7 +5090,7 @@ errorLine2=" ~~~~~~~~~"> @@ -6135,7 +5101,7 @@ errorLine2=" ~~~~~~~~~"> @@ -6392,28 +5358,6 @@ column="47"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + errorLine1=" sm.sendMessage(HearingAidStateMachine.MESSAGE_STACK_EVENT, stackEvent);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -6839,7 +5728,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -6850,7 +5739,7 @@ errorLine2=" ~~~~~"> @@ -6861,7 +5750,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> @@ -6872,7 +5761,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -6883,7 +5772,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> @@ -6894,7 +5783,7 @@ errorLine2=" ~~~~"> @@ -6905,7 +5794,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -6916,7 +5805,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -6927,7 +5816,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -6938,7 +5827,7 @@ errorLine2=" ~~~~~~~~~"> @@ -8027,21 +6916,10 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - @@ -8269,7 +7147,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -8280,7 +7158,7 @@ errorLine2=" ^"> -- GitLab From 1c2e1e43e663816b2f634c585809003a3711be06 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Thu, 31 Oct 2024 17:04:19 +0100 Subject: [PATCH 519/875] Add flag: sec_disconnect_on_le_key_missing Test: Pair with Fast Pair device, forget bond on it, then try pairing again Flag: com.android.bluetooth.flags.sec_disconnect_on_le_key_missing Bug: 376680866 Bug: 315241296 Test: mma -j32; Ignore-AOSP-First: security fix Change-Id: I059f381e7f594cf2cd4d4589b32dedb7590f9f1d --- flags/security.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/security.aconfig b/flags/security.aconfig index 26a7fefeb06..ce3f9d6b9eb 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -85,3 +85,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +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 + } +} \ No newline at end of file -- GitLab From b00fba0c7e2861daef2196916223b1465d7b00c7 Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Thu, 31 Oct 2024 20:02:02 +0800 Subject: [PATCH 520/875] floss: mgmt: Don't restart Floss if the index doesn't present If the index doesn't present then the start must fail. This patch only aims to decrease the crash amount, no user facing issue is fixed. Bug: 362366319 Tag: #floss Test: mmm packages/modules/Bluetooth Test: modprobe -r btusb # btadapterd is not restarted immediately modprobe btusb # btadapterd is then restarted Test: btclient -c 'adapter enable' && modprobe -r btusb # btadapterd is not restarted after timeout modprobe btusb # btadapterd is then restarted Flag: EXEMPT, Floss-only change Change-Id: Ie77fd55431c257308698d3b9a82673984bda2b8a --- .../gd/rust/linux/mgmt/src/state_machine.rs | 59 +++++++++++++------ 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/system/gd/rust/linux/mgmt/src/state_machine.rs b/system/gd/rust/linux/mgmt/src/state_machine.rs index 2df9e7c16ce..6e9a1c23701 100644 --- a/system/gd/rust/linux/mgmt/src/state_machine.rs +++ b/system/gd/rust/linux/mgmt/src/state_machine.rs @@ -1530,9 +1530,22 @@ impl StateMachineInternal { let restart_count = self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0); - // If we've restarted a number of times, attempt to use the reset mechanism instead - // of retrying a start. - if restart_count >= RESET_ON_RESTART_COUNT { + if !present { + // If the index doesn't present, we have nothing to do - We can't even trigger + // the hardware reset because the sysfs reset entry would disappear as well. + // After the index presents, we shall try restarting. + warn!( + "{} stopped unexpectedly. After {} restarts, index disappeared.", + hci, restart_count + ); + self.modify_state(hci, |s: &mut AdapterState| { + s.state = ProcessState::Off; + s.restart_count = 0; + }); + (ProcessState::Off, CommandTimeoutAction::CancelTimer) + } else if restart_count >= RESET_ON_RESTART_COUNT { + // If we've restarted a number of times, attempt to use the reset mechanism + // instead of retrying a start. warn!( "{} stopped unexpectedly. After {} restarts, trying a reset recovery.", hci, restart_count @@ -1599,12 +1612,26 @@ impl StateMachineInternal { let restart_count = self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0); - // If we've restarted a number of times, attempt to use the reset mechanism instead - // of retrying a start. - if restart_count >= RESET_ON_RESTART_COUNT { + if !present { + // If the index doesn't present, we have nothing to do - We can't even trigger + // the hardware reset because the sysfs reset entry would disappear as well. + // After the index presents, we shall try restarting. + warn!( + "{} timed out while starting. After {} restarts, index disappeared.", + hci, restart_count + ); + self.modify_state(hci, |s: &mut AdapterState| { + s.state = ProcessState::Off; + s.restart_count = 0; + }); + self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci)); + StateMachineTimeoutActions::Noop + } else if restart_count >= RESET_ON_RESTART_COUNT { + // If we've restarted a number of times, attempt to use the reset mechanism + // instead of retrying a start. warn!( - "{} timed out while starting (present={}). After {} restarts, trying a reset recovery.", - hci, present, restart_count + "{} timed out while starting. After {} restarts, trying a reset recovery.", + hci, restart_count ); // Reset the restart count since we're attempting a reset now. self.modify_state(hci, |s: &mut AdapterState| { @@ -1618,9 +1645,8 @@ impl StateMachineInternal { StateMachineTimeoutActions::Noop } else { warn!( - "{} timed out while starting (present={}), try restarting (attempt #{})", + "{} timed out while starting, try restarting (attempt #{})", hci, - present, restart_count + 1 ); self.modify_state(hci, |s: &mut AdapterState| { @@ -1934,12 +1960,10 @@ mod tests { assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn); }); - // Stopped with no presence should restart if config enabled. + // Stopped with no presence should not restart even if config enabled. tokio::runtime::Runtime::new().unwrap().block_on(async { let mut process_manager = MockProcessManager::new(); process_manager.expect_start(); - // Expect to start again. - process_manager.expect_start(); let mut state_machine = make_state_machine(process_manager); state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true); state_machine.set_config_enabled(DEFAULT_ADAPTER, true); @@ -1948,9 +1972,9 @@ mod tests { state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, false); assert_eq!( state_machine.action_on_bluetooth_stopped(DEFAULT_ADAPTER), - (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer) + (ProcessState::Off, CommandTimeoutAction::CancelTimer) ); - assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn); + assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off); }); // If floss was disabled and we see stopped, we shouldn't restart. @@ -2084,7 +2108,6 @@ mod tests { let mut process_manager = MockProcessManager::new(); process_manager.expect_start(); process_manager.expect_stop(); - process_manager.expect_start(); let mut state_machine = make_state_machine(process_manager); state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true); state_machine.set_config_enabled(DEFAULT_ADAPTER, true); @@ -2093,9 +2116,9 @@ mod tests { state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, false); assert_eq!( state_machine.action_on_command_timeout(DEFAULT_ADAPTER), - StateMachineTimeoutActions::RetryStart + StateMachineTimeoutActions::Noop ); - assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn); + assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off); }); } -- GitLab From 2677bba3c1d8dcc1dfaa3be07523264b29e00776 Mon Sep 17 00:00:00 2001 From: Eric Shih Date: Wed, 30 Oct 2024 04:14:04 +0000 Subject: [PATCH 521/875] Fix not fallback to LE Audio when HFP removed active device If the device connects to an LE audio device and HFP device, when the HFP active device is set to null, the ActvieDeviceManager should try to fallback to the LE Audio device. Bug: 359743806 Test: atest BluetoothInstrumentationTests Flag: Exempt, trivial and obvious fix. Change-Id: I7e42f9788ee53914fd010b09b745ae37c4921db5 --- .../btservice/ActiveDeviceManager.java | 15 +++++++++++++++ .../btservice/ActiveDeviceManagerTest.java | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java index 9b926f13069..bef847cacde 100644 --- a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +++ b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java @@ -688,6 +688,14 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac if (device != null) { // remove LE audio active device when it is not null, and not dual mode setLeAudioActiveDevice(null, true); + } else { + Log.d( + TAG, + "HFP active device is null. Try to fallback to le audio active" + + " device"); + synchronized (mLock) { + setFallbackDeviceActiveLocked(device); + } } } } @@ -782,6 +790,13 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac mLeHearingAidActiveDevice = device; } + if (device == null && !Utils.isDualModeAudioEnabled()) { + Log.d(TAG, "LE audio active device is null. Try to fallback to hfp active device."); + synchronized (mLock) { + setFallbackDeviceActiveLocked(device); + } + } + mLeAudioActiveDevice = device; } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index b50835e74aa..2f02fad1c4a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -377,6 +377,24 @@ public class ActiveDeviceManagerTest { verify(mHeadsetService).setActiveDevice(mHeadsetDevice); } + @Test + public void headsetRemoveActive_fallbackToLeAudio() { + when(mHeadsetService.getFallbackDevice()).thenReturn(mHeadsetDevice); + + leAudioConnected(mLeAudioDevice); + mTestLooper.dispatchAll(); + verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice); + + headsetConnected(mHeadsetDevice, false); + mTestLooper.dispatchAll(); + verify(mHeadsetService).setActiveDevice(mHeadsetDevice); + + // HFP activce device to null. Expect to fallback to LeAudio. + headsetActiveDeviceChanged(null); + mTestLooper.dispatchAll(); + verify(mLeAudioService, times(2)).setActiveDevice(mLeAudioDevice); + } + @Test public void a2dpConnectedButHeadsetNotConnected_setA2dpActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); -- GitLab From 0899441766319cabe0f8c0f9fb875f84d25a63ec Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Fri, 1 Nov 2024 12:17:20 +0800 Subject: [PATCH 522/875] floss: mgmt: Wait until btadapterd completely stopped before restart It's common to see btmanagerd is trying to restart btadapterd but actually nothing happens, because the restart could be rejected by upstart if btadapterd process is still alive (btmanagerd considers it as stopped as soon as the pid file is removed, which is a bit earlier than upstart). Wait until btadapterd is completely stopped to avoid a redundant wait. Also revise the NativeInvoker to match the new definition of the ProcessManager API. For systemd and upstart invokers, comment is updated and no behavior change. Bug: 374017641 Tag: #floss Test: mmm packages/modules/Bluetooth Test: modprobe -r btusb; modprobe btusb # btmanagerd waits for btadapterd to completely stop, and then restarts it. Flag: EXEMPT, Floss-only change Change-Id: I99192d3db64cd7ae29726425ae1c4315ef738514 --- .../gd/rust/linux/mgmt/src/state_machine.rs | 102 ++++++++++-------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/system/gd/rust/linux/mgmt/src/state_machine.rs b/system/gd/rust/linux/mgmt/src/state_machine.rs index 6e9a1c23701..be4b7965fa9 100644 --- a/system/gd/rust/linux/mgmt/src/state_machine.rs +++ b/system/gd/rust/linux/mgmt/src/state_machine.rs @@ -946,6 +946,9 @@ pub trait ProcessManager { /// Stop the adapter process. /// + /// This should block the thread until the btadapterd process is completely stopped, + /// that is, another btadapterd process with the same index is ready to be |start|. + /// /// # Args /// * `virtual_hci` - Virtual index of adapter used for apis. /// * `real_hci` - Real index of the adapter on the system. @@ -961,8 +964,7 @@ pub enum Invoker { #[derive(Default)] pub struct NativeInvoker { - process_container: Option, - bluetooth_pid: u32, + process_container: HashMap, } impl NativeInvoker { @@ -973,23 +975,28 @@ impl NativeInvoker { impl ProcessManager for NativeInvoker { fn start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) { - let new_process = Command::new("/usr/bin/btadapterd") + if self.process_container.contains_key(&virtual_hci) { + return; + } + match Command::new("/usr/bin/btadapterd") .arg(format!("INDEX={} HCI={}", virtual_hci.to_i32(), real_hci.to_i32())) .stdout(Stdio::piped()) .spawn() - .expect("cannot open"); - self.bluetooth_pid = new_process.id(); - self.process_container = Some(new_process); - } - fn stop(&mut self, _virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex) { - match self.process_container { - Some(ref mut _p) => { - signal::kill(Pid::from_raw(self.bluetooth_pid as i32), Signal::SIGTERM).unwrap(); - self.process_container = None; + { + Ok(p) => { + self.process_container.insert(virtual_hci, p); } - None => { - warn!("Process doesn't exist"); + Err(e) => error!("Failed to start btadapterd: {}", e), + } + } + fn stop(&mut self, virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex) { + if let Some(mut p) = self.process_container.remove(&virtual_hci) { + if let Err(e) = signal::kill(Pid::from_raw(p.id() as i32), Signal::SIGTERM) { + warn!("Failed to send signal, process could have exited: {}", e); } + let _ = p.wait(); + } else { + warn!("Process doesn't exist"); } } } @@ -1018,14 +1025,14 @@ impl ProcessManager for UpstartInvoker { } } - fn stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) { + fn stop(&mut self, virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex) { + // Currently in the upstart script, only INDEX is used for identifying the instance. Thus, + // intentionally NOT passing HCI to upstart, to avoid the following confusing situation: + // 1. UpstartInvoker: start btadapterd INDEX=0 HCI=0 + // 2. Kernel: The HCI0 crashed, and became HCI1 + // 3. UpstartInvoker: stop btadapterd INDEX=0 HCI=1 <---- This is confusing if let Err(e) = Command::new("initctl") - .args([ - "stop", - "btadapterd", - format!("INDEX={}", virtual_hci.to_i32()).as_str(), - format!("HCI={}", real_hci.to_i32()).as_str(), - ]) + .args(["stop", "btadapterd", format!("INDEX={}", virtual_hci.to_i32()).as_str()]) .output() { error!("Failed to stop btadapterd: {}", e); @@ -1055,6 +1062,9 @@ impl ProcessManager for SystemdInvoker { } fn stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) { + // FIXME(b/307625503): If the real index changed (could be caused by FW crash or USB issues) + // then this function would be broken. Need a re-design of the virtual/real index management + // that is compatible other invokers. Command::new("systemctl") .args([ "stop", @@ -1530,14 +1540,20 @@ impl StateMachineInternal { let restart_count = self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0); + // This is an unexpectedly stop, which means the ProcessManager might not yet be + // ready to restart the same instance. Explicitly call stop to make sure we can move + // on to the next step. + warn!( + "{} stopped unexpectedly, first wait for the process to completely exit.", + hci + ); + self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci)); + if !present { // If the index doesn't present, we have nothing to do - We can't even trigger // the hardware reset because the sysfs reset entry would disappear as well. // After the index presents, we shall try restarting. - warn!( - "{} stopped unexpectedly. After {} restarts, index disappeared.", - hci, restart_count - ); + warn!("{} exited. After {} restarts, index disappeared.", hci, restart_count); self.modify_state(hci, |s: &mut AdapterState| { s.state = ProcessState::Off; s.restart_count = 0; @@ -1547,7 +1563,7 @@ impl StateMachineInternal { // If we've restarted a number of times, attempt to use the reset mechanism // instead of retrying a start. warn!( - "{} stopped unexpectedly. After {} restarts, trying a reset recovery.", + "{} exited. After {} restarts, trying a reset recovery.", hci, restart_count ); // Reset the restart count since we're attempting a reset now. @@ -1561,11 +1577,7 @@ impl StateMachineInternal { self.reset_hci(real_hci); (ProcessState::Off, CommandTimeoutAction::CancelTimer) } else { - warn!( - "{} stopped unexpectedly, try restarting (attempt #{})", - hci, - restart_count + 1 - ); + warn!("{} exited. Try restarting (attempt #{})", hci, restart_count + 1); self.modify_state(hci, |s: &mut AdapterState| { s.state = ProcessState::TurningOn; s.restart_count += 1; @@ -1612,25 +1624,29 @@ impl StateMachineInternal { let restart_count = self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0); + // Explicitly call stop to make sure the ProcessManager is ready to restart the + // same instance. + warn!( + "{} timed out while starting, first wait for the process to completely exit.", + hci + ); + self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci)); + if !present { // If the index doesn't present, we have nothing to do - We can't even trigger // the hardware reset because the sysfs reset entry would disappear as well. // After the index presents, we shall try restarting. - warn!( - "{} timed out while starting. After {} restarts, index disappeared.", - hci, restart_count - ); + warn!("{} exited. After {} restarts, index disappeared.", hci, restart_count); self.modify_state(hci, |s: &mut AdapterState| { s.state = ProcessState::Off; s.restart_count = 0; }); - self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci)); StateMachineTimeoutActions::Noop } else if restart_count >= RESET_ON_RESTART_COUNT { // If we've restarted a number of times, attempt to use the reset mechanism // instead of retrying a start. warn!( - "{} timed out while starting. After {} restarts, trying a reset recovery.", + "{} exited. After {} restarts, trying a reset recovery.", hci, restart_count ); // Reset the restart count since we're attempting a reset now. @@ -1644,16 +1660,11 @@ impl StateMachineInternal { self.reset_hci(real_hci); StateMachineTimeoutActions::Noop } else { - warn!( - "{} timed out while starting, try restarting (attempt #{})", - hci, - restart_count + 1 - ); + warn!("{} exited. Try restarting (attempt #{})", hci, restart_count + 1); self.modify_state(hci, |s: &mut AdapterState| { s.state = ProcessState::TurningOn; s.restart_count += 1; }); - self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci)); self.process_manager.start(hci, self.get_real_hci_by_virtual_id(hci)); StateMachineTimeoutActions::RetryStart } @@ -1946,7 +1957,8 @@ mod tests { tokio::runtime::Runtime::new().unwrap().block_on(async { let mut process_manager = MockProcessManager::new(); process_manager.expect_start(); - // Expect to start again + // Expect to wait for stopped and start again + process_manager.expect_stop(); process_manager.expect_start(); let mut state_machine = make_state_machine(process_manager); state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true); @@ -1964,6 +1976,8 @@ mod tests { tokio::runtime::Runtime::new().unwrap().block_on(async { let mut process_manager = MockProcessManager::new(); process_manager.expect_start(); + // Expect to wait for stopped + process_manager.expect_stop(); let mut state_machine = make_state_machine(process_manager); state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true); state_machine.set_config_enabled(DEFAULT_ADAPTER, true); -- GitLab From 9fd6f2a72136d9694a38e4ef4a7d07bba2745408 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Fri, 1 Nov 2024 14:30:22 +0000 Subject: [PATCH 523/875] CS: Allow partial complete procedure for ranging Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 376813431 Test: m com.android.btservice Change-Id: I5a62db759d8c30f0f0edf5d0cb4a3abe1217896d --- system/gd/hci/distance_measurement_manager.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 6caf6a46d6d..2fe3531812c 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -130,8 +130,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { bool contains_sounding_sequence_remote_; CsProcedureDoneStatus local_status; CsProcedureDoneStatus remote_status; - // If the procedure is aborted by either the local or remote side. - bool aborted = false; + // If any subevent is received with a Subevent_Done_Status of 0x0 (All results complete for the + // CS subevent) + bool contains_complete_subevent_ = false; // RAS data SegmentationHeader segmentation_header_; RangingHeader ranging_header_; @@ -1122,12 +1123,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } procedure_data->ras_subevent_header_.num_steps_reported_ += result_data_structures.size(); + if (subevent_done_status == CsSubeventDoneStatus::ALL_RESULTS_COMPLETE) { + procedure_data->contains_complete_subevent_ = true; + } if (procedure_abort_reason != ProcedureAbortReason::NO_ABORT || subevent_abort_reason != SubeventAbortReason::NO_ABORT) { // Even the procedure is aborted, we should keep following process and // handle it when all corresponding remote data received. - procedure_data->aborted = true; procedure_data->ras_subevent_header_.ranging_abort_reason_ = static_cast(procedure_abort_reason); procedure_data->ras_subevent_header_.subevent_abort_reason_ = @@ -1664,7 +1667,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (live_tracker->local_start && procedure_data->local_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE && procedure_data->remote_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE && - !procedure_data->aborted) { + procedure_data->contains_complete_subevent_) { log::debug("Procedure complete counter:{} data size:{}, main_mode_type:{}, sub_mode_type:{}", (uint16_t)procedure_data->counter, (uint16_t)procedure_data->step_channel.size(), (uint16_t)live_tracker->main_mode_type, (uint16_t)live_tracker->sub_mode_type); -- GitLab From 86084a632473354fb3d865ea865d5de435532f56 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 1 Nov 2024 15:43:06 +0000 Subject: [PATCH 524/875] Delete the procedure data correctly. CS: Parsing the CS procedure data of mode 1 Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 376859759 Test: m com.android.btservice Change-Id: I51f3014bf49ce98fedea4f06b2185211e9be3e04 --- system/gd/hci/distance_measurement_manager.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 5dcd379647c..24dec3f546b 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -1684,7 +1684,6 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { raw_data.packet_quality_initiator = procedure_data->packet_quality_initiator; raw_data.packet_quality_reflector = procedure_data->packet_quality_reflector; ranging_hal_->WriteRawData(connection_handle, raw_data); - return; } } -- GitLab From 0ea25cb03d9efffa9e396cace7670c85244d438d Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 1 Nov 2024 15:55:03 +0000 Subject: [PATCH 525/875] Add function to get the HAL version. Flag: com.android.bluetooth.flags.channel_sounding_25q2_apis Bug: 367409858 Bug: 357090692 Test: m com.android.btservices Change-Id: I27d5d7fa38ed2f78c94ffa6af1c1655870c1789d --- system/gd/hal/ranging_hal.h | 6 ++++++ system/gd/hal/ranging_hal_android.cc | 17 +++++++++++++++++ system/gd/hal/ranging_hal_host.cc | 1 + 3 files changed, 24 insertions(+) diff --git a/system/gd/hal/ranging_hal.h b/system/gd/hal/ranging_hal.h index 981f16b00b4..40afe0bbc91 100644 --- a/system/gd/hal/ranging_hal.h +++ b/system/gd/hal/ranging_hal.h @@ -23,6 +23,12 @@ namespace bluetooth { namespace hal { +enum RangingHalVersion { + V_UNKNOWN = 0, + V_1 = 1, + V_2 = 2, +}; + struct VendorSpecificCharacteristic { std::array characteristicUuid_; std::vector value_; diff --git a/system/gd/hal/ranging_hal_android.cc b/system/gd/hal/ranging_hal_android.cc index c50ee18c76f..c24a40ca314 100644 --- a/system/gd/hal/ranging_hal_android.cc +++ b/system/gd/hal/ranging_hal_android.cc @@ -109,6 +109,8 @@ class RangingHalAndroid : public RangingHal { public: bool IsBound() override { return bluetooth_channel_sounding_ != nullptr; } + RangingHalVersion GetRangingHalVersion() { return hal_ver_; } + void RegisterCallback(RangingHalCallback* callback) { ranging_hal_callback_ = callback; } std::vector GetVendorSpecificCharacteristics() override { @@ -248,6 +250,17 @@ public: protected: void ListDependencies(ModuleList* /*list*/) const {} + RangingHalVersion get_ranging_hal_version() { + int ver = 0; + auto aidl_ret = bluetooth_channel_sounding_->getInterfaceVersion(&ver); + if (aidl_ret.isOk()) { + log::info("ranging HAL version - {}", ver); + return static_cast(ver); + } + log::warn("ranging HAL version is not available."); + return RangingHalVersion::V_UNKNOWN; + } + void Start() override { std::string instance = std::string() + IBluetoothChannelSounding::descriptor + "/default"; log::info("AServiceManager_isDeclared {}", AServiceManager_isDeclared(instance.c_str())); @@ -255,6 +268,9 @@ protected: ::ndk::SpAIBinder binder(AServiceManager_waitForService(instance.c_str())); bluetooth_channel_sounding_ = IBluetoothChannelSounding::fromBinder(binder); log::info("Bind IBluetoothChannelSounding {}", IsBound() ? "Success" : "Fail"); + if (bluetooth_channel_sounding_ != nullptr) { + hal_ver_ = get_ranging_hal_version(); + } } } @@ -267,6 +283,7 @@ private: RangingHalCallback* ranging_hal_callback_; std::unordered_map> session_trackers_; + RangingHalVersion hal_ver_; }; const ModuleFactory RangingHal::Factory = ModuleFactory([]() { return new RangingHalAndroid(); }); diff --git a/system/gd/hal/ranging_hal_host.cc b/system/gd/hal/ranging_hal_host.cc index 36c821f419e..b11d20dd654 100644 --- a/system/gd/hal/ranging_hal_host.cc +++ b/system/gd/hal/ranging_hal_host.cc @@ -27,6 +27,7 @@ namespace hal { class RangingHalHost : public RangingHal { public: bool IsBound() override { return false; } + RangingHalVersion GetRangingHalVersion() { return V_UNKNOWN; } void RegisterCallback(RangingHalCallback* /* callback */) override {} std::vector GetVendorSpecificCharacteristics() override { std::vector vendor_specific_characteristics = {}; -- GitLab From d2d8fa18f188f35d851592da3aa6f1ce5b1f1ec9 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 1 Nov 2024 11:35:33 -0700 Subject: [PATCH 526/875] Adapter: re-order init to prevent null exception As soon as the callback are registered, the adapter can be notified. There is a thin possibility that the bluetooth is being started at the same time which would result in the callback being called before the initialization is completed. Since the initialization is only creating local variable except for the registration, moving the registration to be the last init action would solve this. Note that this require a very fast callback call and a very slow init altogether with a precise timing. None of that are expect on a normal journey Bug: 376735216 Fix: 376735216 Test: m . Flag: Exempt, trivial fix Change-Id: I6029fb30a7c4bf3be6d10b743684b6bbc41b5cb1 --- .../android/bluetooth/BluetoothAdapter.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 3477bed73f4..ebbe97566d9 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -1092,12 +1092,6 @@ public final class BluetoothAdapter { BluetoothAdapter(IBluetoothManager managerService, AttributionSource attributionSource) { mManagerService = requireNonNull(managerService); mAttributionSource = requireNonNull(attributionSource); - mServiceLock.writeLock().lock(); - try { - mService = getBluetoothService(mManagerCallback); - } finally { - mServiceLock.writeLock().unlock(); - } Consumer registerQualityReportCallbackConsumer = (IBluetooth service) -> { @@ -1165,6 +1159,13 @@ public final class BluetoothAdapter { new CallbackWrapper( registerBluetoothConnectionCallbackConsumer, unregisterBluetoothConnectionCallbackConsumer); + + mServiceLock.writeLock().lock(); + try { + mService = registerBlueoothManagerCallback(mManagerCallback); + } finally { + mServiceLock.writeLock().unlock(); + } } /** @@ -4211,15 +4212,8 @@ public final class BluetoothAdapter { } } - /** - * Registers a IBluetoothManagerCallback and returns the cached Bluetooth service proxy object. - * - *

    TODO: rename this API to registerBlueoothManagerCallback or something? the current name - * does not match what it does very well. - * - *

    / @UnsupportedAppUsage /*package - */ - IBluetooth getBluetoothService(IBluetoothManagerCallback cb) { + /** Registers a IBluetoothManagerCallback and returns the cached service proxy object. */ + IBluetooth registerBlueoothManagerCallback(IBluetoothManagerCallback cb) { requireNonNull(cb); if (Flags.getProfileUseLock()) { sServiceLock.writeLock().lock(); -- GitLab From eb64c56bb946e4634213b34d113f91de41c32851 Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 11 Oct 2024 17:31:51 -0700 Subject: [PATCH 527/875] AICS: add aidl definition AudioInputType is a bluetooth generic definition. Status/GainMode/Mute are aics specific Bug: 372328699 Flag: com.android.bluetooth.flags.aics_api Test: m Bluetooth Change-Id: I3f309b15c6a830a41fde03dd5c4e9f85fd757913 --- android/app/Android.bp | 3 ++ common/Android.bp | 14 ++++++++ common/OWNERS | 1 + .../bluetooth/constants/AudioInputType.aidl | 34 +++++++++++++++++++ .../constants/aics/AudioInputStatus.aidl | 29 ++++++++++++++++ common/bluetooth/constants/aics/GainMode.aidl | 30 ++++++++++++++++ common/bluetooth/constants/aics/Mute.aidl | 29 ++++++++++++++++ system/bta/Android.bp | 4 +++ system/btif/Android.bp | 10 ++++++ 9 files changed, 154 insertions(+) create mode 100644 common/Android.bp create mode 100644 common/OWNERS create mode 100644 common/bluetooth/constants/AudioInputType.aidl create mode 100644 common/bluetooth/constants/aics/AudioInputStatus.aidl create mode 100644 common/bluetooth/constants/aics/GainMode.aidl create mode 100644 common/bluetooth/constants/aics/Mute.aidl diff --git a/android/app/Android.bp b/android/app/Android.bp index 2bac3ba017a..2efc47100aa 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -73,6 +73,9 @@ cc_library_shared { "jni_headers", "libbluetooth_headers", ], + aidl: { + libs: ["bluetooth_constants"], + }, include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", diff --git a/common/Android.bp b/common/Android.bp new file mode 100644 index 00000000000..9afdd9dcfc7 --- /dev/null +++ b/common/Android.bp @@ -0,0 +1,14 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +aidl_library { + name: "bluetooth_constants", + srcs: [ + "bluetooth/constants/AudioInputType.aidl", + "bluetooth/constants/aics/AudioInputStatus.aidl", + "bluetooth/constants/aics/GainMode.aidl", + "bluetooth/constants/aics/Mute.aidl", + ], + visibility: ["//packages/modules/Bluetooth:__subpackages__"], +} diff --git a/common/OWNERS b/common/OWNERS new file mode 100644 index 00000000000..5b3f4bad26b --- /dev/null +++ b/common/OWNERS @@ -0,0 +1 @@ +wescande@google.com diff --git a/common/bluetooth/constants/AudioInputType.aidl b/common/bluetooth/constants/AudioInputType.aidl new file mode 100644 index 00000000000..2dfef1e7c3f --- /dev/null +++ b/common/bluetooth/constants/AudioInputType.aidl @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package bluetooth.constants; + +/** + * See Bluetooth SIG Assigned Numbers 6.12.2 Audio Input Type Definitions + * {@hide} + */ +@JavaDerive(toString = true) +@Backing(type="int") +enum AudioInputType { + UNSPECIFIED = 0x00, + BLUETOOTH = 0x01, + MICROPHONE = 0x02, + ANALOG = 0x03, + DIGITAL = 0x04, + RADIO = 0x05, + STREAMING = 0x06, + AMBIENT = 0x07, +} diff --git a/common/bluetooth/constants/aics/AudioInputStatus.aidl b/common/bluetooth/constants/aics/AudioInputStatus.aidl new file mode 100644 index 00000000000..b217e65e45a --- /dev/null +++ b/common/bluetooth/constants/aics/AudioInputStatus.aidl @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package bluetooth.constants.aics; + +/** + * See Audio Input Control Service 1.0 - 3.4 Audio Input Status + * {@hide} + */ +@JavaDerive(toString = true) +@Backing(type="byte") +enum AudioInputStatus { + INACTIVE = 0x00, + ACTIVE = 0x01, + // RFU 0x02 - 0xFF +} diff --git a/common/bluetooth/constants/aics/GainMode.aidl b/common/bluetooth/constants/aics/GainMode.aidl new file mode 100644 index 00000000000..97405e75d11 --- /dev/null +++ b/common/bluetooth/constants/aics/GainMode.aidl @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package bluetooth.constants.aics; + +/** + * See Audio Input Control Service 1.0 - 2.2.1.3. Gain_Mode field + * {@hide} + */ +@JavaDerive(toString = true) +@Backing(type="byte") +enum GainMode { + MANUAL_ONLY = 0x00, + AUTOMATIC_ONLY = 0x01, + MANUAL = 0x02, + AUTOMATIC = 0x03, +} diff --git a/common/bluetooth/constants/aics/Mute.aidl b/common/bluetooth/constants/aics/Mute.aidl new file mode 100644 index 00000000000..ce2af50ff2e --- /dev/null +++ b/common/bluetooth/constants/aics/Mute.aidl @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package bluetooth.constants.aics; + +/** + * See Audio Input Control Service 1.0 - 2.2.1.2. Mute field + * {@hide} + */ +@JavaDerive(toString = true) +@Backing(type="byte") +enum Mute { + NOT_MUTED = 0x00, + MUTED = 0x01, + DISABLED = 0x02, +} diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 4ffce6907d6..ad4e798016f 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -154,7 +154,11 @@ cc_library_static { "libcom.android.sysprop.bluetooth.wrapped", "liblc3", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ + "libbinder", "libcrypto", ], generated_headers: [ diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 2402f95c070..4aa018563be 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -165,6 +165,12 @@ cc_library_static { "libbtif-core", "libflatbuffers-cpp", ], + aidl: { + libs: ["bluetooth_constants"], + }, + shared_libs: [ + "libbinder", + ], apex_available: [ "com.android.btservices", ], @@ -243,7 +249,11 @@ cc_library_static { "libflatbuffers-cpp", "libstatslog_bt", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ + "libbinder", "libcrypto", "libcutils", ], -- GitLab From c58264b1ab01e66a9e3e7aab99307708d1afef96 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 23 Oct 2024 17:11:10 -0700 Subject: [PATCH 528/875] AICS: use aidl definition in java Bug: 372328699 Flag: com.android.bluetooth.flags.aics_api Test: m Bluetooth Change-Id: I058961dcf9f33f1280fa2c112a323c09e106dbe4 --- android/app/Android.bp | 1 + .../vc/VolumeControlInputDescriptor.java | 27 +++++++++---------- .../bluetooth/vc/VolumeControlService.java | 7 +++-- .../vc/VolumeControlInputDescriptorTest.java | 12 +++++---- common/Android.bp | 15 +++++++++++ common/bluetooth/constants/aics/GainMode.aidl | 6 +++++ 6 files changed, 46 insertions(+), 22 deletions(-) diff --git a/android/app/Android.bp b/android/app/Android.bp index 2efc47100aa..83de2861e97 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -270,6 +270,7 @@ android_app { "bluetooth-protos-lite", "bluetooth.change-ids", "bluetooth.mapsapi", + "bluetooth_constants_java", "com.android.obex", "com.android.vcard", "guava", diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java index 759655cf9d4..5055ee43a4c 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java @@ -20,6 +20,11 @@ import android.util.Log; import com.android.bluetooth.btservice.ProfileService; +import bluetooth.constants.AudioInputType; +import bluetooth.constants.aics.AudioInputStatus; +import bluetooth.constants.aics.GainMode; +import bluetooth.constants.aics.Mute; + class VolumeControlInputDescriptor { private static final String TAG = VolumeControlInputDescriptor.class.getSimpleName(); @@ -34,23 +39,15 @@ class VolumeControlInputDescriptor { } private static class Descriptor { - int mStatus = 0; // AudioInputStatus.INACTIVE; + int mStatus = AudioInputStatus.INACTIVE; - int mType = 0; // AudioInputType.UNSPECIFIED; + int mType = AudioInputType.UNSPECIFIED; int mGainValue = 0; - /* See AICS 1.0 - 3.1.3. Gain_Mode field - * The Gain_Mode field shall be set to a value that reflects whether gain modes are manual - * or automatic. - * - Manual Only, the server allows only manual gain. - * - Automatic Only, the server allows only automatic gain. - * - * For all other Gain_Mode field values, the server allows switchable automatic/manual gain. - */ - int mGainMode = 0; + int mGainMode = GainMode.MANUAL_ONLY; - int mMute = 2; // DISABLED + int mMute = Mute.DISABLED; /* See AICS 1.0 * The Gain_Setting (mGainValue) field is a signed value for which a single increment or @@ -84,7 +81,7 @@ class VolumeControlInputDescriptor { } int getStatus(int id) { - if (!isValidId(id)) return 0; // AudioInputStatus.INACTIVE; + if (!isValidId(id)) return AudioInputStatus.INACTIVE; return mVolumeInputs[id].mStatus; } @@ -104,7 +101,7 @@ class VolumeControlInputDescriptor { } int getType(int id) { - if (!isValidId(id)) return 0; // AudioInputType.UNSPECIFIED; + if (!isValidId(id)) return AudioInputType.UNSPECIFIED; return mVolumeInputs[id].mType; } @@ -114,7 +111,7 @@ class VolumeControlInputDescriptor { } int getMute(int id) { - if (!isValidId(id)) return 2; // MuteField.DISABLED + if (!isValidId(id)) return Mute.DISABLED; return mVolumeInputs[id].mMute; } diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 4d0c44adf2e..a54142899ad 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -63,6 +63,9 @@ import com.android.internal.annotations.VisibleForTesting; import libcore.util.SneakyThrow; +import bluetooth.constants.AudioInputType; +import bluetooth.constants.aics.AudioInputStatus; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -1056,7 +1059,7 @@ public class VolumeControlService extends ProfileService { return; } - if (status != 0 && status != 1) { + if (status != AudioInputStatus.INACTIVE && status != AudioInputStatus.ACTIVE) { Log.e(TAG, logInfo + ": Invalid status argument"); return; } @@ -1079,7 +1082,7 @@ public class VolumeControlService extends ProfileService { return; } - if (type > 7) { // AudioInputType.AMBIENT) { + if (type > AudioInputType.AMBIENT) { Log.e(TAG, logInfo + ": Invalid type argument"); return; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java index 37f52cc4fb4..48487d6efc0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java @@ -24,6 +24,8 @@ import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import bluetooth.constants.aics.Mute; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -111,7 +113,7 @@ public class VolumeControlInputDescriptorTest { public void setState_withValidIdButIncorrectSettings_valueIsNotUpdated() { int newGainValue = 42; int newGainMode = 42; - int mute = 0; // NOT_MUTED + int mute = Mute.NOT_MUTED; mDescriptor.setState(VALID_ID, newGainMode, newGainMode, mute); assertThat(mDescriptor.getGain(VALID_ID)).isNotEqualTo(newGainValue); @@ -128,12 +130,12 @@ public class VolumeControlInputDescriptorTest { int newGainValue = 42; int newGainMode = 42; - int mute = 1; // MUTED + int mute = Mute.MUTED; mDescriptor.setState(VALID_ID, newGainMode, newGainMode, mute); assertThat(mDescriptor.getGain(VALID_ID)).isEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); - assertThat(mDescriptor.getMute(VALID_ID)).isEqualTo(1); // MUTED + assertThat(mDescriptor.getMute(VALID_ID)).isEqualTo(mute); } @Test @@ -146,12 +148,12 @@ public class VolumeControlInputDescriptorTest { int newGainValue = 42; int newGainMode = 42; - int mute = 1; + int mute = Mute.MUTED; mDescriptor.setState(INVALID_ID, newGainMode, newGainMode, mute); assertThat(mDescriptor.getGain(INVALID_ID)).isNotEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); - assertThat(mDescriptor.getMute(INVALID_ID)).isEqualTo(2); // DISABLED + assertThat(mDescriptor.getMute(INVALID_ID)).isEqualTo(Mute.DISABLED); } @Test diff --git a/common/Android.bp b/common/Android.bp index 9afdd9dcfc7..900cc365d79 100644 --- a/common/Android.bp +++ b/common/Android.bp @@ -12,3 +12,18 @@ aidl_library { ], visibility: ["//packages/modules/Bluetooth:__subpackages__"], } + +// other java component doesn't know how to depend on an aidl_library +java_library { + name: "bluetooth_constants_java", + srcs: [ + "bluetooth/constants/AudioInputType.aidl", + "bluetooth/constants/aics/AudioInputStatus.aidl", + "bluetooth/constants/aics/GainMode.aidl", + "bluetooth/constants/aics/Mute.aidl", + ], + apex_available: ["com.android.btservices"], + min_sdk_version: "Tiramisu", + sdk_version: "module_current", + visibility: ["//packages/modules/Bluetooth:__subpackages__"], +} diff --git a/common/bluetooth/constants/aics/GainMode.aidl b/common/bluetooth/constants/aics/GainMode.aidl index 97405e75d11..2f3516a2902 100644 --- a/common/bluetooth/constants/aics/GainMode.aidl +++ b/common/bluetooth/constants/aics/GainMode.aidl @@ -18,6 +18,12 @@ package bluetooth.constants.aics; /** * See Audio Input Control Service 1.0 - 2.2.1.3. Gain_Mode field + * The Gain_Mode field shall be set to a value that reflects whether gain modes are manual + * or automatic. + * - Manual Only, the server allows only manual gain. + * - Automatic Only, the server allows only automatic gain. + * + * For all other Gain_Mode field values, the server allows switchable automatic/manual gain. * {@hide} */ @JavaDerive(toString = true) -- GitLab From 56d03852f41be3cc103d4302284cf7e94c5c949d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Paw=C5=82owski?= Date: Wed, 30 Oct 2024 18:31:17 +0000 Subject: [PATCH 529/875] Disconnect when remote key is missing Bug: 376280645 Bug: 376680866 Test: mmm packages/modules/Bluetooth Test: Manual | pair with device, forget bond from the remote, connect to it, observe UX prompts Ignore-AOSP-First: security fix Flag: com.android.bluetooth.flags.sec_disconnect_on_le_key_missing Change-Id: I20135e97eb297a1472959e179dea9c3a94df1727 --- system/stack/btm/btm_sec.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index dc7ba92ce5f..8ac0bc8afa7 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -3294,6 +3294,10 @@ 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"); + } return; } -- GitLab From c7ef13e6a075e1d598493c8c165195e2e380e2b5 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 1 Nov 2024 21:13:11 +0000 Subject: [PATCH 530/875] Disable Secure Connections Only mode support in ICS Secure Connections Only mode is not supported in Android Bluetooth Test: atest pts-bot Flag: TEST_ONLY Bug: 376751772 Change-Id: Ib471dea85b4f6446df3e3add92415f00ec9913f2 --- android/pandora/server/configs/pts_bot_tests_config.json | 1 - 1 file changed, 1 deletion(-) diff --git a/android/pandora/server/configs/pts_bot_tests_config.json b/android/pandora/server/configs/pts_bot_tests_config.json index 45b8679572d..b66af4510f1 100644 --- a/android/pandora/server/configs/pts_bot_tests_config.json +++ b/android/pandora/server/configs/pts_bot_tests_config.json @@ -1893,7 +1893,6 @@ "TSPC_GAP_2_7c": true, "TSPC_GAP_2_8": true, "TSPC_GAP_2_9": true, - "TSPC_GAP_2_11": true, "TSPC_GAP_2_13": true, "TSPC_GAP_3_1": true, "TSPC_GAP_3_3": true, -- GitLab From ddc94c30f525771b0ef147242e8c6e124c5ab0b1 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Fri, 1 Nov 2024 21:23:25 +0000 Subject: [PATCH 531/875] Use LE as default transport for GATT When the application does not specify transport for the GATT connections, use LE transport if LE is supported. Test: mmm packages/modules/Bluetooth Flag: com.android.bluetooth.flags.default_gatt_transport Bug: 372973407 Bug: 376276742 Change-Id: I99a7e18972a1389179f814ae52d083d565a1b3d3 --- system/btif/src/btif_gatt_client.cc | 42 ++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/system/btif/src/btif_gatt_client.cc b/system/btif/src/btif_gatt_client.cc index a873664183f..075ed1b20d6 100644 --- a/system/btif/src/btif_gatt_client.cc +++ b/system/btif/src/btif_gatt_client.cc @@ -332,24 +332,30 @@ void btif_gattc_open_impl(int client_if, RawAddress address, tBLE_ADDR_TYPE addr // Determine transport if (transport == BT_TRANSPORT_AUTO) { - switch (device_type) { - case BT_DEVICE_TYPE_BREDR: - transport = BT_TRANSPORT_BR_EDR; - break; - - case BT_DEVICE_TYPE_BLE: - transport = BT_TRANSPORT_LE; - break; - - case BT_DEVICE_TYPE_DUMO: - transport = (addr_type == BLE_ADDR_RANDOM) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR; - break; - - default: - log::error("Unknown device type {}", DeviceTypeText(device_type)); - // transport must not be AUTO for finding control blocks. Use LE for backward compatibility. - transport = BT_TRANSPORT_LE; - break; + if (com::android::bluetooth::flags::default_gatt_transport()) { + // Prefer LE transport when LE is supported + transport = (device_type == BT_DEVICE_TYPE_BREDR) ? BT_TRANSPORT_BR_EDR : BT_TRANSPORT_LE; + } else { + switch (device_type) { + case BT_DEVICE_TYPE_BREDR: + transport = BT_TRANSPORT_BR_EDR; + break; + + case BT_DEVICE_TYPE_BLE: + transport = BT_TRANSPORT_LE; + break; + + case BT_DEVICE_TYPE_DUMO: + transport = (addr_type == BLE_ADDR_RANDOM) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR; + break; + + default: + log::error("Unknown device type {}", DeviceTypeText(device_type)); + // transport must not be AUTO for finding control blocks. Use LE for backward + // compatibility. + transport = BT_TRANSPORT_LE; + break; + } } } -- GitLab From 2fa1c35c4b982b266d1dfa37446d60c1dec6b4af Mon Sep 17 00:00:00 2001 From: William Escande Date: Fri, 1 Nov 2024 16:28:37 -0700 Subject: [PATCH 532/875] Do not report read remote feature if it failed Bug: 328841620 Fix: 328841620 Test: m . Flag: Exempt obvious status check Change-Id: I000f70198226dfec35bafce1616128714e5ec95b --- system/gd/hci/acl_manager/classic_impl.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/system/gd/hci/acl_manager/classic_impl.h b/system/gd/hci/acl_manager/classic_impl.h index ca0baf74179..08cdcbd2313 100644 --- a/system/gd/hci/acl_manager/classic_impl.h +++ b/system/gd/hci/acl_manager/classic_impl.h @@ -624,6 +624,11 @@ public: auto view = ReadRemoteSupportedFeaturesCompleteView::Create(packet); log::assert_that(view.IsValid(), "Read remote supported features packet invalid"); uint16_t handle = view.GetConnectionHandle(); + auto status = view.GetStatus(); + if (status != ErrorCode::SUCCESS) { + log::error("handle:{} status:{}", handle, ErrorCodeText(status)); + return; + } bluetooth::os::LogMetricBluetoothRemoteSupportedFeatures(connections.get_address(handle), 0, view.GetLmpFeatures(), handle); connections.execute(handle, [=](ConnectionManagementCallbacks* callbacks) { @@ -635,6 +640,11 @@ public: auto view = ReadRemoteExtendedFeaturesCompleteView::Create(packet); log::assert_that(view.IsValid(), "Read remote extended features packet invalid"); uint16_t handle = view.GetConnectionHandle(); + auto status = view.GetStatus(); + if (status != ErrorCode::SUCCESS) { + log::error("handle:{} status:{}", handle, ErrorCodeText(status)); + return; + } bluetooth::os::LogMetricBluetoothRemoteSupportedFeatures(connections.get_address(handle), view.GetPageNumber(), view.GetExtendedLmpFeatures(), handle); -- GitLab From 066933a9980aafba73b30cd9a086b9ad47f95f2e Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Mon, 28 Oct 2024 10:41:19 -0700 Subject: [PATCH 533/875] stack::avct Null out transmit queue pointer after free Bug: 375741222 Test: atest net_test_stack_avctp64 Flag: EXEMPT, Null pointer exemption Change-Id: Ib50c33cfb49f82de4f3f3fed29b96a6ab30da118 --- system/stack/avct/avct_api.cc | 3 +- system/stack/avct/avct_lcb.cc | 2 +- system/stack/test/stack_avctp_test.cc | 72 +++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index 7e1e7a99ad0..55c7cd02e72 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -113,8 +113,9 @@ void AVCT_Deregister(void) { // Clean up AVCTP data structures for (int i = 0; i < AVCT_NUM_LINKS; i++) { - osi_free(avct_cb.lcb[i].p_rx_msg); + osi_free_and_reset((void**)&(avct_cb.lcb[i].p_rx_msg)); fixed_queue_free(avct_cb.lcb[i].tx_q, nullptr); + avct_cb.lcb[i].tx_q = nullptr; osi_free_and_reset((void**)&(avct_cb.bcb[i].p_tx_msg)); } } diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc index ac4519c11c0..43a2b9470bc 100644 --- a/system/stack/avct/avct_lcb.cc +++ b/system/stack/avct/avct_lcb.cc @@ -327,7 +327,7 @@ void avct_lcb_dealloc(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* /* p_data */) { // If not, de-allocate now... log::verbose("Freeing LCB"); - osi_free(p_lcb->p_rx_msg); + osi_free_and_reset((void**)&(p_lcb->p_rx_msg)); fixed_queue_free(p_lcb->tx_q, NULL); memset(p_lcb, 0, sizeof(tAVCT_LCB)); } diff --git a/system/stack/test/stack_avctp_test.cc b/system/stack/test/stack_avctp_test.cc index 17abac13c6d..e617b6462a5 100644 --- a/system/stack/test/stack_avctp_test.cc +++ b/system/stack/test/stack_avctp_test.cc @@ -30,14 +30,27 @@ using ::testing::SaveArg; namespace { constexpr uint16_t kRemoteCid = 0x0123; +constexpr uint16_t kRemoteBrowseCid = 0x0456; const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); } // namespace -class StackAvctpTest : public ::testing::Test { +class StackAvctpWithMocksTest : public ::testing::Test { protected: void SetUp() override { fake_osi_ = std::make_unique<::test::fake::FakeOsi>(); bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_); + } + + void TearDown() override {} + + bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_; + std::unique_ptr fake_osi_; +}; + +class StackAvctpTest : public StackAvctpWithMocksTest { +protected: + void SetUp() override { + StackAvctpWithMocksTest::SetUp(); EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _)) .WillRepeatedly([this](unsigned short psm, const tL2CAP_APPL_INFO& cb, bool /* c */, tL2CAP_ERTM_INFO* /*d*/, unsigned short /* e */, @@ -57,11 +70,10 @@ protected: EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP)); EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE)); AVCT_Deregister(); + StackAvctpWithMocksTest::TearDown(); } std::map callback_map_; - bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_; - std::unique_ptr fake_osi_; int fd_{STDOUT_FILENO}; }; @@ -126,3 +138,57 @@ TEST_F(StackAvctpTest, AVCT_RemoteInitiatesBrowse) { AVCT_Dumpsys(fd_); } + +TEST_F(StackAvctpWithMocksTest, AVCT_Lifecycle) { + // Register the AVCT profile and capture the l2cap callbacks + std::map callback_map; + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _)) + .WillRepeatedly([&callback_map](unsigned short psm, const tL2CAP_APPL_INFO& cb, + bool /* c */, tL2CAP_ERTM_INFO* /*d*/, + unsigned short /* e */, unsigned short /* f */, + unsigned short /* g */) { + callback_map.insert(std::make_tuple(psm, cb)); + return psm; + }); + AVCT_Register(); + + // Return well known l2cap channel IDs for each of the two PSMs + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _)) + .WillRepeatedly( + [](unsigned short psm, const RawAddress /* bd_addr */, uint16_t /* sec_level */) { + return (psm == BT_PSM_AVCTP) ? kRemoteCid : kRemoteBrowseCid; + }); + + uint8_t handle; + tAVCT_CC cc = { + .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */, + const RawAddress* /* peer_addr */) {}, + .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */, + BT_HDR* /* p_pkt */) {}, + .pid = 0x1234, + .role = AVCT_ROLE_INITIATOR, + .control = 1, + }; + + // Initiate the creation of both control and browse AVCT connections + ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress)); + ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateBrowse(handle, AVCT_ROLE_INITIATOR)); + + // Provide appropriate l2cap remote responses to open both channels + tL2CAP_CFG_INFO l2cap_cfg{}; + callback_map[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK); + callback_map[BT_PSM_AVCTP].pL2CA_ConfigCfm_Cb(kRemoteCid, 0, &l2cap_cfg); + callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectCfm_Cb(kRemoteBrowseCid, + tL2CAP_CONN::L2CAP_CONN_OK); + callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConfigCfm_Cb(kRemoteBrowseCid, 0, &l2cap_cfg); + + // Close the profile by deregistering from l2cap + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP)); + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE)); + AVCT_Deregister(); + + // Ensure that API calls with a cached handle value or any run from a reactor + // thread or message loop do not fail + ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveBrowse(handle)); + ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle)); +} -- GitLab From f73d35aabe7898c8a2d255ce5d53de0db3f04194 Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Mon, 28 Oct 2024 14:35:18 -0700 Subject: [PATCH 534/875] stack::avct cleanup Remove link and browse functions Bug: 375741222 Test: m . Flag: EXEMPT, Code cleanup (cherry picked from https://android-review.googlesource.com/q/commit:bd318db3cdd7622ea26724cbcc0d0652838f88fd) Merged-In: I56759d2e5aec7fcfdaa0ad017113d3c75b34dd86 Change-Id: I56759d2e5aec7fcfdaa0ad017113d3c75b34dd86 --- system/stack/avct/avct_api.cc | 48 ++++++++++++++++------------------- system/stack/avct/avct_lcb.cc | 25 +++++++++++++----- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index d4a6aab45eb..7e1e7a99ad0 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -197,27 +197,25 @@ uint16_t AVCT_CreateConn(uint8_t* p_handle, tAVCT_CC* p_cc, const RawAddress& pe * ******************************************************************************/ uint16_t AVCT_RemoveConn(uint8_t handle) { - uint16_t result = AVCT_SUCCESS; - tAVCT_CCB* p_ccb; - log::verbose("AVCT_RemoveConn"); /* map handle to ccb */ - p_ccb = avct_ccb_by_idx(handle); - if (p_ccb == NULL) { - result = AVCT_BAD_HANDLE; + tAVCT_CCB* p_ccb = avct_ccb_by_idx(handle); + if (p_ccb == nullptr) { + return AVCT_BAD_HANDLE; } + /* if connection not bound to lcb, dealloc */ - else if (p_ccb->p_lcb == NULL) { + if (p_ccb->p_lcb == nullptr) { avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL); - } - /* send unbind event to lcb */ - else { - tAVCT_LCB_EVT avct_lcb_evt; - avct_lcb_evt.p_ccb = p_ccb; + } else { + /* send unbind event to lcb */ + tAVCT_LCB_EVT avct_lcb_evt = { + .p_ccb = p_ccb, + }; avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt); } - return result; + return AVCT_SUCCESS; } /******************************************************************************* @@ -301,24 +299,22 @@ uint16_t AVCT_CreateBrowse(uint8_t handle, tAVCT_ROLE role) { * ******************************************************************************/ uint16_t AVCT_RemoveBrowse(uint8_t handle) { - uint16_t result = AVCT_SUCCESS; - tAVCT_CCB* p_ccb; - log::verbose("AVCT_RemoveBrowse"); /* map handle to ccb */ - p_ccb = avct_ccb_by_idx(handle); - if (p_ccb == NULL) { - result = AVCT_BAD_HANDLE; - } else if (p_ccb->p_bcb != NULL) - /* send unbind event to bcb */ - { - tAVCT_LCB_EVT avct_lcb_evt; - avct_lcb_evt.p_ccb = p_ccb; - avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt); + tAVCT_CCB* p_ccb = avct_ccb_by_idx(handle); + if (p_ccb == nullptr) { + return AVCT_BAD_HANDLE; } - return result; + if (p_ccb->p_bcb != nullptr) { + /* send unbind event to bcb */ + tAVCT_LCB_EVT avct_lcb_evt = { + .p_ccb = p_ccb, + }; + avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt); + } + return AVCT_SUCCESS; } /******************************************************************************* diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc index 26d4a731605..ac4519c11c0 100644 --- a/system/stack/avct/avct_lcb.cc +++ b/system/stack/avct/avct_lcb.cc @@ -90,10 +90,23 @@ typedef void (*tAVCT_LCB_ACTION)(tAVCT_LCB* p_ccb, tAVCT_LCB_EVT* p_data); /* action function list */ const tAVCT_LCB_ACTION avct_lcb_action[] = { - avct_lcb_chnl_open, avct_lcb_chnl_disc, avct_lcb_send_msg, avct_lcb_open_ind, - avct_lcb_open_fail, avct_lcb_close_ind, avct_lcb_close_cfm, avct_lcb_msg_ind, - avct_lcb_cong_ind, avct_lcb_bind_conn, avct_lcb_bind_fail, avct_lcb_unbind_disc, - avct_lcb_chk_disc, avct_lcb_discard_msg, avct_lcb_dealloc, avct_lcb_free_msg_ind}; + avct_lcb_chnl_open, // AVCT_LCB_CHNL_OPEN + avct_lcb_chnl_disc, // AVCT_LCB_CHNL_DISC + avct_lcb_send_msg, // AVCT_LCB_SEND_MSG + avct_lcb_open_ind, // AVCT_LCB_OPEN_IND + avct_lcb_open_fail, // AVCT_LCB_OPEN_FAIL + avct_lcb_close_ind, // AVCT_LCB_CLOSE_IND + avct_lcb_close_cfm, // AVCT_LCB_CLOSE_CFM + avct_lcb_msg_ind, // AVCT_LCB_MSG_IND + avct_lcb_cong_ind, // AVCT_LCB_CONG_IND + avct_lcb_bind_conn, // AVCT_LCB_BIND_CONN + avct_lcb_bind_fail, // AVCT_LCB_BIND_FAIL + avct_lcb_unbind_disc, // AVCT_LCB_UNBIND_DISC + avct_lcb_chk_disc, // AVCT_LCB_CHK_DISC + avct_lcb_discard_msg, // AVCT_LCB_DISCARD_MSG + avct_lcb_dealloc, // AVCT_LCB_DEALLOC + avct_lcb_free_msg_ind // AVCT_LCB_FREE_MSG_IND +}; /* state table information */ #define AVCT_LCB_ACTIONS 2 /* number of actions */ @@ -341,8 +354,8 @@ tAVCT_LCB* avct_lcb_by_lcid(uint16_t lcid) { if (i == AVCT_NUM_LINKS) { /* out of lcbs */ - p_lcb = NULL; - log::warn("No lcb for lcid {:x}", lcid); + p_lcb = nullptr; + log::warn("No lcb for lcid 0x{:04x}", lcid); } return p_lcb; -- GitLab From 9b743496ae1b939d04cd24da814d22b26a402b13 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Fri, 2 Aug 2024 09:28:50 +0000 Subject: [PATCH 535/875] Add a flag to fix le_impl stuck in pausing state Bug: 315241296 Bug: 357024179 Test: m -j; Change-Id: I7c2022b9180685cd1681aa3ab9ead5ddd8817891 --- flags/gap.aconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/flags/gap.aconfig b/flags/gap.aconfig index 2b2b5cdd557..daf2f770b3d 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -236,6 +236,19 @@ flag { namespace: "bluetooth" description: "Support MSFT HCI extension for LE Scanning. go/bt-msft-aosp-dd" bug: "365787977" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "le_impl_ack_pause_disarmed" + namespace: "bluetooth" + description: "Let le_impl AckPause when disarmed to prevent stuck in pausing state" + bug: "357024179" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { -- GitLab From eaa2abd938607fbef360c8807c8fc56130cd961c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Y=C4=B1lmaz?= Date: Mon, 4 Nov 2024 04:58:33 +0000 Subject: [PATCH 536/875] Fix setter being skipped over / ignored for field `mIdentityAddress` in RemoteDevices.java Bug: 377180135 Flag: Exempt, trivial fix Test: atest RemoteDevicesTest Change-Id: Iacc99850c819d0962f1bbfc63864497bbf7b0140 --- .../app/src/com/android/bluetooth/btservice/RemoteDevices.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index bd64fb6c7b3..2b39eb9acb6 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -1168,7 +1168,7 @@ public class RemoteDevices { + Utils.getRedactedAddressStringFromByte(secondaryAddress)); DeviceProperties deviceProperties = getDeviceProperties(device); - deviceProperties.mIdentityAddress = Utils.getAddressStringFromByte(secondaryAddress); + deviceProperties.setIdentityAddress(Utils.getAddressStringFromByte(secondaryAddress)); } void aclStateChangeCallback( -- GitLab From 323f22649862df2cd7de1287dc181cc9e8be5135 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 4 Nov 2024 04:41:03 +0000 Subject: [PATCH 537/875] floss: prefer SBC over AAC as default Floss attempts to open AVDTP channel for the codec with the highest priority for default. Some controllers have issues when closing a non-SBC AVDTP channel and immediately opening another for SBC. This CL sets SBC as the highest priority codec so that does not occur. Bug: 306542979 Flag: EXEMPT floss-only Test: m Bluetooth Change-Id: I3fcde3d71c6a34e02df8f7fa62bf9f42f6df9736 --- system/gd/rust/topshim/btav/btav_shim.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/system/gd/rust/topshim/btav/btav_shim.cc b/system/gd/rust/topshim/btav/btav_shim.cc index b334bf30532..3838d03b66a 100644 --- a/system/gd/rust/topshim/btav/btav_shim.cc +++ b/system/gd/rust/topshim/btav/btav_shim.cc @@ -292,10 +292,16 @@ std::unique_ptr GetA2dpProfile(const unsigned char* btif) { } int A2dpIntf::init() const { - std::vector a; + btav_a2dp_codec_config_t a2dp_config_sbc{ + .codec_type = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, + .codec_priority = BTAV_A2DP_CODEC_PRIORITY_HIGHEST, + // Using default settings for those untouched fields + }; + + std::vector codec_priorities(1, a2dp_config_sbc); std::vector b; std::vector c; - return btif_av_source_init(&internal::g_callbacks, 1, a, b, &c); + return btif_av_source_init(&internal::g_callbacks, 1, codec_priorities, b, &c); } uint32_t A2dpIntf::connect(RawAddress addr) const { return btif_av_source_connect(addr); } -- GitLab From 948293c419244f15df4cde105a890a05bd5a6bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Ko=C5=82odziejczyk?= Date: Tue, 29 Oct 2024 15:48:53 +0000 Subject: [PATCH 538/875] flags: add leaudio_stop_updated_to_not_available_context_stream Introduce flag to allow stack stop stream which contains only not allowed contexts. Bug: 376251433 Bug: 315241296 Test: mmm packages/modules/Bluetooth Change-Id: I28db34d9a1bdf9c12961b0edaa483e05c48649ef --- flags/leaudio.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 346c3ba1548..b6430949cd5 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -417,3 +417,13 @@ flag { description: "API to manage broadcast primary group" bug: "375422410" } + +flag { + name: "leaudio_stop_updated_to_not_available_context_stream" + namespace: "bluetooth" + description: "Allow stack to stop stream which remains with non allowed context" + bug: "376251433" + metadata { + purpose: PURPOSE_BUGFIX + } +} \ No newline at end of file -- GitLab From 44c46b107f8bbd57a32aaaec4d45b2aafe91d1de Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Mon, 4 Nov 2024 18:01:48 +0000 Subject: [PATCH 539/875] Prioritize strict address match over RPA resolution btm_find_dev() finds the device record for the given address. It goes through the list of all device records and returns record where 1. identity address matches the given address, 2. pseudo address matches the given address, or 3. IRK can resolve the given address. This means that if an IRK from one of device in the list prior to target device record is able to resolve the address, that device record will be returned. The updated logic now first compares the identity and pseudo address from the device records. If the exact device record is not found, then it tries to find the device record which can resolve the address. Test: mmm packages/modules/Bluetooth Flag: EXEMPT bugfix Bug: 372533704 Change-Id: I8a87d7a47e024014b0a909e0c468b197c774be32 --- system/stack/btm/btm_dev.cc | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc index c791c033192..d4edde046cd 100644 --- a/system/stack/btm/btm_dev.cc +++ b/system/stack/btm/btm_dev.cc @@ -343,7 +343,7 @@ tBTM_SEC_DEV_REC* btm_find_dev_by_handle(uint16_t handle) { return NULL; } -static bool is_address_equal(void* data, void* context) { +static bool is_not_same_identity_or_pseudo_address(void* data, void* context) { tBTM_SEC_DEV_REC* p_dev_rec = static_cast(data); const RawAddress* bd_addr = ((RawAddress*)context); @@ -355,12 +355,18 @@ static bool is_address_equal(void* data, void* context) { return false; } + return true; +} + +static bool is_rpa_unresolvable(void* data, void* context) { + tBTM_SEC_DEV_REC* p_dev_rec = static_cast(data); + const RawAddress* bd_addr = ((RawAddress*)context); + if (btm_ble_addr_resolvable(*bd_addr, p_dev_rec)) { return false; } return true; } - /******************************************************************************* * * Function btm_find_dev @@ -376,12 +382,19 @@ tBTM_SEC_DEV_REC* btm_find_dev(const RawAddress& bd_addr) { return nullptr; } - list_node_t* n = list_foreach(btm_sec_cb.sec_dev_rec, is_address_equal, (void*)&bd_addr); - if (n) { + // Find by matching identity address or pseudo address. + list_node_t* n = list_foreach(btm_sec_cb.sec_dev_rec, is_not_same_identity_or_pseudo_address, + (void*)&bd_addr); + // If not found by matching identity address or pseudo address, find by RPA + if (n == nullptr) { + n = list_foreach(btm_sec_cb.sec_dev_rec, is_rpa_unresolvable, (void*)&bd_addr); + } + + if (n != nullptr) { return static_cast(list_node(n)); } - return NULL; + return nullptr; } static bool has_lenc_and_address_is_equal(void* data, void* context) { @@ -390,7 +403,7 @@ static bool has_lenc_and_address_is_equal(void* data, void* context) { return true; } - return is_address_equal(data, context); + return is_not_same_identity_or_pseudo_address(data, context); } /******************************************************************************* -- GitLab From c264594ae393e59358bf3729c3f11dbe2cd28eca Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Mon, 28 Oct 2024 10:41:19 -0700 Subject: [PATCH 540/875] stack::avct Null out transmit queue pointer after free Bug: 375741222 Test: atest net_test_stack_avctp64 Flag: EXEMPT, Null pointer exemption (cherry picked from https://android-review.googlesource.com/q/commit:066933a9980aafba73b30cd9a086b9ad47f95f2e) Merged-In: Ib50c33cfb49f82de4f3f3fed29b96a6ab30da118 Change-Id: Ib50c33cfb49f82de4f3f3fed29b96a6ab30da118 --- system/stack/avct/avct_api.cc | 3 +- system/stack/avct/avct_lcb.cc | 2 +- system/stack/test/stack_avctp_test.cc | 72 +++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index 7e1e7a99ad0..55c7cd02e72 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -113,8 +113,9 @@ void AVCT_Deregister(void) { // Clean up AVCTP data structures for (int i = 0; i < AVCT_NUM_LINKS; i++) { - osi_free(avct_cb.lcb[i].p_rx_msg); + osi_free_and_reset((void**)&(avct_cb.lcb[i].p_rx_msg)); fixed_queue_free(avct_cb.lcb[i].tx_q, nullptr); + avct_cb.lcb[i].tx_q = nullptr; osi_free_and_reset((void**)&(avct_cb.bcb[i].p_tx_msg)); } } diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc index ac4519c11c0..43a2b9470bc 100644 --- a/system/stack/avct/avct_lcb.cc +++ b/system/stack/avct/avct_lcb.cc @@ -327,7 +327,7 @@ void avct_lcb_dealloc(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* /* p_data */) { // If not, de-allocate now... log::verbose("Freeing LCB"); - osi_free(p_lcb->p_rx_msg); + osi_free_and_reset((void**)&(p_lcb->p_rx_msg)); fixed_queue_free(p_lcb->tx_q, NULL); memset(p_lcb, 0, sizeof(tAVCT_LCB)); } diff --git a/system/stack/test/stack_avctp_test.cc b/system/stack/test/stack_avctp_test.cc index 17abac13c6d..e617b6462a5 100644 --- a/system/stack/test/stack_avctp_test.cc +++ b/system/stack/test/stack_avctp_test.cc @@ -30,14 +30,27 @@ using ::testing::SaveArg; namespace { constexpr uint16_t kRemoteCid = 0x0123; +constexpr uint16_t kRemoteBrowseCid = 0x0456; const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); } // namespace -class StackAvctpTest : public ::testing::Test { +class StackAvctpWithMocksTest : public ::testing::Test { protected: void SetUp() override { fake_osi_ = std::make_unique<::test::fake::FakeOsi>(); bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_); + } + + void TearDown() override {} + + bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_; + std::unique_ptr fake_osi_; +}; + +class StackAvctpTest : public StackAvctpWithMocksTest { +protected: + void SetUp() override { + StackAvctpWithMocksTest::SetUp(); EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _)) .WillRepeatedly([this](unsigned short psm, const tL2CAP_APPL_INFO& cb, bool /* c */, tL2CAP_ERTM_INFO* /*d*/, unsigned short /* e */, @@ -57,11 +70,10 @@ protected: EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP)); EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE)); AVCT_Deregister(); + StackAvctpWithMocksTest::TearDown(); } std::map callback_map_; - bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_; - std::unique_ptr fake_osi_; int fd_{STDOUT_FILENO}; }; @@ -126,3 +138,57 @@ TEST_F(StackAvctpTest, AVCT_RemoteInitiatesBrowse) { AVCT_Dumpsys(fd_); } + +TEST_F(StackAvctpWithMocksTest, AVCT_Lifecycle) { + // Register the AVCT profile and capture the l2cap callbacks + std::map callback_map; + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _)) + .WillRepeatedly([&callback_map](unsigned short psm, const tL2CAP_APPL_INFO& cb, + bool /* c */, tL2CAP_ERTM_INFO* /*d*/, + unsigned short /* e */, unsigned short /* f */, + unsigned short /* g */) { + callback_map.insert(std::make_tuple(psm, cb)); + return psm; + }); + AVCT_Register(); + + // Return well known l2cap channel IDs for each of the two PSMs + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _)) + .WillRepeatedly( + [](unsigned short psm, const RawAddress /* bd_addr */, uint16_t /* sec_level */) { + return (psm == BT_PSM_AVCTP) ? kRemoteCid : kRemoteBrowseCid; + }); + + uint8_t handle; + tAVCT_CC cc = { + .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */, + const RawAddress* /* peer_addr */) {}, + .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */, + BT_HDR* /* p_pkt */) {}, + .pid = 0x1234, + .role = AVCT_ROLE_INITIATOR, + .control = 1, + }; + + // Initiate the creation of both control and browse AVCT connections + ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress)); + ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateBrowse(handle, AVCT_ROLE_INITIATOR)); + + // Provide appropriate l2cap remote responses to open both channels + tL2CAP_CFG_INFO l2cap_cfg{}; + callback_map[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK); + callback_map[BT_PSM_AVCTP].pL2CA_ConfigCfm_Cb(kRemoteCid, 0, &l2cap_cfg); + callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectCfm_Cb(kRemoteBrowseCid, + tL2CAP_CONN::L2CAP_CONN_OK); + callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConfigCfm_Cb(kRemoteBrowseCid, 0, &l2cap_cfg); + + // Close the profile by deregistering from l2cap + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP)); + EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE)); + AVCT_Deregister(); + + // Ensure that API calls with a cached handle value or any run from a reactor + // thread or message loop do not fail + ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveBrowse(handle)); + ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle)); +} -- GitLab From 8af16b893382b447618a6b7dd2deb6019a87009f Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Mon, 4 Nov 2024 17:50:03 +0000 Subject: [PATCH 541/875] Add a flag to avoid updating bonded devices properties from advertisements and inquiry results Ignore-AOSP-First: security fix Flag: com.android.bluetooth.flags.guard_bonded_device_properties Test: mmm packages/modules/Bluetooth Bug: 376928594 Bug: 315241296 Change-Id: I87fb561e2595c6ecb9f31d633c98fa05c639ed58 --- flags/security.aconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flags/security.aconfig b/flags/security.aconfig index ce3f9d6b9eb..c80017c2278 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -94,4 +94,14 @@ flag { 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" + bug: "376928594" + metadata { + purpose: PURPOSE_BUGFIX + } } \ No newline at end of file -- GitLab From 1409d576b4f68fbc526c4fbebcc25e32344423b2 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 30 Oct 2024 16:32:33 -0700 Subject: [PATCH 542/875] SnoopLog: make sure mode is initialized Test: m . Flag: Exempt debugging tool without logical change Bug: 328846950 Fix: 328846950 Change-Id: I493f7517045d5d33b6d5176488fb643b7a60f804 --- system/gd/hal/snoop_logger.cc | 58 ++++++++++----------------- system/gd/hal/snoop_logger.h | 15 ++++--- system/stack/fuzzers/l2cap_fuzzer.cc | 2 +- system/stack/l2cap/internal/l2c_api.h | 2 +- system/stack/l2cap/l2c_api.cc | 5 ++- 5 files changed, 33 insertions(+), 49 deletions(-) diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc index 6b9fc8a2d13..0fc1939d7cd 100644 --- a/system/gd/hal/snoop_logger.cc +++ b/system/gd/hal/snoop_logger.cc @@ -23,7 +23,7 @@ #include #ifdef __ANDROID__ #include -#endif // __ANDROID__ +#endif // __ANDROID__ #include #include @@ -469,8 +469,6 @@ const std::string SnoopLogger::kBtSnoopLogFilterProfileModeMagic = "magic"; // PBAP, MAP and HFP packets filter mode - disabled const std::string SnoopLogger::kBtSnoopLogFilterProfileModeDisabled = "disabled"; -std::string SnoopLogger::btsnoop_mode_; - // Consts accessible in unit tests const size_t SnoopLogger::PACKET_TYPE_LENGTH = 1; const size_t SnoopLogger::MAX_HCI_ACL_LEN = 14; @@ -482,7 +480,8 @@ SnoopLogger::SnoopLogger(std::string snoop_log_path, std::string snooz_log_path, const std::chrono::milliseconds snooz_log_life_time, const std::chrono::milliseconds snooz_log_delete_alarm_interval, bool snoop_log_persists) - : snoop_log_path_(std::move(snoop_log_path)), + : btsnoop_mode_(btsnoop_mode), + snoop_log_path_(std::move(snoop_log_path)), snooz_log_path_(std::move(snooz_log_path)), max_packets_per_file_(max_packets_per_file), btsnooz_buffer_(max_packets_per_buffer), @@ -490,8 +489,6 @@ SnoopLogger::SnoopLogger(std::string snoop_log_path, std::string snooz_log_path, snooz_log_life_time_(snooz_log_life_time), snooz_log_delete_alarm_interval_(snooz_log_delete_alarm_interval), snoop_log_persists(snoop_log_persists) { - btsnoop_mode_ = btsnoop_mode; - if (btsnoop_mode_ == kBtSnoopLogModeFiltered) { log::info("Snoop Logs filtered mode enabled"); EnableFilters(); @@ -566,9 +563,6 @@ void SnoopLogger::OpenNextSnoopLogFile() { } void SnoopLogger::EnableFilters() { - if (btsnoop_mode_ != kBtSnoopLogModeFiltered) { - return; - } std::lock_guard lock(snoop_log_filters_mutex); for (auto itr = kBtSnoopLogFilterState.begin(); itr != kBtSnoopLogFilterState.end(); itr++) { auto filter_enabled_property = os::GetSystemProperty(itr->first); @@ -1135,7 +1129,7 @@ void SnoopLogger::Capture(const HciPacket& immutable_packet, Direction direction if (com::android::bluetooth::flags::snoop_logger_tracing()) { LogTracePoint(packet, direction, type); } - #endif // __ANDROID__ +#endif // __ANDROID__ uint64_t timestamp_us = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) @@ -1305,7 +1299,7 @@ void SnoopLogger::Stop() { socket_ = nullptr; } - btsnoop_mode_.clear(); + btsnoop_mode_ = kBtSnoopLogModeDisabled; // Disable all filters DisableFilters(); @@ -1350,36 +1344,26 @@ size_t SnoopLogger::GetMaxPacketsPerBuffer() { return btsnooz_max_memory_usage_bytes / kDefaultBtSnoozMaxBytesPerPacket; } -std::string SnoopLogger::GetBtSnoopMode() { +std::string SnoopLogger::GetCurrentSnoopMode() { return btsnoop_mode_; } + +static std::string GetBtSnoopMode() { // Default mode is FILTERED on userdebug/eng build, DISABLED on user build. // In userdebug/eng build, it can also be overwritten by modifying the global setting - std::string default_mode = kBtSnoopLogModeDisabled; - { - auto is_debuggable = os::GetSystemPropertyBool(kIsDebuggableProperty, false); - if (is_debuggable) { - auto default_mode_property = os::GetSystemProperty(kBtSnoopDefaultLogModeProperty); - if (default_mode_property) { - default_mode = std::move(default_mode_property.value()); - } else { - default_mode = kBtSnoopLogModeFiltered; - } - } + std::string btsnoop_mode = SnoopLogger::kBtSnoopLogModeDisabled; + if (os::GetSystemPropertyBool(SnoopLogger::kIsDebuggableProperty, false)) { + btsnoop_mode = os::GetSystemProperty(SnoopLogger::kBtSnoopDefaultLogModeProperty) + .value_or(SnoopLogger::kBtSnoopLogModeFiltered); } - // Get the actual mode if exist - std::string btsnoop_mode = default_mode; - { - auto btsnoop_mode_prop = os::GetSystemProperty(kBtSnoopLogModeProperty); - if (btsnoop_mode_prop) { - btsnoop_mode = std::move(btsnoop_mode_prop.value()); - } - } + btsnoop_mode = os::GetSystemProperty(SnoopLogger::kBtSnoopLogModeProperty).value_or(btsnoop_mode); - // If Snoop Logger already set up, return current mode - bool btsnoop_mode_empty = btsnoop_mode_.empty(); - log::info("btsnoop_mode_empty: {}", btsnoop_mode_empty); - if (!btsnoop_mode_empty) { - return btsnoop_mode_; + // Only allow a subset of values: + if (!(btsnoop_mode == SnoopLogger::kBtSnoopLogModeDisabled || + btsnoop_mode == SnoopLogger::kBtSnoopLogModeFull || + btsnoop_mode == SnoopLogger::kBtSnoopLogModeFiltered || + btsnoop_mode == SnoopLogger::kBtSnoopLogModeKernel)) { + log::warn("{}: Invalid btsnoop value, default back to disabled", btsnoop_mode); + return SnoopLogger::kBtSnoopLogModeDisabled; } return btsnoop_mode; @@ -1463,7 +1447,7 @@ void SnoopLogger::LogTracePoint(const HciPacket& packet, Direction direction, Pa } break; } } -#endif // __ANDROID__ +#endif // __ANDROID__ } // namespace hal } // namespace bluetooth diff --git a/system/gd/hal/snoop_logger.h b/system/gd/hal/snoop_logger.h index 3566630e70d..bcd406cc9db 100644 --- a/system/gd/hal/snoop_logger.h +++ b/system/gd/hal/snoop_logger.h @@ -199,9 +199,8 @@ public: static size_t GetMaxPacketsPerBuffer(); - // Get snoop logger mode based on current system setup - // Changes to this values is only effective after restarting Bluetooth - static std::string GetBtSnoopMode(); + // Get current snoop logger mode + std::string GetCurrentSnoopMode(); // Returns whether the soc manufacturer is Qualcomm // Changes to this value is only effective after restarting Bluetooth @@ -232,7 +231,7 @@ public: // Set a RFCOMM dlci as acceptlisted, allowing packets with that RFCOMM CID // to show up in the snoop logs. The local_cid is used to associate it with - // its corrisponding ACL connection. The dlci is the channel with direction + // its corresponding ACL connection. The dlci is the channel with direction // so there is no chance of a collision if two services are using the same // channel but in different directions. void AcceptlistRfcommDlci(uint16_t conn_handle, uint16_t local_cid, uint8_t dlci); @@ -305,7 +304,7 @@ protected: uint32_t FilterProfiles(bool is_received, uint8_t* packet); // Check if packet is A2DP media packet (a2dppktsfiltered mode) bool IsA2dpMediaPacket(bool is_received, uint8_t* packet); - // Chec if channel is cached in snoop logger for filtering (a2dppktsfiltered mode) + // Check if channel is cached in snoop logger for filtering (a2dppktsfiltered mode) bool IsA2dpMediaChannel(uint16_t conn_handle, uint16_t cid, bool is_local_cid); // Handle HFP filtering while profilesfiltered enabled uint32_t FilterProfilesHandleHfp(uint8_t* packet, uint32_t length, uint32_t totlen, @@ -319,12 +318,12 @@ protected: std::unique_ptr snoop_logger_socket_thread_; - #ifdef __ANDROID__ +#ifdef __ANDROID__ void LogTracePoint(const HciPacket& packet, Direction direction, PacketType type); - #endif // __ANDROID__ +#endif // __ANDROID__ private: - static std::string btsnoop_mode_; + std::string btsnoop_mode_; std::string snoop_log_path_; std::string snooz_log_path_; std::ofstream btsnoop_ostream_; diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc index 2c5c3d2cde6..1963983aef0 100644 --- a/system/stack/fuzzers/l2cap_fuzzer.cc +++ b/system/stack/fuzzers/l2cap_fuzzer.cc @@ -85,7 +85,7 @@ class SnoopLogger; const std::string SnoopLogger::kBtSnoopLogModeFiltered = "filtered"; -std::string SnoopLogger::GetBtSnoopMode() { return "filtered"; } +std::string SnoopLogger::GetCurrentSnoopMode() { return "filtered"; } void SnoopLogger::AcceptlistL2capChannel(uint16_t, uint16_t, uint16_t) {} void SnoopLogger::AddA2dpMediaChannel(uint16_t, uint16_t, uint16_t) {} void SnoopLogger::AddRfcommL2capChannel(uint16_t, uint16_t, uint16_t) {} diff --git a/system/stack/l2cap/internal/l2c_api.h b/system/stack/l2cap/internal/l2c_api.h index 6f65f81d717..5ed3403cffa 100644 --- a/system/stack/l2cap/internal/l2c_api.h +++ b/system/stack/l2cap/internal/l2c_api.h @@ -75,7 +75,7 @@ typedef uint8_t tL2CAP_CHNL_DATA_RATE; #define L2CAP_FCR_CHAN_OPT_ALL_MASK (L2CAP_FCR_CHAN_OPT_BASIC | L2CAP_FCR_CHAN_OPT_ERTM) /* Validity check for PSM. PSM values must be odd. Also, all PSM values must - * be assigned such that the least significant bit of the most sigificant + * be assigned such that the least significant bit of the most significant * octet equals zero. */ #define L2C_INVALID_PSM(psm) (((psm) & 0x0101) != 0x0001) diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc index a233046a747..b9587454f1a 100644 --- a/system/stack/l2cap/l2c_api.cc +++ b/system/stack/l2cap/l2c_api.cc @@ -24,7 +24,7 @@ #define LOG_TAG "bt_l2cap" -#include "stack/l2cap/internal/l2c_api.h" +#include "stack/l2cap/l2c_api.h" #include #include @@ -47,6 +47,7 @@ #include "stack/include/btm_client_interface.h" #include "stack/include/l2cap_module.h" #include "stack/include/main_thread.h" +#include "stack/l2cap/internal/l2c_api.h" #include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" @@ -1639,7 +1640,7 @@ void L2CA_SetMediaStreamChannel(uint16_t local_media_cid, bool status) { return; } - if (snoop_logger->GetBtSnoopMode() != snoop_logger->kBtSnoopLogModeFiltered) { + if (snoop_logger->GetCurrentSnoopMode() != snoop_logger->kBtSnoopLogModeFiltered) { return; } -- GitLab From 27948a5105c7adf4b7ddfa44db7c811f40046651 Mon Sep 17 00:00:00 2001 From: Jakub Rotkiewicz Date: Wed, 14 Aug 2024 10:43:53 +0000 Subject: [PATCH 543/875] avatar: Add AVDTP collision simulation test Bug: 330246568 Flag: EXEMPT - test only Test: atest avatar:A2dpTest#test_avdt_signaling_channel_connection_collision Change-Id: I9878a7b11bf079ddfbe883d505acb3aac20b6c85 --- android/pandora/test/a2dp_test.py | 141 +++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 14 deletions(-) diff --git a/android/pandora/test/a2dp_test.py b/android/pandora/test/a2dp_test.py index 2ca7bcf797c..17f368fa887 100644 --- a/android/pandora/test/a2dp_test.py +++ b/android/pandora/test/a2dp_test.py @@ -14,15 +14,14 @@ import asyncio import avatar +import dataclasses import itertools import logging -import math import numpy as np -import os from avatar import BumblePandoraDevice, PandoraDevice, PandoraDevices, pandora from avatar.pandora_server import AndroidPandoraServer -from bumble import l2cap +import bumble from bumble.avctp import AVCTP_PSM from bumble.a2dp import ( A2DP_SBC_CODEC_TYPE, @@ -35,29 +34,27 @@ from bumble.a2dp import ( SbcMediaCodecInformation, make_audio_sink_service_sdp_records, ) -from bumble.avdtp import ( - AVDTP_AUDIO_MEDIA_TYPE, - AVDTP_OPEN_STATE, - AVDTP_STREAMING_STATE, - Listener, - MediaCodecCapabilities, -) +from bumble.avdtp import (AVDTP_AUDIO_MEDIA_TYPE, AVDTP_OPEN_STATE, AVDTP_PSM, AVDTP_STREAMING_STATE, Listener, + MediaCodecCapabilities, Protocol) +from bumble.l2cap import (ChannelManager, ClassicChannel, ClassicChannelSpec, L2CAP_Configure_Request, + L2CAP_Connection_Response, L2CAP_SIGNALING_CID) from bumble.pairing import PairingDelegate 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_none # type: ignore from mobly.asserts import assert_is_not_none # type: ignore from mobly.asserts import fail # type: ignore from pandora.a2dp_grpc_aio import A2DP -from pandora.a2dp_pb2 import PlaybackAudioRequest, Sink, Source +from pandora.a2dp_pb2 import PlaybackAudioRequest, Source from pandora.host_pb2 import Connection from pandora.security_pb2 import LEVEL2 -from threading import Thread from typing import Optional +logger = logging.getLogger(__name__) + AVRCP_CONNECT_A2DP_WITH_DELAY = 'persist.device_config.aconfig_flags.bluetooth.com.android.bluetooth.flags.avrcp_connect_a2dp_with_delay' + async def initiate_pairing(device, address) -> Connection: """Connect and pair a remote device.""" @@ -288,12 +285,128 @@ class A2dpTest(base_test.BaseTestClass): # type: ignore[misc] connection = pandora.get_raw_connection(device=self.ref1, connection=ref1_dut) # Open AVCTP L2CAP channel - avctp = await connection.create_l2cap_channel(spec=l2cap.ClassicChannelSpec(AVCTP_PSM)) + avctp = await connection.create_l2cap_channel(spec=ClassicChannelSpec(AVCTP_PSM)) self.ref1.log.info(f'AVCTP: {avctp}') # Wait for AVDTP L2CAP channel await asyncio.wait_for(avdtp_future, timeout=10.0) + @avatar.asynchronous + async def test_avdt_signaling_channel_connection_collision(self) -> None: + """Test AVDTP signaling channel connection collision. + + Test steps after DUT and RD1 connected and paired: + 1. RD1 connects DUT over AVDTP - first AVDTP signaling channel + 2. AVDTP signaling channel configuration postponed until DUT tries to initiate AVDTP signaling channel connection + 3. DUT tries connecting RD1 - collision simulated + 4. RD1 rejects AVDTP signaling channel connection request from DUT + 5. RD1 proceeds with first AVDTP signaling channel configuration + 6. Channel established - collision avoided + """ + + @dataclasses.dataclass + class L2capConfigurationRequest: + connection: Optional[Connection] = None + cid: Optional[int] = None + request: Optional[L2CAP_Configure_Request] = None + + global pending_configuration_request + pending_configuration_request = L2capConfigurationRequest() + + class TestChannelManager(ChannelManager): + + def __init__( + self, + device: BumblePandoraDevice, + ) -> None: + super().__init__( + device.l2cap_channel_manager.extended_features, + device.l2cap_channel_manager.connectionless_mtu, + ) + self.register_fixed_channel(bumble.smp.SMP_CID, device.on_smp_pdu) + device.sdp_server.register(self) + self.register_fixed_channel(bumble.att.ATT_CID, device.on_gatt_pdu) + self.host = device.host + + def on_l2cap_connection_request(self, connection: Connection, cid: int, request) -> None: + global pending_configuration_request + if (request.psm == AVDTP_PSM and pending_configuration_request is not None): + logger.info("<< 4. RD1 rejects AVDTP connection request from DUT >>") + self.send_control_frame( + connection, cid, + L2CAP_Connection_Response( + identifier=request.identifier, + destination_cid=0, + source_cid=request.source_cid, + result=L2CAP_Connection_Response.CONNECTION_REFUSED_NO_RESOURCES_AVAILABLE, + status=0x0000, + )) + logger.info("<< 5. RD1 proceeds with first AVDTP channel configuration >>") + chan_connection = pending_configuration_request.connection + chan_cid = pending_configuration_request.cid + chan_request = pending_configuration_request.request + pending_configuration_request = None + super().on_control_frame(connection=chan_connection, cid=chan_cid, control_frame=chan_request) + return + super().on_l2cap_connection_request(connection, cid, request) + + class TestClassicChannel(ClassicChannel): + + def on_connection_response(self, response): + assert self.state == self.State.WAIT_CONNECT_RSP + assert response.result == L2CAP_Connection_Response.CONNECTION_SUCCESSFUL, f"Connection response: {response}" + self.destination_cid = response.destination_cid + self._change_state(self.State.WAIT_CONFIG) + logger.info("<< 2. RD1 connected DUT, configuration postponed >>") + + def on_configure_request(self, request) -> None: + global pending_configuration_request + if (pending_configuration_request is not None): + logger.info("<< 3. Block RD1 until DUT tries AVDTP channel connection >>") + pending_configuration_request.connection = self.connection + pending_configuration_request.cid = self.source_cid + pending_configuration_request.request = request + else: + super().on_configure_request(request) + + # Override L2CAP Channel Manager to control signaling + self.ref1.device.l2cap_channel_manager = TestChannelManager(self.ref1.device) + + # Connect and pair DUT -> RD1. + dut_ref1, ref1_dut = await asyncio.gather( + initiate_pairing(self.dut, self.ref1.address), + accept_pairing(self.ref1, self.dut.address), + ) + + # Retrieve Bumble connection object from Pandora connection token + connection = pandora.get_raw_connection(device=self.ref1, connection=ref1_dut) + # Find a free CID for a new channel + connection_channels = self.ref1.device.l2cap_channel_manager.channels.setdefault(connection.handle, {}) + source_cid = self.ref1.device.l2cap_channel_manager.find_free_br_edr_cid(connection_channels) + assert source_cid is not None, "source_cid is None" + + spec = ClassicChannelSpec(AVDTP_PSM) + channel = TestClassicChannel( + self.ref1.device.l2cap_channel_manager, + connection, + L2CAP_SIGNALING_CID, + AVDTP_PSM, + source_cid, + spec.mtu, + ) + connection_channels[source_cid] = channel + + logger.info("<< 1. RD1 connects DUT over AVDTP - first channel >>") + await channel.connect() + logger.info(f"<< 6. Channel established: {channel} >>") + assert channel.state == ClassicChannel.State.OPEN + + # Initiate AVDTP with connected L2CAP signaling channel + protocol = Protocol(channel) + protocol.add_sink(codec_capabilities()) + logger.info("<< Test finished! >>") + + if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) test_runner.main() # type: ignore -- GitLab From 0861bbd1b84dd8235878bad74fb60a4319ae9cbf Mon Sep 17 00:00:00 2001 From: Jakub Rotkiewicz Date: Wed, 4 Sep 2024 15:43:11 +0000 Subject: [PATCH 544/875] avatar: Add codec reconfiguration test Bug: 372300895 Flag: EXEMPT - test only Test: atest avatar:'A2dpTest#test_codec_reconfiguration' -v Change-Id: Ide1968078dfb93bd253762260dfdd92ad32a3188 --- android/pandora/server/src/A2dp.kt | 312 ++++++++++++++++++++++++++++- android/pandora/test/a2dp_test.py | 153 +++++++++++++- 2 files changed, 451 insertions(+), 14 deletions(-) diff --git a/android/pandora/server/src/A2dp.kt b/android/pandora/server/src/A2dp.kt index 59fe71b5264..029d0b4e3d1 100644 --- a/android/pandora/server/src/A2dp.kt +++ b/android/pandora/server/src/A2dp.kt @@ -18,6 +18,9 @@ package com.android.pandora import android.bluetooth.BluetoothA2dp import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothCodecConfig +import android.bluetooth.BluetoothCodecStatus +import android.bluetooth.BluetoothCodecType import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothProfile import android.content.Context @@ -27,6 +30,7 @@ import android.media.* import android.util.Log import com.google.protobuf.BoolValue import com.google.protobuf.ByteString +import com.google.protobuf.Empty import io.grpc.Status import io.grpc.stub.StreamObserver import java.io.Closeable @@ -42,6 +46,7 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn +import kotlinx.coroutines.withTimeoutOrNull import pandora.A2DPGrpc.A2DPImplBase import pandora.A2DPProto.* @@ -65,6 +70,7 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { val intentFilter = IntentFilter() intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED) intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED) + intentFilter.addAction(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED) flow = intentFlow(context, intentFilter, scope).shareIn(scope, SharingStarted.Eagerly) } @@ -76,7 +82,7 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { override fun openSource( request: OpenSourceRequest, - responseObserver: StreamObserver + responseObserver: StreamObserver, ) { grpcUnary(scope, responseObserver) { val device = request.connection.toBluetoothDevice(bluetoothAdapter) @@ -114,7 +120,7 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { override fun waitSource( request: WaitSourceRequest, - responseObserver: StreamObserver + responseObserver: StreamObserver, ) { grpcUnary(scope, responseObserver) { val device = request.connection.toBluetoothDevice(bluetoothAdapter) @@ -183,7 +189,7 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { override fun suspend( request: SuspendRequest, - responseObserver: StreamObserver + responseObserver: StreamObserver, ) { grpcUnary(scope, responseObserver) { val device = bluetoothAdapter.getRemoteDevice(request.source.cookie.toString("UTF-8")) @@ -211,7 +217,7 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { override fun isSuspended( request: IsSuspendedRequest, - responseObserver: StreamObserver + responseObserver: StreamObserver, ) { grpcUnary(scope, responseObserver) { val device = bluetoothAdapter.getRemoteDevice(request.source.cookie.toString("UTF-8")) @@ -271,7 +277,7 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { audioManager.setStreamVolume( AudioManager.STREAM_MUSIC, maxVolume, - AudioManager.FLAG_SHOW_UI + AudioManager.FLAG_SHOW_UI, ) } } @@ -305,7 +311,7 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { override fun getAudioEncoding( request: GetAudioEncodingRequest, - responseObserver: StreamObserver + responseObserver: StreamObserver, ) { grpcUnary(scope, responseObserver) { val device = bluetoothAdapter.getRemoteDevice(request.source.cookie.toString("UTF-8")) @@ -321,4 +327,298 @@ class A2dp(val context: Context) : A2DPImplBase(), Closeable { .build() } } + + override fun getConfiguration( + request: GetConfigurationRequest, + responseObserver: StreamObserver, + ) { + grpcUnary(scope, responseObserver) { + val device = request.connection.toBluetoothDevice(bluetoothAdapter) + Log.i(TAG, "getConfiguration: device=$device") + + if (bluetoothA2dp.getConnectionState(device) != BluetoothA2dp.STATE_CONNECTED) { + throw RuntimeException("Device is not connected, cannot getConfiguration") + } + + val codecStatus = bluetoothA2dp.getCodecStatus(device) + if (codecStatus == null) { + throw RuntimeException("Codec status is null") + } + + val currentCodecConfig = codecStatus.getCodecConfig() + if (currentCodecConfig == null) { + throw RuntimeException("Codec configuration is null") + } + + val supportedCodecTypes = bluetoothA2dp.getSupportedCodecTypes() + val configuration = + Configuration.newBuilder() + .setId(getProtoCodecId(currentCodecConfig, supportedCodecTypes)) + .setParameters(getProtoCodecParameters(currentCodecConfig)) + .build() + GetConfigurationResponse.newBuilder().setConfiguration(configuration).build() + } + } + + override fun setConfiguration( + request: SetConfigurationRequest, + responseObserver: StreamObserver, + ) { + grpcUnary(scope, responseObserver) { + val timeoutMillis: Long = 5_000L // milliseconds + val device = request.connection.toBluetoothDevice(bluetoothAdapter) + Log.i(TAG, "setConfiguration: device=$device") + + if (bluetoothA2dp.getConnectionState(device) != BluetoothA2dp.STATE_CONNECTED) { + throw RuntimeException("Device is not connected, cannot getCodecStatus") + } + + val newCodecConfig = getCodecConfigFromProtoConfiguration(request.configuration) + if (newCodecConfig == null) { + throw RuntimeException("New codec configuration is null") + } + + val codecId = packCodecId(request.configuration.id) + + val a2dpCodecConfigChangedFlow = + flow + .filter { it.getAction() == BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED } + .filter { it.getBluetoothDeviceExtra() == device } + .map { + it.getParcelableExtra( + BluetoothCodecStatus.EXTRA_CODEC_STATUS, + BluetoothCodecStatus::class.java, + ) + ?.getCodecConfig() + } + + bluetoothA2dp.setCodecConfigPreference(device, newCodecConfig) + + val result = + withTimeoutOrNull(timeoutMillis) { + a2dpCodecConfigChangedFlow + .filter { it?.getExtendedCodecType()?.getCodecId() == codecId } + .first() + } + Log.i(TAG, "Result=$result") + SetConfigurationResponse.newBuilder().setSuccess(result != null).build() + } + } + + private fun unpackCodecId(codecId: Long): CodecId { + val codecType = (codecId and 0xFF).toInt() + val vendorId = ((codecId shr 8) and 0xFFFF).toInt() + val vendorCodecId = ((codecId shr 24) and 0xFFFF).toInt() + val codecIdBuilder = CodecId.newBuilder() + when (codecType) { + 0x00 -> { + codecIdBuilder.setSbc(Empty.getDefaultInstance()) + } + 0x02 -> { + codecIdBuilder.setMpegAac(Empty.getDefaultInstance()) + } + 0xFF -> { + val vendor = Vendor.newBuilder().setId(vendorId).setCodecId(vendorCodecId).build() + codecIdBuilder.setVendor(vendor) + } + else -> { + throw RuntimeException("Unknown codec type") + } + } + return codecIdBuilder.build() + } + + private fun packCodecId(codecId: CodecId): Long { + var codecType: Int + var vendorId: Int = 0 + var vendorCodecId: Int = 0 + when { + codecId.hasSbc() -> { + codecType = 0x00 + } + codecId.hasMpegAac() -> { + codecType = 0x02 + } + codecId.hasVendor() -> { + codecType = 0xFF + vendorId = codecId.vendor.id + vendorCodecId = codecId.vendor.codecId + } + else -> { + throw RuntimeException("Unknown codec type") + } + } + return (codecType.toLong() and 0xFF) or + ((vendorId.toLong() and 0xFFFF) shl 8) or + ((vendorCodecId.toLong() and 0xFFFF) shl 24) + } + + private fun getProtoCodecId( + codecConfig: BluetoothCodecConfig, + supportedCodecTypes: Collection, + ): CodecId { + var selectedCodecType: BluetoothCodecType? = null + for (codecType: BluetoothCodecType in supportedCodecTypes) { + if (codecType.getCodecId() == codecConfig.getExtendedCodecType()?.getCodecId()) { + selectedCodecType = codecType + } + } + if (selectedCodecType == null) { + Log.e(TAG, "getProtoCodecId: selectedCodecType is null") + return CodecId.newBuilder().build() + } + return unpackCodecId(selectedCodecType.getCodecId()) + } + + private fun getProtoCodecParameters(codecConfig: BluetoothCodecConfig): CodecParameters { + var channelMode: ChannelMode + var samplingFrequencyHz: Int + var bitDepth: Int + when (codecConfig.getSampleRate()) { + BluetoothCodecConfig.SAMPLE_RATE_NONE -> { + samplingFrequencyHz = 0 + } + BluetoothCodecConfig.SAMPLE_RATE_44100 -> { + samplingFrequencyHz = 44100 + } + BluetoothCodecConfig.SAMPLE_RATE_48000 -> { + samplingFrequencyHz = 48000 + } + BluetoothCodecConfig.SAMPLE_RATE_88200 -> { + samplingFrequencyHz = 88200 + } + BluetoothCodecConfig.SAMPLE_RATE_96000 -> { + samplingFrequencyHz = 96000 + } + BluetoothCodecConfig.SAMPLE_RATE_176400 -> { + samplingFrequencyHz = 176400 + } + BluetoothCodecConfig.SAMPLE_RATE_192000 -> { + samplingFrequencyHz = 192000 + } + else -> { + throw RuntimeException("Unknown sample rate") + } + } + when (codecConfig.getBitsPerSample()) { + BluetoothCodecConfig.BITS_PER_SAMPLE_NONE -> { + bitDepth = 0 + } + BluetoothCodecConfig.BITS_PER_SAMPLE_16 -> { + bitDepth = 16 + } + BluetoothCodecConfig.BITS_PER_SAMPLE_24 -> { + bitDepth = 24 + } + BluetoothCodecConfig.BITS_PER_SAMPLE_32 -> { + bitDepth = 32 + } + else -> { + throw RuntimeException("Unknown bit depth") + } + } + when (codecConfig.getChannelMode()) { + BluetoothCodecConfig.CHANNEL_MODE_NONE -> { + channelMode = ChannelMode.UNKNOWN + } + BluetoothCodecConfig.CHANNEL_MODE_MONO -> { + channelMode = ChannelMode.MONO + } + BluetoothCodecConfig.CHANNEL_MODE_STEREO -> { + channelMode = ChannelMode.STEREO + } + else -> { + throw RuntimeException("Unknown channel mode") + } + } + return CodecParameters.newBuilder() + .setSamplingFrequencyHz(samplingFrequencyHz) + .setBitDepth(bitDepth) + .setChannelMode(channelMode) + .build() + } + + private fun getCodecConfigFromProtoConfiguration( + configuration: Configuration + ): BluetoothCodecConfig? { + var selectedCodecType: BluetoothCodecType? = null + val codecTypes = bluetoothA2dp.getSupportedCodecTypes() + val codecId = packCodecId(configuration.id) + var sampleRate: Int + var bitsPerSample: Int + var channelMode: Int + for (codecType: BluetoothCodecType in codecTypes) { + if (codecType.getCodecId() == codecId) { + selectedCodecType = codecType + } + } + if (selectedCodecType == null) { + Log.e(TAG, "getCodecConfigFromProtoConfiguration: selectedCodecType is null") + return null + } + when (configuration.parameters.getSamplingFrequencyHz()) { + 0 -> { + sampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE + } + 44100 -> { + sampleRate = BluetoothCodecConfig.SAMPLE_RATE_44100 + } + 48000 -> { + sampleRate = BluetoothCodecConfig.SAMPLE_RATE_48000 + } + 88200 -> { + sampleRate = BluetoothCodecConfig.SAMPLE_RATE_88200 + } + 96000 -> { + sampleRate = BluetoothCodecConfig.SAMPLE_RATE_96000 + } + 176400 -> { + sampleRate = BluetoothCodecConfig.SAMPLE_RATE_176400 + } + 192000 -> { + sampleRate = BluetoothCodecConfig.SAMPLE_RATE_192000 + } + else -> { + throw RuntimeException("Unknown sample rate") + } + } + when (configuration.parameters.getBitDepth()) { + 0 -> { + bitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE + } + 16 -> { + bitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_16 + } + 24 -> { + bitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_24 + } + 32 -> { + bitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_32 + } + else -> { + throw RuntimeException("Unknown bit depth") + } + } + when (configuration.parameters.getChannelMode()) { + ChannelMode.UNKNOWN -> { + channelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE + } + ChannelMode.MONO -> { + channelMode = BluetoothCodecConfig.CHANNEL_MODE_MONO + } + ChannelMode.STEREO -> { + channelMode = BluetoothCodecConfig.CHANNEL_MODE_STEREO + } + else -> { + throw RuntimeException("Unknown channel mode") + } + } + return BluetoothCodecConfig.Builder() + .setExtendedCodecType(selectedCodecType) + .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST) + .setSampleRate(sampleRate) + .setBitsPerSample(bitsPerSample) + .setChannelMode(channelMode) + .build() + } } diff --git a/android/pandora/test/a2dp_test.py b/android/pandora/test/a2dp_test.py index 17f368fa887..7006a819459 100644 --- a/android/pandora/test/a2dp_test.py +++ b/android/pandora/test/a2dp_test.py @@ -24,6 +24,8 @@ from avatar.pandora_server import AndroidPandoraServer import bumble from bumble.avctp import AVCTP_PSM from bumble.a2dp import ( + A2DP_MPEG_2_4_AAC_CODEC_TYPE, + MPEG_2_AAC_LC_OBJECT_TYPE, A2DP_SBC_CODEC_TYPE, SBC_DUAL_CHANNEL_MODE, SBC_JOINT_STEREO_CHANNEL_MODE, @@ -31,11 +33,12 @@ from bumble.a2dp import ( SBC_MONO_CHANNEL_MODE, SBC_SNR_ALLOCATION_METHOD, SBC_STEREO_CHANNEL_MODE, + AacMediaCodecInformation, SbcMediaCodecInformation, make_audio_sink_service_sdp_records, ) from bumble.avdtp import (AVDTP_AUDIO_MEDIA_TYPE, AVDTP_OPEN_STATE, AVDTP_PSM, AVDTP_STREAMING_STATE, Listener, - MediaCodecCapabilities, Protocol) + MediaCodecCapabilities, Protocol, AVDTP_BAD_STATE_ERROR, Suspend_Reject) from bumble.l2cap import (ChannelManager, ClassicChannel, ClassicChannelSpec, L2CAP_Configure_Request, L2CAP_Connection_Response, L2CAP_SIGNALING_CID) from bumble.pairing import PairingDelegate @@ -45,10 +48,10 @@ 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.a2dp_grpc_aio import A2DP -from pandora.a2dp_pb2 import PlaybackAudioRequest, Source +from pandora.a2dp_pb2 import PlaybackAudioRequest, Source, Configuration, STEREO from pandora.host_pb2 import Connection from pandora.security_pb2 import LEVEL2 -from typing import Optional +from typing import Optional, Tuple logger = logging.getLogger(__name__) @@ -91,7 +94,7 @@ async def open_source(device, connection) -> Source: return source -def codec_capabilities(): +def sbc_codec_capabilities() -> MediaCodecCapabilities: """Codec capabilities for the Bumble sink devices.""" return MediaCodecCapabilities( @@ -117,6 +120,22 @@ def codec_capabilities(): ) +def aac_codec_capabilities() -> MediaCodecCapabilities: + """Codec capabilities for the Bumble sink devices.""" + + return MediaCodecCapabilities( + media_type=AVDTP_AUDIO_MEDIA_TYPE, + media_codec_type=A2DP_MPEG_2_4_AAC_CODEC_TYPE, + media_codec_information=AacMediaCodecInformation.from_lists( + object_types=[MPEG_2_AAC_LC_OBJECT_TYPE], + sampling_frequencies=[48000, 44100], + channels=[1, 2], + vbr=1, + bitrate=256000, + ), + ) + + class AudioSignal: """Audio signal generator and verifier.""" @@ -209,10 +228,11 @@ class A2dpTest(base_test.BaseTestClass): # type: ignore[misc] self.ref2.a2dp_sink = None def on_ref1_avdtp_connection(server): - self.ref1.a2dp_sink = server.add_sink(codec_capabilities()) + self.ref1.a2dp_sink = server.add_sink(sbc_codec_capabilities()) def on_ref2_avdtp_connection(server): - self.ref2.a2dp_sink = server.add_sink(codec_capabilities()) + self.ref2.a2dp_sink = server.add_sink(sbc_codec_capabilities()) + self.ref2.a2dp_sink = server.add_sink(aac_codec_capabilities()) self.ref1.a2dp.on('connection', on_ref1_avdtp_connection) self.ref2.a2dp.on('connection', on_ref2_avdtp_connection) @@ -275,7 +295,7 @@ class A2dpTest(base_test.BaseTestClass): # type: ignore[misc] def on_avdtp_connection(server): nonlocal avdtp_future - self.ref1.a2dp_sink = server.add_sink(codec_capabilities()) + self.ref1.a2dp_sink = server.add_sink(sbc_codec_capabilities()) self.ref1.log.info(f'Sink: {self.ref1.a2dp_sink}') avdtp_future.set_result(None) @@ -403,9 +423,126 @@ class A2dpTest(base_test.BaseTestClass): # type: ignore[misc] # Initiate AVDTP with connected L2CAP signaling channel protocol = Protocol(channel) - protocol.add_sink(codec_capabilities()) + protocol.add_sink(sbc_codec_capabilities()) logger.info("<< Test finished! >>") + @avatar.asynchronous + async def test_reconfigure_codec_success(self) -> None: + """Basic A2DP connection and codec reconfiguration. + + 1. Pair and Connect RD2 + 2. Check current codec configuration - should be AAC + 3. Set SBC codec configuration + """ + # Connect and pair RD2. + dut_ref2, ref2_dut = await asyncio.gather( + initiate_pairing(self.dut, self.ref2.address), + accept_pairing(self.ref2, self.dut.address), + ) + + # Connect AVDTP to RD2. + dut_ref2_source = await open_source(self.dut, dut_ref2) + assert_is_not_none(self.ref2.a2dp_sink) + assert_is_not_none(self.ref2.a2dp_sink.stream) + assert_in(self.ref2.a2dp_sink.stream.state, [AVDTP_OPEN_STATE, AVDTP_STREAMING_STATE]) + + # Get current codec status + configurationResponse = await self.dut.a2dp.GetConfiguration(connection=dut_ref2) + logger.info(f"Current codec configuration: {configurationResponse.configuration}") + assert configurationResponse.configuration.id.HasField('mpeg_aac') + + new_configuration = Configuration() + new_configuration.id.sbc.SetInParent() + new_configuration.parameters.sampling_frequency_hz = 44100 + new_configuration.parameters.bit_depth = 16 + new_configuration.parameters.channel_mode = STEREO + + # Set new codec + logger.info(f"Switching to codec: {new_configuration}") + result = await self.dut.a2dp.SetConfiguration(connection=dut_ref2, configuration=new_configuration) + assert result.success + + # Get current codec status + configurationResponse = await self.dut.a2dp.GetConfiguration(connection=dut_ref2) + logger.info(f"Current codec configuration: {configurationResponse.configuration}") + assert configurationResponse.configuration.id.HasField('sbc') + + @avatar.asynchronous + async def test_reconfigure_codec_error_unsupported(self) -> None: + """Basic A2DP connection and codec reconfiguration failure. + + 1. Pair and Connect RD2 + 2. Check current codec configuration - should be AAC + 3. Set SBC codec configuration with unsupported parameters + """ + # Connect and pair RD2. + dut_ref2, ref2_dut = await asyncio.gather( + initiate_pairing(self.dut, self.ref2.address), + accept_pairing(self.ref2, self.dut.address), + ) + + # Connect AVDTP to RD2. + dut_ref2_source = await open_source(self.dut, dut_ref2) + assert_is_not_none(self.ref2.a2dp_sink) + assert_is_not_none(self.ref2.a2dp_sink.stream) + assert_in(self.ref2.a2dp_sink.stream.state, [AVDTP_OPEN_STATE, AVDTP_STREAMING_STATE]) + + # Get current codec status + configurationResponse = await self.dut.a2dp.GetConfiguration(connection=dut_ref2) + logger.info(f"Current codec configuration: {configurationResponse.configuration}") + assert configurationResponse.configuration.id.HasField('mpeg_aac') + + new_configuration = Configuration() + new_configuration.id.sbc.SetInParent() + new_configuration.parameters.sampling_frequency_hz = 176400 + new_configuration.parameters.bit_depth = 24 + new_configuration.parameters.channel_mode = STEREO + + # Set new codec + logger.info(f"Switching to codec: {new_configuration}") + result = await self.dut.a2dp.SetConfiguration(connection=dut_ref2, configuration=new_configuration) + assert result.success == False + + # Get current codec status, assure it did not change + configurationResponse = await self.dut.a2dp.GetConfiguration(connection=dut_ref2) + logger.info(f"Current codec configuration: {configurationResponse.configuration}") + assert configurationResponse.configuration.id.HasField('mpeg_aac') + + @avatar.asynchronous + async def test_reconfigure_codec_aac_error(self) -> None: + # Connect and pair RD2. + dut_ref2, ref2_dut = await asyncio.gather( + initiate_pairing(self.dut, self.ref2.address), + accept_pairing(self.ref2, self.dut.address), + ) + + # Connect AVDTP to RD2. + dut_ref2_source = await open_source(self.dut, dut_ref2) + assert_is_not_none(self.ref2.a2dp_sink) + assert_is_not_none(self.ref2.a2dp_sink.stream) + assert_in(self.ref2.a2dp_sink.stream.state, [AVDTP_OPEN_STATE, AVDTP_STREAMING_STATE]) + + # Get current codec status + configurationResponse = await self.dut.a2dp.GetConfiguration(connection=dut_ref2) + logger.info(f"Current codec configuration: {configurationResponse.configuration}") + assert configurationResponse.configuration.id.HasField('mpeg_aac') + + new_configuration = Configuration() + new_configuration.id.sbc.SetInParent() + new_configuration.parameters.sampling_frequency_hz = 176400 + new_configuration.parameters.bit_depth = 24 + new_configuration.parameters.channel_mode = STEREO + + # Set new codec + logger.info(f"Switching to codec: {new_configuration}") + result = await self.dut.a2dp.SetConfiguration(connection=dut_ref2, configuration=new_configuration) + assert result.success == False + + # Get current codec status, assure it did not change + configurationResponse = await self.dut.a2dp.GetConfiguration(connection=dut_ref2) + logger.info(f"Current codec configuration: {configurationResponse.configuration}") + assert configurationResponse.configuration.id.HasField('mpeg_aac') + if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) -- GitLab From 90a75ade1f4ad06907dce0f59f7c98d9c040da70 Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Sat, 26 Oct 2024 05:56:32 +0000 Subject: [PATCH 545/875] [le audio] Add new APIs to get assistant local metadata for source getSourceMetadata is introduced to allow app to get sink's broadcast source metadata. Bug: 375421703 Bug: 375423982 Test: atest BluetoothLeBroadcastAssistantTest Test: atest BassClientServiceTest Test: manual test callback with LeAudioTestApp Change-Id: I695bc0fe42bba991b5d895b548c0d00b966d3952 --- .../IBluetoothLeBroadcastAssistant.aidl | 2 + .../bass_client/BassClientService.java | 33 ++++++++++++ .../bass_client/BassClientStateMachine.java | 8 +-- .../bass_client/BassClientServiceTest.java | 34 +++++++++++++ framework/api/system-current.txt | 1 + .../BluetoothLeBroadcastAssistant.java | 50 +++++++++++++++++++ 6 files changed, 124 insertions(+), 4 deletions(-) diff --git a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl index bf95bb5ceec..54b947c0614 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl @@ -60,4 +60,6 @@ interface IBluetoothLeBroadcastAssistant { List getAllSources(in BluetoothDevice sink, in AttributionSource source); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") int getMaximumSourceCapacity(in BluetoothDevice sink, in AttributionSource source); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + BluetoothLeBroadcastMetadata getSourceMetadata(in BluetoothDevice sink, in int sourceId, in AttributionSource source); } 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 7a0389ad2c5..957b02c3221 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -23,6 +23,7 @@ import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask; import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState; +import static com.android.bluetooth.flags.Flags.leaudioBroadcastApiGetLocalMetadata; import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment; import static com.android.bluetooth.flags.Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine; import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper; @@ -3273,6 +3274,27 @@ public class BassClientService extends ProfileService { return stateMachine.getMaximumSourceCapacity(); } + /** + * Get metadata of source that stored on this Broadcast Sink + * + * @param sink Broadcast Sink device + * @param sourceId Broadcast source id + * @return metadata of source that stored on this Broadcast Sink + */ + BluetoothLeBroadcastMetadata getSourceMetadata(BluetoothDevice sink, int sourceId) { + if (!leaudioBroadcastApiGetLocalMetadata()) { + return null; + } + + log("getSourceMetadata: device = " + sink + " with source id = " + sourceId); + BassClientStateMachine stateMachine = getOrCreateStateMachine(sink); + if (stateMachine == null) { + log("stateMachine is null"); + return null; + } + return stateMachine.getCurrentBroadcastMetadata(sourceId); + } + private boolean isLocalBroadcast(int broadcastId) { LeAudioService leAudioService = mServiceFactory.getLeAudioService(); if (leAudioService == null) { @@ -4630,5 +4652,16 @@ public class BassClientService extends ProfileService { } 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/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index b59ff2fcd27..021b73289b8 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -376,10 +376,6 @@ class BassClientStateMachine extends StateMachine { return mPendingSourceToSwitch != null; } - BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) { - return mCurrentMetadata.getOrDefault(sourceId, null); - } - private void setCurrentBroadcastMetadata( Integer sourceId, BluetoothLeBroadcastMetadata metadata) { if (metadata != null) { @@ -2619,6 +2615,10 @@ class BassClientStateMachine extends StateMachine { return mNumOfBroadcastReceiverStates; } + BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) { + return mCurrentMetadata.getOrDefault(sourceId, null); + } + BluetoothDevice getDevice() { return mDevice; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 12a0f7d9efe..e6e9f40cae8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -2039,6 +2039,40 @@ public class BassClientServiceTest { } } + @Test + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_API_GET_LOCAL_METADATA) + public void testGetSourceMetadata() { + prepareConnectedDeviceGroup(); + startSearchingForSources(); + onScanResult(mSourceDevice, TEST_BROADCAST_ID); + onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); + BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); + + for (BassClientStateMachine sm : mStateMachines.values()) { + injectRemoteSourceStateSourceAdded( + sm, + meta, + TEST_SOURCE_ID, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null); + doReturn(null).when(sm).getCurrentBroadcastMetadata(eq(TEST_SOURCE_ID)); + assertThat(mBassClientService.getSourceMetadata(sm.getDevice(), TEST_SOURCE_ID)) + .isEqualTo(null); + + doReturn(meta).when(sm).getCurrentBroadcastMetadata(eq(TEST_SOURCE_ID)); + doReturn(true).when(sm).isSyncedToTheSource(eq(TEST_SOURCE_ID)); + assertThat(mBassClientService.getSourceMetadata(sm.getDevice(), TEST_SOURCE_ID)) + .isEqualTo(meta); + } + + for (BassClientStateMachine sm : mStateMachines.values()) { + injectRemoteSourceStateRemoval(sm, TEST_SOURCE_ID); + } + } + /** Test whether the group operation flag is set on addSource() and removed on removeSource */ @Test public void testGroupStickyFlagSetUnset() { diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 7aa89155b14..e8280710182 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -592,6 +592,7 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List getDevicesMatchingConnectionStates(@NonNull int[]); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getMaximumSourceCapacity(@NonNull android.bluetooth.BluetoothDevice); + method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_api_get_local_metadata") @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothLeBroadcastMetadata getSourceMetadata(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isSearchInProgress(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void modifySource(@NonNull android.bluetooth.BluetoothDevice, int, @NonNull android.bluetooth.BluetoothLeBroadcastMetadata); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothLeBroadcastAssistant.Callback); diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java index 28b4e779eef..829ee2f301a 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java @@ -21,7 +21,9 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.BLUETOOTH_SCAN; import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresNoPermission; @@ -40,6 +42,8 @@ import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.bluetooth.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -1205,6 +1209,52 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au return defaultValue; } + /** + * Gets the {@link BluetoothLeBroadcastMetadata} of a specified source added to this Broadcast + * Sink. + * + *

    This method retrieves the {@link BluetoothLeBroadcastMetadata} associated with the + * specified source. The metadata is obtained from the {@link BluetoothLeBroadcastReceiveState} + * maintained by this Broadcast Sink. If no matching metadata is found, this method returns + * {@code null}. + * + *

    The source's {@link BluetoothLeBroadcastMetadata} is initially set by {@link + * #addSource(BluetoothDevice, BluetoothLeBroadcastMetadata, boolean)} and can be updated with + * {@link #modifySource(BluetoothDevice, int, BluetoothLeBroadcastMetadata)}. + * + * @param sink Broadcast Sink device + * @param sourceId Broadcast source id. Valid range is [0, 0xFF] as defined in the Broadcast + * Audio Scan Service 1.0 specification (section 3.2). + * @return metadata {@link BluetoothLeBroadcastMetadata} associated with the specified source. + * @throws IllegalArgumentException if sourceID is not [0, 0xFF]. + * @hide + */ + @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_API_GET_LOCAL_METADATA) + @SystemApi + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) + public @Nullable BluetoothLeBroadcastMetadata getSourceMetadata( + @NonNull BluetoothDevice sink, @IntRange(from = 0x00, to = 0xFF) int sourceId) { + log("getSourceMetadata()"); + Objects.requireNonNull(sink, "sink cannot be null"); + if (sourceId < 0x00 || sourceId > 0xFF) { + throw new IllegalArgumentException( + "sourceId " + sourceId + " does not fall between 0x00 and 0xFF"); + } + final IBluetoothLeBroadcastAssistant service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mBluetoothAdapter.isEnabled()) { + try { + return service.getSourceMetadata(sink, sourceId, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } + return null; + } + private static void log(@NonNull String msg) { if (DBG) { Log.d(TAG, msg); -- GitLab From fa5d5f10db0dbd2ae335745837c5376dc0fb18cb Mon Sep 17 00:00:00 2001 From: Billy Huang Date: Thu, 24 Oct 2024 13:55:19 -0700 Subject: [PATCH 546/875] OPP: check content URI permissions of sending application on V+ Flag: com.android.bluetooth.flags.opp_check_content_uri_permissions Ignore-AOSP-First: Security fix Test: m com.google.android.btservices Test: researcher POC Test: atest GoogleBluetoothInstrumentationTests Bug: 193800863 Bug: 375466974 Change-Id: Iced5a075222e50bef3b0d75c5b8bf5e597381c01 --- .../bluetooth/BluetoothMethodProxy.java | 11 + .../opp/BluetoothOppLauncherActivity.java | 81 +++++- .../opp/BluetoothOppLauncherActivityTest.java | 245 +++++++++++++++++- 3 files changed, 333 insertions(+), 4 deletions(-) diff --git a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java index f6d065eb761..dcd2e243173 100644 --- a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +++ b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java @@ -18,6 +18,7 @@ package com.android.bluetooth; import android.annotation.NonNull; import android.annotation.SuppressLint; +import android.app.ComponentCaller; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.PeriodicAdvertisingCallback; @@ -33,6 +34,7 @@ import android.database.Cursor; import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Handler; @@ -43,6 +45,8 @@ import android.os.ParcelFileDescriptor; import android.provider.Telephony; import android.util.Log; +import androidx.annotation.RequiresApi; + import com.android.bluetooth.bass_client.BassClientPeriodicAdvertisingManager; import com.android.internal.annotations.VisibleForTesting; import com.android.obex.HeaderSet; @@ -283,4 +287,11 @@ public class BluetoothMethodProxy { MediaSessionManager manager) { return manager.getActiveSessions(null); } + + /** Proxies {@link ComponentCaller#checkContentUriPermission(Uri, int)}. } */ + @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) + public int componentCallerCheckContentUriPermission( + ComponentCaller caller, Uri uri, int modeFlags) { + return caller.checkContentUriPermission(uri, modeFlags); + } } diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java index 002ac61e976..216c0f3506c 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java @@ -34,6 +34,9 @@ package com.android.bluetooth.opp; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static java.util.function.Predicate.not; +import static java.util.stream.Collectors.toList; + import android.annotation.SuppressLint; import android.app.Activity; import android.bluetooth.BluetoothDevicePicker; @@ -42,25 +45,32 @@ import android.bluetooth.BluetoothProtoEnums; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.util.Log; import android.util.Patterns; import android.widget.Toast; +import androidx.annotation.RequiresApi; + import com.android.bluetooth.BluetoothMethodProxy; 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 com.android.modules.utils.build.SdkLevel; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -124,6 +134,16 @@ public class BluetoothOppLauncherActivity extends Activity { // Browser, share one link goes to this case; if (stream != null && type != null) { Log.v(TAG, "Get ACTION_SEND intent: Uri = " + stream + "; mimetype = " + type); + if (Flags.oppCheckContentUriPermissions() && SdkLevel.isAtLeastV()) { + if (!checkCallerAndSelfContentUriPermission(stream)) { + finish(); + return; + } else { + Log.v(TAG, "Sender has permissions to access Uri = " + stream); + } + } else { + Log.v(TAG, "Did not check sender permissions to Uri = " + stream); + } // Save type/stream, will be used when adding transfer // session to DB. Thread t = @@ -191,6 +211,7 @@ public class BluetoothOppLauncherActivity extends Activity { } else if (action.equals(Intent.ACTION_SEND_MULTIPLE)) { final String mimeType = intent.getType(); final ArrayList uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + final List permittedUris; if (mimeType != null && uris != null) { Log.v( TAG, @@ -198,6 +219,37 @@ public class BluetoothOppLauncherActivity extends Activity { + uris + "\n Type= " + mimeType); + if (Flags.oppCheckContentUriPermissions() && SdkLevel.isAtLeastV()) { + permittedUris = + uris.stream() + .filter(this::checkCallerAndSelfContentUriPermission) + .collect(toList()); + if (permittedUris.isEmpty()) { + Log.w(TAG, "Sender has no permissions to access any uris in " + uris); + finish(); + return; + } else if (!permittedUris.equals(uris)) { + List blockedUris = + uris.stream() + .filter(not(permittedUris::contains)) + .collect(toList()); + Log.w( + TAG, + "Sender has partial permissions to uris. " + + "Permitted uris: " + + permittedUris + + ", " + + "Blocked uris: " + + blockedUris + + ". " + + "Proceeding only with permitted uris."); + } else { + Log.v(TAG, "Sender has permissions to all uris in " + uris); + } + } else { + permittedUris = uris; + Log.v(TAG, "Did not check sender permissions to uris in " + uris); + } Thread t = new Thread( new Runnable() { @@ -208,7 +260,7 @@ public class BluetoothOppLauncherActivity extends Activity { BluetoothOppLauncherActivity.this) .saveSendingFileInfo( mimeType, - uris, + permittedUris, false /* isHandover */, true /* fromExternal */); // Done getting file info..Launch device picker @@ -291,6 +343,33 @@ public class BluetoothOppLauncherActivity extends Activity { } } + /** + * Checks whether the sender (and Bluetooth) have permissions to access the given content uri. + * The result does not differentiate the sender vs. Bluetooth's lack of permissions. + * + * @param uri A uri with a content scheme. + * @return true if both the sender and Bluetooth have permissions, false otherwise. + */ + @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) + private boolean checkCallerAndSelfContentUriPermission(Uri uri) { + boolean hasPermission = false; + try { + hasPermission = + BluetoothMethodProxy.getInstance() + .componentCallerCheckContentUriPermission( + getInitialCaller(), + uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION) + == PackageManager.PERMISSION_GRANTED; + } catch (SecurityException e) { + Log.w(TAG, "Bluetooth does not have permissions to Uri = " + uri, e); + } + if (!hasPermission) { + Log.w(TAG, "Sender does not have permissions to Uri = " + uri); + } + return hasPermission; + } + /* Returns true if Bluetooth is allowed given current airplane mode settings. */ private boolean isBluetoothAllowed() { final ContentResolver resolver = this.getContentResolver(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java index c162cc9562a..bceff44b7a1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java @@ -23,9 +23,14 @@ import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -33,7 +38,11 @@ import android.bluetooth.BluetoothDevicePicker; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; +import android.content.pm.PackageManager; import android.net.Uri; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.sysprop.BluetoothProperties; import androidx.lifecycle.Lifecycle; @@ -45,9 +54,9 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.TestUtils; +import com.android.bluetooth.flags.Flags; import org.junit.After; -import org.junit.Assume; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -59,15 +68,20 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; @MediumTest @RunWith(AndroidJUnit4.class) public class BluetoothOppLauncherActivityTest { + public static final String CONTENT_TYPE = "image/png"; + Context mTargetContext; Intent mIntent; BluetoothMethodProxy mMethodProxy; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock BluetoothOppManager mBluetoothOppManager; @@ -76,9 +90,11 @@ public class BluetoothOppLauncherActivityTest { // Add retry rule to resolve this problem. @Rule public TestUtils.RetryTestRule mRetryTestRule = new TestUtils.RetryTestRule(); + @Rule public SetFlagsRule.ClassRule mSetFlagsClassRule = new SetFlagsRule.ClassRule(); + @Before public void setUp() throws Exception { - Assume.assumeTrue(BluetoothProperties.isProfileOppEnabled().orElse(false)); + assumeTrue(BluetoothProperties.isProfileOppEnabled().orElse(false)); mTargetContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext())); mMethodProxy = spy(BluetoothMethodProxy.getInstance()); @@ -128,6 +144,229 @@ public class BluetoothOppLauncherActivityTest { assertActivityState(activityScenario, Lifecycle.State.DESTROYED); } + @Test + @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSend_checkEnabled_noPermission_doesNotSaveFileInfo() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_DENIED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + String uriString = "content://test.provider/1"; + + ActivityScenario unused = + ActivityScenario.launch(createSendIntent(uriString)); + + verify(mBluetoothOppManager, never()) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriString), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSend_checkEnabled_hasPermission_savesFileInfo() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_GRANTED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + String uriString = "content://test.provider/1"; + + ActivityScenario unused = + ActivityScenario.launch(createSendIntent(uriString)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriString), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSend_checkNotEnabled_noPermission_savesFileInfo() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_DENIED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + String uriString = "content://test.provider/1"; + + ActivityScenario unused = + ActivityScenario.launch(createSendIntent(uriString)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriString), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSend_checkNotEnabled_hasPermission_savesFileInfo() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_GRANTED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + String uriString = "content://test.provider/1"; + + ActivityScenario unused = + ActivityScenario.launch(createSendIntent(uriString)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriString), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + private Intent createSendIntent(String uriString) { + return new Intent(Intent.ACTION_SEND) + .setClass(mTargetContext, BluetoothOppLauncherActivity.class) + .setType(CONTENT_TYPE) + .putExtra(Intent.EXTRA_STREAM, Uri.parse(uriString)); + } + + @Test + @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSendMultiple_checkEnabled_noPermission_doesNotSaveFileInfos() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_DENIED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + List uriList = + Arrays.asList( + Uri.parse("content://test.provider/1"), + Uri.parse("content://test.provider/2")); + + ActivityScenario unused = + ActivityScenario.launch(createSendMultipleIntent(uriList)); + + verify(mBluetoothOppManager, never()) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriList), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSendMultiple_checkEnabled_hasPermission_savesFileInfos() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_GRANTED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + List uriList = + Arrays.asList( + Uri.parse("content://test.provider/1"), + Uri.parse("content://test.provider/2")); + + ActivityScenario unused = + ActivityScenario.launch(createSendMultipleIntent(uriList)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriList), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void + onCreate_withActionSendMultiple_checkEnabled_partialPermission_savesPermittedFileInfo() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_GRANTED, PackageManager.PERMISSION_DENIED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + List uriList = + Arrays.asList( + Uri.parse("content://test.provider/1"), + Uri.parse("content://test.provider/2")); + + ActivityScenario unused = + ActivityScenario.launch(createSendMultipleIntent(uriList)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(Arrays.asList(Uri.parse("content://test.provider/1"))), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSendMultiple_checkNotEnabled_noPermission_savesFileInfos() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_DENIED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + List uriList = + Arrays.asList( + Uri.parse("content://test.provider/1"), + Uri.parse("content://test.provider/2")); + + ActivityScenario unused = + ActivityScenario.launch(createSendMultipleIntent(uriList)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriList), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSendMultiple_checkNotEnabled_hasPermission_savesFileInfos() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_GRANTED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + List uriList = + Arrays.asList( + Uri.parse("content://test.provider/1"), + Uri.parse("content://test.provider/2")); + + ActivityScenario unused = + ActivityScenario.launch(createSendMultipleIntent(uriList)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriList), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + @Test + @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + public void onCreate_withActionSendMultiple_checkNotEnabled_partialPermission_savesFileInfos() + throws Exception { + doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); + doReturn(PackageManager.PERMISSION_GRANTED, PackageManager.PERMISSION_DENIED) + .when(mMethodProxy) + .componentCallerCheckContentUriPermission(any(), any(), anyInt()); + List uriList = + Arrays.asList( + Uri.parse("content://test.provider/1"), + Uri.parse("content://test.provider/2")); + + ActivityScenario unused = + ActivityScenario.launch(createSendMultipleIntent(uriList)); + + verify(mBluetoothOppManager) + .saveSendingFileInfo( + eq(CONTENT_TYPE), eq(uriList), + anyBoolean() /* isHandover */, anyBoolean() /* fromExternal */); + } + + private Intent createSendMultipleIntent(List uriList) { + return new Intent(Intent.ACTION_SEND_MULTIPLE) + .setClass(mTargetContext, BluetoothOppLauncherActivity.class) + .setType(CONTENT_TYPE) + .putParcelableArrayListExtra(Intent.EXTRA_STREAM, new ArrayList<>(uriList)); + } + @Test public void onCreate_withActionOpen_sendBroadcast() throws Exception { mIntent.setAction(Constants.ACTION_OPEN); -- GitLab From 72a8ae06a92098ddf58d620dd0fe79b2fa076ba2 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 29 Oct 2024 21:03:41 +0100 Subject: [PATCH 547/875] Fix state machine stuck after disconnection 1. Connect on LE transport to dual mode device 2. Initiate pairing, control block will contain RPA as remote address 2. Obtain Identity Address, perform CTKD, generate Classic keys 3. Connect on Classic transport, start encryption 4. Encryption success, try reading the key size 5. Suddenly, connection times out, disconnection event is received Current behavior: Disconnection is not matched with the pairing device address. We stay stuck in pairing state. With fix: We check if RPA from control block belongs to same device that disconnected, and if so pass this event to state machine that would clean up the control block. Bug: 376306092 Bug: 369095269 Test: none Flag: com.android.bluetooth.flags. smp_state_machine_stuck_after_disconnection_fix Change-Id: I53bc0a4a8ac124dc20b4e9a1a30bb579653ef5a1 --- system/stack/smp/smp_l2c.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/system/stack/smp/smp_l2c.cc b/system/stack/smp/smp_l2c.cc index 04b6249a95e..219cb723f71 100644 --- a/system/stack/smp/smp_l2c.cc +++ b/system/stack/smp/smp_l2c.cc @@ -263,7 +263,19 @@ 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) { - return; + 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 */ + if (p_dev_rec == nullptr || p_dev_rec->RemoteAddress() != p_cb->pairing_bda) { + return; + } } /* Check if we already finished SMP pairing over LE, and are waiting to -- GitLab From 29cb8d036be1014e9e27c2db7161d481dc7a9051 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 4 Nov 2024 12:16:19 -0800 Subject: [PATCH 548/875] Obfuscate address in AdapterProperties dump Bug: 376920094 Fix: 376920094 Test: m . Flag: Exempt trivial dump edit Change-Id: I9b8d0400931992e4c8060ffbfe1209e7edbf2547 --- .../android/bluetooth/btservice/AdapterProperties.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index 9c3118bea3a..851df2c0304 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -30,6 +30,7 @@ import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSap; +import android.bluetooth.BluetoothUtils; import android.bluetooth.BufferConstraint; import android.bluetooth.BufferConstraints; import android.content.Context; @@ -1077,7 +1078,7 @@ class AdapterProperties { protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { writer.println(TAG); writer.println(" " + "Name: " + getName()); - writer.println(" " + "Address: " + Utils.getAddressStringFromByte(mAddress)); + writer.println(" " + "Address: " + Utils.getRedactedAddressStringFromByte(mAddress)); writer.println(" " + "ConnectionState: " + dumpConnectionState(getConnectionState())); writer.println(" " + "State: " + BluetoothAdapter.nameForState(getState())); writer.println(" " + "MaxConnectedAudioDevices: " + getMaxConnectedAudioDevices()); @@ -1096,7 +1097,7 @@ class AdapterProperties { if (brEdrAddress.equals(address)) { writer.println( " " - + address + + BluetoothUtils.toAnonymizedAddress(address) + " [" + dumpDeviceType(mRemoteDevices.getType(device)) + "][ 0x" @@ -1105,9 +1106,9 @@ class AdapterProperties { + Utils.getName(device)); } else { sb.append(" ") - .append(address) + .append(BluetoothUtils.toAnonymizedAddress(address)) .append(" => ") - .append(brEdrAddress) + .append(BluetoothUtils.toAnonymizedAddress(brEdrAddress)) .append(" [") .append(dumpDeviceType(mRemoteDevices.getType(device))) .append("][ 0x") -- GitLab From 605bc9acad352320d59b96d6f60003393a1703c3 Mon Sep 17 00:00:00 2001 From: Arjun Dhaliwal Date: Mon, 4 Nov 2024 10:56:54 -0800 Subject: [PATCH 549/875] osi: Use CLOCK_MONOTONIC on platforms that can't wake on BT Some devices (such as TVs) are not wired up to be woken by the controller. These devices might run into unforeseen issues going to sleep with timers armed. This commit adds a sysprop (bluetooth.hardware.wakeup_supported) to specify that the platform is wired up like that, and makes all alarms on those platforms monotonic, so they do not count up during suspend. Bug: 343826774 Test: m -j128 com.android.btservices & QA testing Flag: EXEMPT, behaviour controlled by sysprop Change-Id: Ie720ea3c20cba317eb3536c49604c9c8b9c2d80f --- sysprop/Android.bp | 1 + sysprop/BUILD.gn | 1 + .../android_bluetooth_sysprop.h | 1 + sysprop/hardware.sysprop | 10 ++++++++++ system/audio_hal_interface/Android.bp | 2 ++ system/audio_hal_interface/fuzzer/Android.bp | 1 + system/audio_hearing_aid_hw/Android.bp | 1 + system/bta/Android.bp | 6 ++++++ system/btcore/Android.bp | 1 + system/btcore/fuzzer/Android.bp | 1 + system/btif/Android.bp | 2 ++ system/common/Android.bp | 2 ++ system/device/Android.bp | 1 + system/device/fuzzer/Android.bp | 1 + system/hci/Android.bp | 1 + system/osi/Android.bp | 2 ++ system/osi/BUILD.gn | 2 ++ system/osi/src/alarm.cc | 10 +++++++++- system/osi/test/fuzzers/alarm/Android.bp | 1 + system/osi/test/fuzzers/allocator/Android.bp | 1 + system/osi/test/fuzzers/fixed_queue/Android.bp | 1 + system/osi/test/fuzzers/future/Android.bp | 1 + system/osi/test/fuzzers/list/Android.bp | 1 + system/osi/test/fuzzers/ringbuffer/Android.bp | 1 + system/profile/avrcp/Android.bp | 1 + system/stack/Android.bp | 17 +++++++++++++++++ system/stack/test/fuzzers/Android.bp | 1 + system/test/headless/Android.bp | 1 + system/types/Android.bp | 1 + 29 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 sysprop/hardware.sysprop diff --git a/sysprop/Android.bp b/sysprop/Android.bp index 1b72eb4cb7a..e9d820b2f14 100644 --- a/sysprop/Android.bp +++ b/sysprop/Android.bp @@ -12,6 +12,7 @@ sysprop_library { "bta.sysprop", "device_id.sysprop", "gap.sysprop", + "hardware.sysprop", "hfp.sysprop", ], property_owner: "Platform", diff --git a/sysprop/BUILD.gn b/sysprop/BUILD.gn index 407b7a88fcc..9cdbf485306 100644 --- a/sysprop/BUILD.gn +++ b/sysprop/BUILD.gn @@ -8,6 +8,7 @@ sysprop("libcom.android.sysprop.bluetooth") { "bta.sysprop", "device_id.sysprop", "gap.sysprop", + "hardware.sysprop", "hfp.sysprop", ] deps = [ "//bt/floss/android-base:android-base" ] diff --git a/sysprop/exported_include/android_bluetooth_sysprop.h b/sysprop/exported_include/android_bluetooth_sysprop.h index 8d5122d8e22..24053123ac6 100644 --- a/sysprop/exported_include/android_bluetooth_sysprop.h +++ b/sysprop/exported_include/android_bluetooth_sysprop.h @@ -22,4 +22,5 @@ #include #include #include +#include #include diff --git a/sysprop/hardware.sysprop b/sysprop/hardware.sysprop new file mode 100644 index 00000000000..07c09134bb6 --- /dev/null +++ b/sysprop/hardware.sysprop @@ -0,0 +1,10 @@ +module: "android.sysprop.bluetooth.hardware" +owner: Platform + +prop { + api_name: "wakeup_supported" + type: Boolean + scope: Internal + access: Readonly + prop_name: "bluetooth.hardware.wakeup_supported" +} diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index 987b8592146..f485de80aa9 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -187,6 +187,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libflagtest", "libfmq", "libgmock", @@ -246,6 +247,7 @@ cc_defaults { "libbtif", "libbtif-core", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libcutils", "libevent", "libg722codec", diff --git a/system/audio_hal_interface/fuzzer/Android.bp b/system/audio_hal_interface/fuzzer/Android.bp index 93a734b02fa..9a32f910e3e 100644 --- a/system/audio_hal_interface/fuzzer/Android.bp +++ b/system/audio_hal_interface/fuzzer/Android.bp @@ -83,6 +83,7 @@ cc_defaults { "libbtif", "libbtif-core", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libcutils", "libevent", "libexpresslog", diff --git a/system/audio_hearing_aid_hw/Android.bp b/system/audio_hearing_aid_hw/Android.bp index 19694cac774..fa17bac2747 100644 --- a/system/audio_hearing_aid_hw/Android.bp +++ b/system/audio_hearing_aid_hw/Android.bp @@ -59,6 +59,7 @@ cc_test { static_libs: [ "audio.hearing_aid.default", "libbluetooth_log", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], min_sdk_version: "29", diff --git a/system/bta/Android.bp b/system/bta/Android.bp index ad4e798016f..8efc0fdba0d 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -447,6 +447,7 @@ cc_test { "libbt-platform-protos-lite", "libbtcore", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libgmock", "libosi", "libstatslog_bt", @@ -563,6 +564,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libcutils", "libgmock", "libosi", @@ -610,6 +612,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libgmock", "libosi", ], @@ -823,6 +826,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libflatbuffers-cpp", "libgmock", @@ -933,6 +937,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libflatbuffers-cpp", "libgmock", @@ -1022,6 +1027,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libflagtest", "libflatbuffers-cpp", diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp index 96da5abf573..dc6df095adb 100644 --- a/system/btcore/Android.bp +++ b/system/btcore/Android.bp @@ -110,6 +110,7 @@ cc_test { "libbluetooth_log", "libbtcore", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], host_supported: true, diff --git a/system/btcore/fuzzer/Android.bp b/system/btcore/fuzzer/Android.bp index 746a3b31b50..c9300866944 100644 --- a/system/btcore/fuzzer/Android.bp +++ b/system/btcore/fuzzer/Android.bp @@ -38,6 +38,7 @@ cc_defaults { "libbt-common", "libbtcore", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "liblog", "libmodpb64", diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 4aa018563be..649c08e941f 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -396,6 +396,7 @@ cc_test { "libbluetooth_gd", "libbluetooth_log", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], shared_libs: [ @@ -430,6 +431,7 @@ cc_test { "libbluetooth-types", "libbluetooth_log", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], shared_libs: [ diff --git a/system/common/Android.bp b/system/common/Android.bp index 3009c77ec0e..4bc0bebf2d6 100644 --- a/system/common/Android.bp +++ b/system/common/Android.bp @@ -140,6 +140,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "libosi", @@ -168,6 +169,7 @@ cc_benchmark { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libosi", ], diff --git a/system/device/Android.bp b/system/device/Android.bp index 4753441a666..1a5d72ae459 100644 --- a/system/device/Android.bp +++ b/system/device/Android.bp @@ -68,6 +68,7 @@ cc_test { "libbtcore", "libbtdevice", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], header_libs: ["libbluetooth_headers"], diff --git a/system/device/fuzzer/Android.bp b/system/device/fuzzer/Android.bp index 0b5e6c1296d..a466d78d6b2 100644 --- a/system/device/fuzzer/Android.bp +++ b/system/device/fuzzer/Android.bp @@ -52,6 +52,7 @@ cc_fuzz { "libbtcore", "libbtdevice", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libgmock", "libosi", ], diff --git a/system/hci/Android.bp b/system/hci/Android.bp index 5e493288a7b..e4e01066065 100644 --- a/system/hci/Android.bp +++ b/system/hci/Android.bp @@ -66,6 +66,7 @@ cc_test { "libbluetooth_log", "libbt-hci", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], sanitize: { diff --git a/system/osi/Android.bp b/system/osi/Android.bp index aeabc7ad182..4806d61985e 100644 --- a/system/osi/Android.bp +++ b/system/osi/Android.bp @@ -92,6 +92,7 @@ cc_library_static { "libaconfig_storage_read_api_cc", "libbluetooth_log", "libbt-platform-protos-lite", + "libcom.android.sysprop.bluetooth.wrapped", "server_configurable_flags", ], } @@ -145,6 +146,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "libosi", diff --git a/system/osi/BUILD.gn b/system/osi/BUILD.gn index fdd2736fab4..ffc3dfcac88 100644 --- a/system/osi/BUILD.gn +++ b/system/osi/BUILD.gn @@ -55,6 +55,7 @@ static_library("osi") { deps = [ "//bt/flags:bluetooth_flags_c_lib", + "//bt/sysprop:libcom.android.sysprop.bluetooth", "//bt/system/common", ] @@ -92,6 +93,7 @@ if (use.test) { ] deps = [ + "//bt/sysprop:libcom.android.sysprop.bluetooth", "//bt/system/osi", ] diff --git a/system/osi/src/alarm.cc b/system/osi/src/alarm.cc index a280442bb0b..c1a1b6da106 100644 --- a/system/osi/src/alarm.cc +++ b/system/osi/src/alarm.cc @@ -20,6 +20,7 @@ #include "osi/include/alarm.h" +#include #include #include #include @@ -312,6 +313,13 @@ static bool lazy_initialize(void) { bool timer_initialized = false; bool wakeup_timer_initialized = false; + // some platforms are not wired up to be woken up by the controller. + // on those platforms, if we go to sleep with a timer armed, it will + // continue counting during sleep. to prevent unwanted timer fires on + // those platforms, use CLOCK_MONOTONIC and don't count up during sleep. + bool wakeup_supported = android::sysprop::bluetooth::hardware::wakeup_supported().value_or(true); + clockid_t alarm_clockid = wakeup_supported ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC; + std::lock_guard lock(alarms_mutex); alarms = list_new(NULL); @@ -325,7 +333,7 @@ static bool lazy_initialize(void) { } timer_initialized = true; - if (!timer_create_internal(CLOCK_BOOTTIME_ALARM, &wakeup_timer)) { + if (!timer_create_internal(alarm_clockid, &wakeup_timer)) { if (!timer_create_internal(CLOCK_BOOTTIME, &wakeup_timer)) { goto error; } diff --git a/system/osi/test/fuzzers/alarm/Android.bp b/system/osi/test/fuzzers/alarm/Android.bp index e1108e87312..3af1096546e 100644 --- a/system/osi/test/fuzzers/alarm/Android.bp +++ b/system/osi/test/fuzzers/alarm/Android.bp @@ -25,6 +25,7 @@ cc_fuzz { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libgmock", "libosi", ], diff --git a/system/osi/test/fuzzers/allocator/Android.bp b/system/osi/test/fuzzers/allocator/Android.bp index f4874ff3223..36b5ee4ae6f 100644 --- a/system/osi/test/fuzzers/allocator/Android.bp +++ b/system/osi/test/fuzzers/allocator/Android.bp @@ -18,6 +18,7 @@ cc_fuzz { "libbase", "libbluetooth_log", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "liblog", "libosi", ], diff --git a/system/osi/test/fuzzers/fixed_queue/Android.bp b/system/osi/test/fuzzers/fixed_queue/Android.bp index 8758597a558..02ad1896bd8 100644 --- a/system/osi/test/fuzzers/fixed_queue/Android.bp +++ b/system/osi/test/fuzzers/fixed_queue/Android.bp @@ -22,6 +22,7 @@ cc_fuzz { static_libs: [ "libbluetooth_log", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], } diff --git a/system/osi/test/fuzzers/future/Android.bp b/system/osi/test/fuzzers/future/Android.bp index 46673e2659e..c96dd2f9844 100644 --- a/system/osi/test/fuzzers/future/Android.bp +++ b/system/osi/test/fuzzers/future/Android.bp @@ -22,6 +22,7 @@ cc_fuzz { static_libs: [ "libbluetooth_log", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", ], } diff --git a/system/osi/test/fuzzers/list/Android.bp b/system/osi/test/fuzzers/list/Android.bp index 5c8f15e81eb..bc5dd9a66e3 100644 --- a/system/osi/test/fuzzers/list/Android.bp +++ b/system/osi/test/fuzzers/list/Android.bp @@ -18,6 +18,7 @@ cc_fuzz { "libbase", "libbluetooth_log", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "liblog", "libosi", ], diff --git a/system/osi/test/fuzzers/ringbuffer/Android.bp b/system/osi/test/fuzzers/ringbuffer/Android.bp index bbba16690fa..08d308c70ca 100644 --- a/system/osi/test/fuzzers/ringbuffer/Android.bp +++ b/system/osi/test/fuzzers/ringbuffer/Android.bp @@ -18,6 +18,7 @@ cc_fuzz { "libbase", "libbluetooth_log", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "liblog", "libosi", ], diff --git a/system/profile/avrcp/Android.bp b/system/profile/avrcp/Android.bp index 133d2a47129..8db8f11b2aa 100644 --- a/system/profile/avrcp/Android.bp +++ b/system/profile/avrcp/Android.bp @@ -81,6 +81,7 @@ cc_test { "libbluetooth_log", "libbtdevice", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libcutils", "libevent", "libgmock", diff --git a/system/stack/Android.bp b/system/stack/Android.bp index cb987debfc1..7cffba529fd 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -833,6 +833,7 @@ cc_test { "libbtif", "libbtif-core", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libflags_rust_cpp_bridge", "libfmq", "libg722codec", @@ -934,6 +935,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1023,6 +1025,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1158,6 +1161,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1229,6 +1233,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1299,6 +1304,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1408,6 +1414,7 @@ cc_test { "libbt-sbc-decoder", "libbt-sbc-encoder", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libgmock", "liblog", "libopus", @@ -1459,6 +1466,7 @@ cc_test { "libbluetooth_log", "libbt-common", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "liblog", "libosi", ], @@ -1523,6 +1531,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1581,6 +1590,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libgmock", "liblog", "libosi", @@ -1657,6 +1667,7 @@ cc_test { "libbt-common", "libbt-platform-protos-lite", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1845,6 +1856,7 @@ cc_test { "libbtdevice", "libbte", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libgmock", "liblog", "libosi", @@ -1904,6 +1916,7 @@ cc_test { "libbtdevice", "libbte", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -1980,6 +1993,7 @@ cc_test { "libbt-platform-protos-lite", "libbtdevice", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -2069,6 +2083,7 @@ cc_test { "libbt-platform-protos-lite", "libbtdevice", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libflagtest", "libgmock", @@ -2162,6 +2177,7 @@ cc_test { "libbt-platform-protos-lite", "libbtdevice", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libgmock", "liblog", @@ -2256,6 +2272,7 @@ cc_test { "libbt-platform-protos-lite", "libbtdevice", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libcutils", "libevent", "libgmock", diff --git a/system/stack/test/fuzzers/Android.bp b/system/stack/test/fuzzers/Android.bp index 3c74de632df..a0b7947b1ee 100644 --- a/system/stack/test/fuzzers/Android.bp +++ b/system/stack/test/fuzzers/Android.bp @@ -61,6 +61,7 @@ cc_defaults { "libbte", "libbtif", "libbtif-core", + "libcom.android.sysprop.bluetooth.wrapped", "libexpresslog", "libflags_rust_cpp_bridge", "libg722codec", diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp index 846f9ec4ccc..118178199a8 100644 --- a/system/test/headless/Android.bp +++ b/system/test/headless/Android.bp @@ -105,6 +105,7 @@ cc_binary { "libbtif", "libbtif-core", "libchrome", + "libcom.android.sysprop.bluetooth.wrapped", "libevent", "libflags_rust_cpp_bridge", "libflatbuffers-cpp", diff --git a/system/types/Android.bp b/system/types/Android.bp index 4bff11709b1..4201bafca41 100644 --- a/system/types/Android.bp +++ b/system/types/Android.bp @@ -58,6 +58,7 @@ cc_test { "libbase", "libbluetooth-types", "libbluetooth_log", + "libcom.android.sysprop.bluetooth.wrapped", "libosi", // strlcpy ], test_suites: ["general-tests"], -- GitLab From 693806af40503e055d4c90a3dfe9f30f63078da1 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 23 Oct 2024 20:45:34 +0000 Subject: [PATCH 550/875] system/btif: clang-tidy fixes Bug: 374984156 Test: m com.android.btservices Test: WITH_TIDY_FLAGS=--fix m libbtif Flag: EXEMPT, no logical change Change-Id: I1f89824743dd57ca6961c513e460603623d1f117 --- .clang-tidy | 18 ++++++- Android.bp | 5 ++ OWNERS | 2 +- system/btif/avrcp/avrcp_service.cc | 17 ++++++ system/btif/co/bta_av_co.cc | 8 ++- system/btif/co/bta_av_co_peer.cc | 11 ++++ system/btif/co/bta_hh_co.cc | 14 ++++- system/btif/co/bta_pan_co.cc | 13 ++--- system/btif/src/bluetooth.cc | 56 +++++++++++--------- system/btif/src/btif_a2dp.cc | 7 +-- system/btif/src/btif_a2dp_sink.cc | 10 +++- system/btif/src/btif_a2dp_source.cc | 28 +++++++--- system/btif/src/btif_av.cc | 21 +++++++- system/btif/src/btif_avrcp_audio_track.cc | 8 ++- system/btif/src/btif_csis_client.cc | 8 +-- system/btif/src/btif_has_client.cc | 8 +-- system/btif/src/btif_hd.cc | 6 +++ system/btif/src/btif_hearing_aid.cc | 6 ++- system/btif/src/btif_hf.cc | 13 +++++ system/btif/src/btif_hf_client.cc | 6 ++- system/btif/src/btif_hh.cc | 18 ++++++- system/btif/src/btif_iot_config.cc | 7 +++ system/btif/src/btif_le_audio.cc | 5 +- system/btif/src/btif_le_audio_broadcaster.cc | 8 ++- system/btif/src/btif_pan.cc | 13 ++++- system/btif/src/btif_profile_queue.cc | 3 ++ system/btif/src/btif_profile_storage.cc | 7 +++ system/btif/src/btif_rc.cc | 15 +++--- system/btif/src/btif_vc.cc | 8 ++- 29 files changed, 272 insertions(+), 77 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index df0d649f1fe..9dc029bd56d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,4 +1,18 @@ --- CheckOptions: - - key: misc-include-cleaner.IgnoreHeaders - value: (fmt/.*|bits/pthread_types\.h) + - key: misc-include-cleaner.IgnoreHeaders + value: "(\ + fmt/.*|\ + bits/.*.h|\ + asm-generic/.*.h|\ + sys/poll.h|\ + sys/endian.h|\ + sys/ioctl.h|\ + arpa/inet.h|\ + linux/if.h|\ + linux/sockios.h|\ + netinet/in.h|\ + osi/include/compat.h|\ + android_bluetooth_sysprop.h|\ + hfp.sysprop.h|\ + __chrono/duration.h)" diff --git a/Android.bp b/Android.bp index 71d6d402c26..216ffdc51f9 100644 --- a/Android.bp +++ b/Android.bp @@ -85,6 +85,11 @@ bluetooth_tidy_checks = [ // This check implements detection of local variables which could be declared // as const but are not. "-misc-const-correctness", + + // Finds classes that contain non-static data members in addition to user-declared + // non-static member functions and diagnose all data members declared with a + // non-public access specifier. + "-misc-non-private-member-variables-in-classes", ] // This default tidy checks that will be run against all the cc targets diff --git a/OWNERS b/OWNERS index 4df6c9967e0..491c4d0a382 100644 --- a/OWNERS +++ b/OWNERS @@ -9,7 +9,7 @@ okamil@google.com #{LAST_RESORT_SUGGESTION} # Per-file ownership # Build files / test_config / presubmit / preupload / linter file -per-file PREUPLOAD.cfg,TEST_MAPPING,*.bp,*.xml,pyrightconfig.json=file:/OWNERS_build +per-file PREUPLOAD.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 diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc index 712f6e0b8f4..a1a4574d041 100644 --- a/system/btif/avrcp/avrcp_service.cc +++ b/system/btif/avrcp/avrcp_service.cc @@ -21,8 +21,13 @@ #include #include #include +#include +#include +#include +#include #include +#include #include #include #include @@ -31,14 +36,26 @@ #include "bta/sys/bta_sys.h" #include "btif/include/btif_av.h" #include "btif/include/btif_common.h" +#include "hardware/avrcp/avrcp.h" +#include "hardware/avrcp/avrcp_common.h" +#include "internal_include/bt_target.h" #include "osi/include/osi.h" #include "profile/avrcp/avrcp_config.h" +#include "profile/avrcp/avrcp_internal.h" +#include "profile/avrcp/avrcp_sdp_records.h" +#include "profile/avrcp/avrcp_sdp_service.h" #include "profile/avrcp/device.h" #include "stack/include/a2dp_api.h" +#include "stack/include/avct_api.h" +#include "stack/include/avrc_api.h" +#include "stack/include/avrc_defs.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_uuid16.h" #include "stack/include/main_thread.h" #include "stack/include/sdp_api.h" +#include "stack/include/sdp_callback.h" +#include "stack/include/sdpdefs.h" +#include "stack/sdp/sdp_discovery_db.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index de0f9066046..5cd91c8ac0b 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -29,7 +29,11 @@ #include #include +#include +#include +#include +#include #include #include #include @@ -42,16 +46,16 @@ #include "btif/include/btif_a2dp_source.h" #include "btif/include/btif_av.h" #include "btif/include/btif_av_co.h" +#include "device/include/device_iot_conf_defs.h" #include "device/include/device_iot_config.h" #include "include/hardware/bt_av.h" -#include "internal_include/bt_trace.h" +#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/a2dp_codec_api.h" #include "stack/include/a2dp_constants.h" #include "stack/include/a2dp_ext.h" #include "stack/include/avdt_api.h" #include "stack/include/bt_hdr.h" -#include "stack/include/bt_types.h" #include "stack/include/bt_uuid16.h" #include "types/raw_address.h" diff --git a/system/btif/co/bta_av_co_peer.cc b/system/btif/co/bta_av_co_peer.cc index 5f9356cd4ca..4bc9544db87 100644 --- a/system/btif/co/bta_av_co_peer.cc +++ b/system/btif/co/bta_av_co_peer.cc @@ -20,7 +20,18 @@ #include +#include +#include +#include +#include +#include + #include "bta/include/bta_av_api.h" +#include "hardware/bt_av.h" +#include "stack/include/a2dp_codec_api.h" +#include "stack/include/avdt_api.h" +#include "stack/include/bt_types.h" +#include "types/raw_address.h" using namespace bluetooth; diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index f60a7016481..12735b6c726 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -18,29 +18,41 @@ #include "bta_hh_co.h" +#include #include #include +#include +#include #include #include #include -#include +#include #include #include +#include #include +#include #include +#include +#include +#include #include "bta_hh_api.h" #include "btif_config.h" #include "btif_hh.h" +#include "hardware/bt_hh.h" #include "hci/controller_interface.h" #include "main/shim/entry.h" +#include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" +#include "osi/include/fixed_queue.h" #include "osi/include/osi.h" #include "osi/include/properties.h" #include "storage/config_keys.h" #include "types/raw_address.h" + #define BTA_HH_NV_LOAD_MAX 16 static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; #define BTA_HH_CACHE_REPORT_VERSION 1 diff --git a/system/btif/co/bta_pan_co.cc b/system/btif/co/bta_pan_co.cc index db84d8bd343..0bdcae371e6 100644 --- a/system/btif/co/bta_pan_co.cc +++ b/system/btif/co/bta_pan_co.cc @@ -26,18 +26,15 @@ ******************************************************************************/ #include "bta_pan_co.h" -#include -#include -#include +#include -#include "bta_api.h" -#include "bta_pan_api.h" +#include +#include + +#include "bta/include/bta_pan_api.h" #include "bta_pan_ci.h" #include "btif_pan_internal.h" -#include "btif_sock_thread.h" -#include "btif_util.h" #include "osi/include/allocator.h" -#include "pan_api.h" #include "stack/include/bt_hdr.h" #include "types/raw_address.h" diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 906a8bd732a..e4f3001b0f7 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -27,32 +27,23 @@ #define LOG_TAG "bt_btif" +#include "hardware/bluetooth.h" + +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "audio_hal_interface/a2dp_encoding.h" -#include "bta/hh/bta_hh_int.h" // for HID HACK profile methods + +#include +#include +#include +#include +#include +#include + +#include "bta/hh/bta_hh_int.h" #include "bta/include/bta_api.h" #include "bta/include/bta_ar_api.h" +#include "bta/include/bta_av_api.h" #include "bta/include/bta_csis_api.h" #include "bta/include/bta_has_api.h" #include "bta/include/bta_hearing_aid_api.h" @@ -66,6 +57,7 @@ #include "btif/include/btif_api.h" #include "btif/include/btif_av.h" #include "btif/include/btif_bqr.h" +#include "btif/include/btif_common.h" #include "btif/include/btif_config.h" #include "btif/include/btif_debug_conn.h" #include "btif/include/btif_dm.h" @@ -91,11 +83,22 @@ #include "device/include/esco_parameters.h" #include "device/include/interop.h" #include "device/include/interop_config.h" +#include "hardware/avrcp/avrcp.h" +#include "hardware/bt_csis.h" +#include "hardware/bt_gatt.h" +#include "hardware/bt_has.h" +#include "hardware/bt_hearing_aid.h" +#include "hardware/bt_le_audio.h" +#include "hardware/bt_rc.h" +#include "hardware/bt_sdp.h" +#include "hardware/bt_sock.h" +#include "hardware/bt_vc.h" #include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" #include "os/parameter_provider.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" +#include "osi/include/properties.h" #include "osi/include/stack_power_telemetry.h" #include "osi/include/wakelock.h" #include "stack/btm/btm_dev.h" @@ -104,9 +107,14 @@ #include "stack/include/a2dp_api.h" #include "stack/include/avct_api.h" #include "stack/include/avdt_api.h" +#include "stack/include/avrc_api.h" +#include "stack/include/bnep_api.h" +#include "stack/include/bt_name.h" +#include "stack/include/bt_octets.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_status.h" #include "stack/include/gatt_api.h" +#include "stack/include/hcidefs.h" #include "stack/include/hfp_lc3_decoder.h" #include "stack/include/hfp_lc3_encoder.h" #include "stack/include/hfp_msbc_decoder.h" @@ -117,6 +125,7 @@ #include "stack/include/pan_api.h" #include "stack/include/sdp_api.h" #include "storage/config_keys.h" +#include "types/ble_address_with_type.h" #include "types/bt_transport.h" #include "types/raw_address.h" @@ -125,7 +134,6 @@ using bluetooth::csis::CsisClientInterface; using bluetooth::has::HasClientInterface; -using bluetooth::hearing_aid::HearingAidInterface; using bluetooth::le_audio::LeAudioBroadcasterInterface; using bluetooth::le_audio::LeAudioClientInterface; using bluetooth::vc::VolumeControlInterface; diff --git a/system/btif/src/btif_a2dp.cc b/system/btif/src/btif_a2dp.cc index 01127c3a68d..f7632bfa9dd 100644 --- a/system/btif/src/btif_a2dp.cc +++ b/system/btif/src/btif_a2dp.cc @@ -23,17 +23,18 @@ #include #include -#include + +#include +#include #include "audio_hal_interface/a2dp_encoding.h" +#include "avdt_api.h" #include "bta_av_api.h" #include "btif_a2dp_sink.h" #include "btif_a2dp_source.h" #include "btif_av.h" #include "btif_av_co.h" #include "btif_hf.h" -#include "btif_util.h" -#include "internal_include/bt_trace.h" #include "types/raw_address.h" using namespace bluetooth; diff --git a/system/btif/src/btif_a2dp_sink.cc b/system/btif/src/btif_a2dp_sink.cc index ec9365a1b47..2d214b05218 100644 --- a/system/btif/src/btif_a2dp_sink.cc +++ b/system/btif/src/btif_a2dp_sink.cc @@ -26,15 +26,23 @@ #include #include +#include +#include +#include +#include #include #include +#include +#include "a2dp_api.h" +#include "a2dp_codec_api.h" +#include "avdt_api.h" +#include "bta_av_api.h" #include "btif/include/btif_av.h" #include "btif/include/btif_av_co.h" #include "btif/include/btif_avrcp_audio_track.h" #include "btif/include/btif_util.h" // CASE_RETURN_STR #include "common/message_loop_thread.h" -#include "hardware/bt_av.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/fixed_queue.h" diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index ae296a4249b..3f3bc5a4790 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -20,22 +20,29 @@ #define LOG_TAG "bluetooth-a2dp" #define ATRACE_TAG ATRACE_TAG_AUDIO -#include +#include "btif_a2dp_source.h" + +#include #include #include -#ifdef __ANDROID__ -#include -#endif - -#include -#include +#include #include +#include +#include +#include #include +#include +#include +#include +#include "a2dp_api.h" +#include "a2dp_codec_api.h" #include "audio_hal_interface/a2dp_encoding.h" +#include "avdt_api.h" +#include "bt_transport.h" +#include "bta_av_api.h" #include "bta_av_ci.h" -#include "btif_a2dp_source.h" #include "btif_av.h" #include "btif_av_co.h" #include "btif_common.h" @@ -46,6 +53,7 @@ #include "common/metrics.h" #include "common/repeating_timer.h" #include "common/time_util.h" +#include "hardware/bt_av.h" #include "osi/include/allocator.h" #include "osi/include/fixed_queue.h" #include "osi/include/wakelock.h" @@ -58,6 +66,10 @@ #include "stack/include/main_thread.h" #include "types/raw_address.h" +#ifdef __ANDROID__ +#include +#endif + using bluetooth::audio::a2dp::BluetoothAudioStatus; using bluetooth::common::A2dpSessionMetrics; using bluetooth::common::BluetoothMetricsLogger; diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 2132172e480..8fa008acdd5 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -20,22 +20,33 @@ #include "btif/include/btif_av.h" -#include #include #include #include #include #include #include +#include +#include #include +#include +#include #include +#include +#include #include #include +#include +#include #include +#include #include #include "audio_hal_interface/a2dp_encoding.h" +#include "bta/include/bta_api.h" +#include "bta/include/bta_api_data_types.h" +#include "bta/include/bta_av_api.h" #include "btif/avrcp/avrcp_service.h" #include "btif/include/btif_a2dp.h" #include "btif/include/btif_a2dp_sink.h" @@ -49,17 +60,23 @@ #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 "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" +#include "stack/include/a2dp_codec_api.h" +#include "stack/include/avdt_api.h" #include "stack/include/avrc_api.h" +#include "stack/include/avrc_defs.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_uuid16.h" #include "stack/include/btm_ble_api.h" +#include "stack/include/btm_ble_api_types.h" #include "stack/include/btm_log_history.h" #include "stack/include/main_thread.h" #include "types/raw_address.h" @@ -3217,7 +3234,7 @@ static void btif_av_handle_bta_av_event(uint8_t peer_sep, const BtifAvEvent& bti } break; } else { - FALLTHROUGH_INTENDED; + [[fallthrough]]; } } case BTA_AV_OFFLOAD_START_RSP_EVT: { diff --git a/system/btif/src/btif_avrcp_audio_track.cc b/system/btif/src/btif_avrcp_audio_track.cc index 7a3d27f6a54..fc249636813 100644 --- a/system/btif/src/btif_avrcp_audio_track.cc +++ b/system/btif/src/btif_avrcp_audio_track.cc @@ -25,17 +25,15 @@ #include #include -#include #include +#include +#include #include -#include "internal_include/bt_target.h" - // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" -using namespace android; using namespace bluetooth; typedef struct { @@ -80,7 +78,7 @@ void BtifAvrcpAudioErrorHandle() { trackHolder->stream = stream; - if (trackHolder != NULL && trackHolder->stream != NULL) { + if (trackHolder != nullptr && trackHolder->stream != NULL) { log::debug("AAudio Error handle: restart A2dp Sink AudioTrack"); AAudioStream_requestStart(trackHolder->stream); } diff --git a/system/btif/src/btif_csis_client.cc b/system/btif/src/btif_csis_client.cc index 2a745ca109e..65811c6abe8 100644 --- a/system/btif/src/btif_csis_client.cc +++ b/system/btif/src/btif_csis_client.cc @@ -18,21 +18,23 @@ #include #include #include -#include #include +#include +#include + #include "bind_helpers.h" +#include "bluetooth/uuid.h" #include "bta_csis_api.h" #include "btif_common.h" #include "btif_profile_storage.h" +#include "raw_address.h" #include "stack/include/main_thread.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" using base::Bind; -using base::Owned; -using base::Passed; using base::Unretained; using bluetooth::csis::ConnectionState; using bluetooth::csis::CsisClientCallbacks; diff --git a/system/btif/src/btif_has_client.cc b/system/btif/src/btif_has_client.cc index 18ae5478cd0..c44485d70b0 100644 --- a/system/btif/src/btif_has_client.cc +++ b/system/btif/src/btif_has_client.cc @@ -17,23 +17,25 @@ #include #include -#include #include +#include +#include #include +#include +#include #include #include "bta_has_api.h" #include "btif_common.h" #include "btif_profile_storage.h" +#include "raw_address.h" #include "stack/include/main_thread.h" // TODO(b/369381361) Enfore -Wmissing-prototypes #pragma GCC diagnostic ignored "-Wmissing-prototypes" using base::Bind; -using base::Owned; -using base::Passed; using base::Unretained; using bluetooth::has::ConnectionState; using bluetooth::has::ErrorCode; diff --git a/system/btif/src/btif_hd.cc b/system/btif/src/btif_hd.cc index 149b9aee2a2..8b2a67310a7 100644 --- a/system/btif/src/btif_hd.cc +++ b/system/btif/src/btif_hd.cc @@ -25,23 +25,29 @@ * * ***********************************************************************************/ + #define LOG_TAG "BTIF_HD" #include "btif/include/btif_hd.h" #include +#include +#include #include +#include #include "bta/include/bta_dm_api.h" #include "bta/include/bta_hd_api.h" #include "bta/sys/bta_sys.h" +#include "bta_api.h" #include "bta_sec_api.h" #include "btif/include/btif_common.h" #include "btif/include/btif_dm.h" #include "btif/include/btif_hh.h" #include "btif/include/btif_profile_storage.h" #include "btif/include/btif_util.h" +#include "hardware/bluetooth.h" #include "include/hardware/bt_hd.h" #include "internal_include/bt_target.h" #include "osi/include/allocator.h" diff --git a/system/btif/src/btif_hearing_aid.cc b/system/btif/src/btif_hearing_aid.cc index 21b134ebd19..64dc35f7a80 100644 --- a/system/btif/src/btif_hearing_aid.cc +++ b/system/btif/src/btif_hearing_aid.cc @@ -22,12 +22,16 @@ #include #include -#include #include +#include +#include +#include + #include "bta_hearing_aid_api.h" #include "btif_common.h" #include "btif_profile_storage.h" +#include "hardware/avrcp/avrcp.h" #include "stack/include/main_thread.h" #include "types/raw_address.h" diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index 372bdf4262b..8edc70ab3da 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -30,27 +30,40 @@ #include "btif/include/btif_hf.h" #include +#include #include #include #include #include +#include #include +#include +#include +#include +#include #include +#include +#include "bta/ag/bta_ag_int.h" #include "bta/include/bta_ag_api.h" +#include "bta/include/bta_api.h" #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" #include "common/metrics.h" +#include "device/include/device_iot_conf_defs.h" #include "device/include/device_iot_config.h" +#include "hardware/bluetooth.h" #include "include/hardware/bluetooth_headset_callbacks.h" #include "include/hardware/bluetooth_headset_interface.h" #include "include/hardware/bt_hf.h" #include "internal_include/bt_target.h" +#include "os/logging/log_adapter.h" #include "stack/btm/btm_sco_hfp_hal.h" #include "stack/include/bt_uuid16.h" #include "stack/include/btm_client_interface.h" diff --git a/system/btif/src/btif_hf_client.cc b/system/btif/src/btif_hf_client.cc index 08e06e19e83..30495459c11 100644 --- a/system/btif/src/btif_hf_client.cc +++ b/system/btif/src/btif_hf_client.cc @@ -49,8 +49,12 @@ #include #include #include -#include +#include +#include + +#include "bta/include/bta_api.h" +#include "bta/include/bta_hfp_api.h" #include "bta_hf_client_api.h" #include "btif_common.h" #include "btif_profile_queue.h" diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index e01e2d8d75d..e1a42df19e1 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -29,11 +29,23 @@ #include "btif/include/btif_hh.h" +#include #include #include +#include +#include +#include +#include #include - +#include + +#include "ble_address_with_type.h" +#include "bluetooth/uuid.h" +#include "bt_device_type.h" +#include "bt_transport.h" +#include "bta_api.h" +#include "bta_hh_api.h" #include "bta_hh_co.h" #include "bta_sec_api.h" #include "btif/include/btif_common.h" @@ -43,12 +55,14 @@ #include "btif/include/btif_profile_storage.h" #include "btif/include/btif_storage.h" #include "btif/include/btif_util.h" +#include "hardware/bluetooth.h" #include "include/hardware/bt_hh.h" +#include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" +#include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_uuid16.h" -#include "stack/include/btm_ble_api.h" #include "stack/include/btm_client_interface.h" #include "stack/include/hidh_api.h" #include "types/raw_address.h" diff --git a/system/btif/src/btif_iot_config.cc b/system/btif/src/btif_iot_config.cc index 1e70657b2a2..9db2159ad70 100644 --- a/system/btif/src/btif_iot_config.cc +++ b/system/btif/src/btif_iot_config.cc @@ -18,9 +18,16 @@ #include +#include +#include + +#include "bt_name.h" #include "bta_sec_api.h" #include "btif_storage.h" +#include "device/include/device_iot_conf_defs.h" #include "device/include/device_iot_config.h" +#include "hardware/bluetooth.h" +#include "raw_address.h" #include "stack/include/btm_ble_api.h" #include "stack/include/btm_client_interface.h" diff --git a/system/btif/src/btif_le_audio.cc b/system/btif/src/btif_le_audio.cc index 0e4ab09e418..8498dab8769 100644 --- a/system/btif/src/btif_le_audio.cc +++ b/system/btif/src/btif_le_audio.cc @@ -16,14 +16,17 @@ */ #include -#include #include +#include +#include +#include #include #include "bta_le_audio_api.h" #include "btif_common.h" #include "btif_profile_storage.h" +#include "raw_address.h" #include "stack/include/main_thread.h" // TODO(b/369381361) Enfore -Wmissing-prototypes diff --git a/system/btif/src/btif_le_audio_broadcaster.cc b/system/btif/src/btif_le_audio_broadcaster.cc index 45c4b5b52d9..253c0e0d525 100644 --- a/system/btif/src/btif_le_audio_broadcaster.cc +++ b/system/btif/src/btif_le_audio_broadcaster.cc @@ -16,9 +16,15 @@ */ #include -#include #include +#include +#include +#include +#include +#include +#include + #include "bta_le_audio_api.h" #include "bta_le_audio_broadcaster_api.h" #include "btif_common.h" diff --git a/system/btif/src/btif_pan.cc b/system/btif/src/btif_pan.cc index 53c7cdb94cc..1f0bcb1b92d 100644 --- a/system/btif/src/btif_pan.cc +++ b/system/btif/src/btif_pan.cc @@ -29,7 +29,6 @@ #include "btif/include/btif_pan.h" -#include #include #include #include @@ -39,13 +38,24 @@ #include #include #include +#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include + #include "bta/include/bta_pan_api.h" #include "btif/include/btif_common.h" #include "btif/include/btif_pan_internal.h" #include "btif/include/btif_sock_thread.h" +#include "hardware/bluetooth.h" #include "hci/controller_interface.h" #include "include/hardware/bt_pan.h" #include "internal_include/bt_target.h" @@ -53,6 +63,7 @@ #include "main/shim/helpers.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" +#include "osi/include/osi.h" #include "stack/include/bt_hdr.h" #include "stack/include/main_thread.h" #include "stack/include/pan_api.h" diff --git a/system/btif/src/btif_profile_queue.cc b/system/btif/src/btif_profile_queue.cc index 15237abe75f..38d00f470fb 100644 --- a/system/btif/src/btif_profile_queue.cc +++ b/system/btif/src/btif_profile_queue.cc @@ -33,10 +33,13 @@ #include #include +#include #include +#include #include "btif/include/stack_manager_t.h" #include "btif_common.h" +#include "hardware/bluetooth.h" #include "types/raw_address.h" using namespace bluetooth; diff --git a/system/btif/src/btif_profile_storage.cc b/system/btif/src/btif_profile_storage.cc index d0949d6af1c..230101906a8 100644 --- a/system/btif/src/btif_profile_storage.cc +++ b/system/btif/src/btif_profile_storage.cc @@ -15,6 +15,7 @@ * limitations under the License. * ******************************************************************************/ + #define LOG_TAG "bt_btif_profile_storage" #include "btif_profile_storage.h" @@ -26,8 +27,13 @@ #include #include +#include +#include +#include #include +#include "ble_address_with_type.h" +#include "bt_transport.h" #include "bta_csis_api.h" #include "bta_groups.h" #include "bta_has_api.h" @@ -41,6 +47,7 @@ #include "btif_config.h" #include "btif_hh.h" #include "btif_storage.h" +#include "hardware/bluetooth.h" #include "stack/include/bt_uuid16.h" #include "stack/include/main_thread.h" #include "storage/config_keys.h" diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index cf244403b14..5b97f454b6a 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -26,17 +26,19 @@ #include "btif_rc.h" +#include #include -#include #include #include -#include +#include #include #include -#include +#include #include #include +#include +#include #include "bta/include/bta_av_api.h" #include "btif/avrcp/avrcp_service.h" @@ -48,6 +50,7 @@ #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/list.h" +#include "osi/include/osi.h" #include "osi/include/properties.h" #include "stack/include/avrc_api.h" #include "stack/include/avrc_defs.h" @@ -1246,7 +1249,7 @@ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data) { bool btif_rc_is_connected_peer(const RawAddress& peer_addr) { for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) { btif_rc_device_cb_t* p_dev = get_connected_device(idx); - if (p_dev != NULL && (p_dev->rc_connected == TRUE) && peer_addr == p_dev->rc_addr) { + if (p_dev != NULL && p_dev->rc_connected && peer_addr == p_dev->rc_addr) { return true; } } @@ -1666,7 +1669,7 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, uint case AVRC_PDU_REQUEST_CONTINUATION_RSP: { log::verbose("REQUEST CONTINUATION: target_pdu: 0x{:02d}", pavrc_cmd->continu.target_pdu); tAVRC_RESPONSE avrc_rsp; - if (p_dev->rc_connected == TRUE) { + if (p_dev->rc_connected) { memset(&(avrc_rsp.continu), 0, sizeof(tAVRC_NEXT_RSP)); avrc_rsp.continu.opcode = opcode_from_pdu(AVRC_PDU_REQUEST_CONTINUATION_RSP); avrc_rsp.continu.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP; @@ -1679,7 +1682,7 @@ static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd, uint case AVRC_PDU_ABORT_CONTINUATION_RSP: { log::verbose("ABORT CONTINUATION: target_pdu: 0x{:02d}", pavrc_cmd->abort.target_pdu); tAVRC_RESPONSE avrc_rsp; - if (p_dev->rc_connected == TRUE) { + if (p_dev->rc_connected) { memset(&(avrc_rsp.abort), 0, sizeof(tAVRC_NEXT_RSP)); avrc_rsp.abort.opcode = opcode_from_pdu(AVRC_PDU_ABORT_CONTINUATION_RSP); avrc_rsp.abort.pdu = AVRC_PDU_ABORT_CONTINUATION_RSP; diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc index e18da7a2d65..15f2fd212ba 100644 --- a/system/btif/src/btif_vc.cc +++ b/system/btif/src/btif_vc.cc @@ -20,9 +20,15 @@ #include #include #include -#include #include +#include +#include +#include +#include +#include +#include + #include "bta/include/bta_vc_api.h" #include "btif/include/btif_common.h" #include "btif/include/btif_profile_storage.h" -- GitLab From b598112fa3b057092acb8ff104680ed9ac4cce07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Y=C4=B1lmaz?= Date: Tue, 5 Nov 2024 01:10:23 +0000 Subject: [PATCH 551/875] Add flag identity_address_type_api Bug: 377171798 Bug: 226253021 Bug: 315241296 Change-Id: Ifff17894806fe1d356105f7cef40769d4abb85bf Test: m . --- flags/framework.aconfig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/flags/framework.aconfig b/flags/framework.aconfig index 32b88d447a9..255d3a7345b 100644 --- a/flags/framework.aconfig +++ b/flags/framework.aconfig @@ -80,4 +80,12 @@ flag { metadata { purpose: PURPOSE_BUGFIX } -} \ No newline at end of file +} + +flag { + name: "identity_address_type_api" + is_exported: true + namespace: "bluetooth" + description: "Add a new API to BluetoothDevice to retrieve Identity Address Type" + bug: "377171798" +} -- GitLab From 5a288596abe62203c7c53e61d56bacd7bf26408a Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 23 Oct 2024 15:08:28 -0700 Subject: [PATCH 552/875] AICS: Add native aics module Bug: 372328699 Flag: com.android.bluetooth.flags.aics_api Test: m . Change-Id: I964c79c02cbf5b53aad1434b0361be4f18798677 --- android/app/Android.bp | 1 + android/app/jni/com_android_bluetooth_vc.cpp | 10 ++-- system/bta/Android.bp | 5 ++ system/bta/BUILD.gn | 2 + system/bta/aics/Android.bp | 32 +++++++++++++ system/bta/aics/BUILD.gn | 40 ++++++++++++++++ system/bta/aics/aics.cc | 32 +++++++++++++ system/bta/aics/include/aics/api.h | 36 +++++++++++++++ system/bta/vc/types.h | 3 +- system/bta/vc/vc.cc | 5 +- system/bta/vc/vc_test.cc | 16 ++++--- system/btif/Android.bp | 14 ++++++ system/btif/BUILD.gn | 2 + system/btif/src/btif_vc.cc | 4 +- system/gd/rust/topshim/Android.bp | 7 +++ system/gd/rust/topshim/BUILD.gn | 5 ++ system/gd/rust/topshim/facade/Android.bp | 2 + system/gd/rust/topshim/vc/vc_shim.cc | 5 +- system/include/Android.bp | 2 + system/include/hardware/bt_vc.h | 5 +- system/main/Android.bp | 4 ++ system/stack/Android.bp | 48 ++++++++++++++++++++ system/test/headless/Android.bp | 5 ++ system/test/suite/Android.bp | 5 ++ 24 files changed, 273 insertions(+), 17 deletions(-) create mode 100644 system/bta/aics/Android.bp create mode 100644 system/bta/aics/BUILD.gn create mode 100644 system/bta/aics/aics.cc create mode 100644 system/bta/aics/include/aics/api.h diff --git a/android/app/Android.bp b/android/app/Android.bp index 83de2861e97..d4fccc05678 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -91,6 +91,7 @@ cc_library_shared { // is required to maintain FIPS compliance. stl: "libc++_static", static_libs: [ + "aics", "android.hardware.audio.common@5.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp index adb9b78c778..80ef9d71848 100644 --- a/android/app/jni/com_android_bluetooth_vc.cpp +++ b/android/app/jni/com_android_bluetooth_vc.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "BluetoothVolumeControlServiceJni" +#include #include #include #include @@ -34,9 +35,12 @@ #include "hardware/bt_vc.h" #include "types/raw_address.h" +using bluetooth::aics::Mute; using bluetooth::vc::ConnectionState; using bluetooth::vc::VolumeControlCallbacks; using bluetooth::vc::VolumeControlInterface; +using bluetooth::vc::VolumeInputStatus; +using bluetooth::vc::VolumeInputType; namespace android { static jmethodID method_onConnectionStateChanged; @@ -218,7 +222,7 @@ public: } void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode, uint8_t mute) override { + uint8_t gain_mode, Mute mute) override { log::info(""); std::shared_lock lock(callbacks_mutex); @@ -241,7 +245,7 @@ public: } void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id, - bluetooth::vc::VolumeInputStatus status) override { + VolumeInputStatus status) override { log::info(""); std::shared_lock lock(callbacks_mutex); @@ -264,7 +268,7 @@ public: } void OnExtAudioInTypeChanged(const RawAddress& bd_addr, uint8_t ext_input_id, - bluetooth::vc::VolumeInputType type) override { + VolumeInputType type) override { log::info(""); std::shared_lock lock(callbacks_mutex); diff --git a/system/bta/Android.bp b/system/bta/Android.bp index ad4e798016f..812c482fcb5 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -655,12 +655,17 @@ cc_test { "vc/vc.cc", "vc/vc_test.cc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libbase", + "libbinder", "libcrypto", "liblog", ], static_libs: [ + "aics", "bluetooth_flags_c_lib_for_test", "libbluetooth-types", "libbluetooth_crypto_toolbox", diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn index b328715d091..928359ab220 100644 --- a/system/bta/BUILD.gn +++ b/system/bta/BUILD.gn @@ -145,6 +145,7 @@ static_library("bta") { "//bt/system/include", "//bt/system/linux_include", "//bt/system/bta", + "//bt/system/bta/aics/include", "//bt/system/gd", "//bt/system/stack/include", "//bt/system/stack/btm", @@ -173,6 +174,7 @@ static_library("bta") { "//bt/system/bta:install_audio_set_configurations_json", "//bt/system/bta:install_audio_set_scenarios_bfbs", "//bt/system/bta:install_audio_set_configurations_bfbs", + "//bt/system/bta/aics:aics", "//bt/system:libbt-platform-protos-lite", ] diff --git a/system/bta/aics/Android.bp b/system/bta/aics/Android.bp new file mode 100644 index 00000000000..33bd649d13e --- /dev/null +++ b/system/bta/aics/Android.bp @@ -0,0 +1,32 @@ +cc_library_headers { + name: "aics_headers", + export_include_dirs: ["include"], + host_supported: true, + vendor_available: true, // remove when https://r.android.com/3302734 is merged + visibility: ["//packages/modules/Bluetooth:__subpackages__"], + apex_available: ["com.android.btservices"], + min_sdk_version: "33", +} + +cc_library { + name: "aics", + defaults: ["fluoride_defaults"], + srcs: [ + "aics.cc", + ], + aidl: { + libs: ["bluetooth_constants"], + }, + shared_libs: [ + "libbase", + "libbinder", + "libbluetooth_log", + "liblog", + ], + header_libs: ["aics_headers"], + export_header_lib_headers: ["aics_headers"], + host_supported: true, + visibility: ["//packages/modules/Bluetooth:__subpackages__"], + apex_available: ["com.android.btservices"], + min_sdk_version: "33", +} diff --git a/system/bta/aics/BUILD.gn b/system/bta/aics/BUILD.gn new file mode 100644 index 00000000000..5663e367f15 --- /dev/null +++ b/system/bta/aics/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (C) 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. + +config("aics_defaults") { + include_dirs = [ + "include", + ] + configs = [ + "//bt/system:target_defaults", + "//bt/system/log:log_defaults", + ] +} + +static_library("aics") { + sources = [ + "aics.cc", + ] + configs += [ + ":aics_defaults", + ] + # include_dirs = [ + # "include", + # ] + + # configs += [ + # "//bt/system:target_defaults", + # "//bt/system/log:log_defaults", + # ] +} + diff --git a/system/bta/aics/aics.cc b/system/bta/aics/aics.cc new file mode 100644 index 00000000000..5b5c0886f36 --- /dev/null +++ b/system/bta/aics/aics.cc @@ -0,0 +1,32 @@ +// Copyright (C) 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. + +#define LOG_TAG "aics" + +#include +#include + +namespace bluetooth::aics { + +bool isValidAudioInputMuteValue(uint8_t data) { + return data >= static_cast(Mute::NOT_MUTED) && + data <= static_cast(Mute::DISABLED); +} + +Mute parseMuteField(uint8_t data) { + log::assert_that(isValidAudioInputMuteValue(data), "Not a valid Mute Value"); + + return static_cast(data); +} + +} // namespace bluetooth::aics diff --git a/system/bta/aics/include/aics/api.h b/system/bta/aics/include/aics/api.h new file mode 100644 index 00000000000..aba825d37ec --- /dev/null +++ b/system/bta/aics/include/aics/api.h @@ -0,0 +1,36 @@ +// Copyright (C) 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 + +#ifndef TARGET_FLOSS +#include +#endif + +#include + +namespace bluetooth::aics { + +#ifndef TARGET_FLOSS +using Mute = bluetooth::constants::aics::Mute; +#else +// TODO: b/376941621 Support the aidl generation in FLOSS +enum class Mute : int8_t { NOT_MUTED = 0, MUTED = 1, DISABLED = 2 }; +#endif + +/** Check if the data is a correct Mute value */ +bool isValidAudioInputMuteValue(uint8_t data); + +/** Convert valid data into a Mute value. Abort if data is not valid */ +Mute parseMuteField(uint8_t data); +} // namespace bluetooth::aics diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h index d896137eef3..a0077f03010 100644 --- a/system/bta/vc/types.h +++ b/system/bta/vc/types.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include @@ -136,7 +137,7 @@ struct GainSettings { struct VolumeAudioInput { /* const */ uint8_t id; - uint8_t mute = 0x02; // DISABLED + Mute mute = bluetooth::aics::Mute::DISABLED; int8_t gain_value = 0; VolumeInputStatus status = VolumeInputStatus::Inactive; VolumeInputType type = VolumeInputType::Unspecified; diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index cd6f477b297..9131274e1e1 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -15,6 +15,7 @@ * limitations under the License. */ +#include #include #include #include @@ -583,11 +584,11 @@ public: STREAM_TO_INT8(input->gain_value, pp); uint8_t mute; STREAM_TO_UINT8(mute, pp); - if (mute > 0x02 /*Mute::DISABLED*/) { + if (!bluetooth::aics::isValidAudioInputMuteValue(mute)) { bluetooth::log::error("{} Invalid mute value: {:#x}", device->address, mute); return; } - input->mute = mute; + input->mute = bluetooth::aics::parseMuteField(mute); STREAM_TO_UINT8(input->mode, pp); STREAM_TO_UINT8(input->change_counter, pp); diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index 6684c1e10b1..aac4736460f 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -15,6 +15,7 @@ * limitations under the License. */ +#include #include #include #include @@ -58,6 +59,7 @@ namespace { using base::Bind; using base::Unretained; +using bluetooth::aics::Mute; using bluetooth::vc::ConnectionState; using bluetooth::vc::VolumeControlCallbacks; @@ -104,7 +106,7 @@ public: (const RawAddress& address, uint8_t ext_output_id, std::string descr), (override)); MOCK_METHOD((void), OnExtAudioInStateChanged, (const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode_auto, uint8_t mute), + uint8_t gain_mode_auto, Mute mute), (override)); MOCK_METHOD((void), OnExtAudioInStatusChanged, (const RawAddress& address, uint8_t ext_input_id, VolumeInputStatus status), @@ -1341,14 +1343,14 @@ TEST_F(VolumeControlCallbackTest, audio_input_state_changed__invalid_mute__is_re } TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__muted) { - std::vector value({0x03, 0x01, 0x02, 0x04}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, 0x01)); + std::vector value({0x03, (uint8_t)Mute::MUTED, 0x02, 0x04}); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, Mute::MUTED)); GetNotificationEvent(0x0032, value); } TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__disabled) { - std::vector value({0x03, 0x02, 0x02, 0x04}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, 0x02)); + std::vector value({0x03, (uint8_t)Mute::DISABLED, 0x02, 0x04}); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, Mute::DISABLED)); GetNotificationEvent(0x0032, value); } @@ -1487,8 +1489,8 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_out_description) { TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_state) { VolumeControl::Get()->GetExtAudioInState(test_address, 1); EXPECT_TRUE(cb); - std::vector value({0x01, 0x00, 0x02, 0x03}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, 0x00)); + std::vector value({0x01, (uint8_t)Mute::NOT_MUTED, 0x02, 0x03}); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, Mute::NOT_MUTED)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 4aa018563be..e6bdf90de5d 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -150,6 +150,7 @@ cc_library_static { }, }, static_libs: [ + "aics", "avrcp-target-service", "bluetooth_flags_c_lib", "lib-bt-packets", @@ -289,9 +290,13 @@ cc_test { "test/btif_storage_test.cc", ], header_libs: ["libbluetooth_headers"], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", "libbase", + "libbinder", "libcrypto", "libcutils", "libhidlbase", @@ -300,6 +305,7 @@ cc_test { "server_configurable_flags", ], static_libs: [ + "aics", "android.hardware.audio.common@5.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", @@ -575,9 +581,13 @@ cc_test { "BluetoothGeneratedDumpsysDataSchema_h", ], header_libs: ["libbluetooth_headers"], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", "libbase", + "libbinder", "libcrypto", "libcutils", "libfmq", @@ -696,9 +706,13 @@ cc_test { "BluetoothGeneratedDumpsysDataSchema_h", ], header_libs: ["libbluetooth_headers"], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", "libbase", + "libbinder", "libcrypto", "libcutils", "libfmq", diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn index 884dc60ba33..68ca336a3d0 100644 --- a/system/btif/BUILD.gn +++ b/system/btif/BUILD.gn @@ -93,6 +93,7 @@ static_library("btif") { "//bt/system/bta/dm", "//bt/system/linux_include", "//bt/system/audio_hearing_aid_hw/include", + "//bt/system/bta/aics/include", "//bt/system/bta/include", "//bt/system/bta/sys", "//bt/system/device/include", @@ -114,6 +115,7 @@ static_library("btif") { "//bt/system:libbt-platform-protos-lite", "//bt/system/common", "//bt/system/profile/avrcp:profile_avrcp", + "//bt/system/bta/aics:aics", ] configs += [ diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc index e18da7a2d65..b564a4aef4a 100644 --- a/system/btif/src/btif_vc.cc +++ b/system/btif/src/btif_vc.cc @@ -17,6 +17,7 @@ /* Volume Control Interface */ +#include #include #include #include @@ -34,6 +35,7 @@ using base::Bind; using base::Unretained; +using bluetooth::aics::Mute; using bluetooth::vc::ConnectionState; using bluetooth::vc::VolumeControlCallbacks; using bluetooth::vc::VolumeControlInterface; @@ -103,7 +105,7 @@ class VolumeControlInterfaceImpl : public VolumeControlInterface, public VolumeC /* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */ void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode, uint8_t mute) override { + uint8_t gain_mode, ::Mute mute) override { do_in_jni_thread(Bind(&VolumeControlCallbacks::OnExtAudioInStateChanged, Unretained(callbacks_), address, ext_input_id, gain_val, gain_mode, mute)); } diff --git a/system/gd/rust/topshim/Android.bp b/system/gd/rust/topshim/Android.bp index af5ed8cb5b3..fe3a5cca155 100644 --- a/system/gd/rust/topshim/Android.bp +++ b/system/gd/rust/topshim/Android.bp @@ -66,11 +66,18 @@ cc_library_static { ], host_supported: true, static_libs: [ + "aics", "libbluetooth_hci_pdl", "libbluetooth_log", "libchrome", "libflatbuffers-cpp", ], + aidl: { + libs: ["bluetooth_constants"], + }, + shared_libs: [ + "libbinder", + ], target: { darwin: { enabled: false, diff --git a/system/gd/rust/topshim/BUILD.gn b/system/gd/rust/topshim/BUILD.gn index a20dbeee532..b2c937d0195 100644 --- a/system/gd/rust/topshim/BUILD.gn +++ b/system/gd/rust/topshim/BUILD.gn @@ -50,9 +50,11 @@ cxxbridge_cc("btif_bridge_code") { ] deps = [ ":btif_bridge_header", + "//bt/system/bta/aics:aics", "//bt/system/pdl:BluetoothGeneratedPackets_h", ] configs = [ + "//bt/system/bta/aics:aics_defaults", "//bt/system/gd:gd_defaults", "//bt/system/log:log_defaults", ] @@ -82,6 +84,9 @@ source_set("btif_cxx_bridge_code") { "//bt/system/gd:gd_defaults", "//bt/system/log:log_defaults", ] + include_dirs = [ + "//bt/system/bta/aics/include", + ] } cxxbridge_libheader("cxxlibheader") { diff --git a/system/gd/rust/topshim/facade/Android.bp b/system/gd/rust/topshim/facade/Android.bp index 725ddaa355d..505d5e8624e 100644 --- a/system/gd/rust/topshim/facade/Android.bp +++ b/system/gd/rust/topshim/facade/Android.bp @@ -32,6 +32,7 @@ rust_defaults { "libtokio", ], static_libs: [ + "aics", "avrcp-target-service", "lib-bt-packets", "lib-bt-packets-avrcp", @@ -72,6 +73,7 @@ rust_defaults { ], shared_libs: [ "libaconfig_storage_read_api_cc", + "libbinder", "libcrypto", "libcutils", "libgrpc++", diff --git a/system/gd/rust/topshim/vc/vc_shim.cc b/system/gd/rust/topshim/vc/vc_shim.cc index ab0edd975b2..9baceb01116 100644 --- a/system/gd/rust/topshim/vc/vc_shim.cc +++ b/system/gd/rust/topshim/vc/vc_shim.cc @@ -21,6 +21,7 @@ #include +#include "aics/api.h" #include "src/profiles/vc.rs.h" #include "types/raw_address.h" @@ -136,9 +137,9 @@ public: } void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode_auto, uint8_t mute) { + uint8_t gain_mode_auto, bluetooth::aics::Mute mute) { log::info("address={}, ext_input_id={}, gain_val={}, gain_mode_auto={}, mute={}", address, - ext_input_id, gain_val, gain_mode_auto, mute); + ext_input_id, gain_val, gain_mode_auto, static_cast(mute)); log::info("Not implemented"); } diff --git a/system/include/Android.bp b/system/include/Android.bp index f76b6fcccbe..5540d0dd45e 100644 --- a/system/include/Android.bp +++ b/system/include/Android.bp @@ -35,11 +35,13 @@ cc_library_headers { "//vendor:__subpackages__", ], header_libs: [ + "aics_headers", "avrcp_headers", "libbluetooth-types-header", "libbtcore_headers", ], export_header_lib_headers: [ + "aics_headers", "avrcp_headers", "libbluetooth-types-header", "libbtcore_headers", diff --git a/system/include/hardware/bt_vc.h b/system/include/hardware/bt_vc.h index 6b45b48bf48..a3f4fcc191d 100644 --- a/system/include/hardware/bt_vc.h +++ b/system/include/hardware/bt_vc.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include @@ -26,6 +27,8 @@ namespace bluetooth { namespace vc { +using bluetooth::aics::Mute; + // Must be kept in sync with BluetoothProfile.java enum class ConnectionState { DISCONNECTED = 0, CONNECTING, CONNECTED, DISCONNECTING }; @@ -73,7 +76,7 @@ public: /* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */ virtual void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, - int8_t gain_val, uint8_t gain_mode_auto, uint8_t mute) = 0; + int8_t gain_val, uint8_t gain_mode_auto, Mute mute) = 0; virtual void OnExtAudioInStatusChanged(const RawAddress& address, uint8_t ext_input_id, VolumeInputStatus status) = 0; diff --git a/system/main/Android.bp b/system/main/Android.bp index cfa85eea7ea..5b270923f44 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -215,9 +215,13 @@ cc_test { "liblog", "libosi", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libPlatformProperties", "libaconfig_storage_read_api_cc", + "libbinder", "libbinder_ndk", "libcrypto", "server_configurable_flags", diff --git a/system/stack/Android.bp b/system/stack/Android.bp index cb987debfc1..aebe1e755e1 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -1214,7 +1214,11 @@ cc_test { "avct/avct_lcb_act.cc", "test/stack_avctp_test.cc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ + "libbinder", "libcrypto", "libcutils", "server_configurable_flags", @@ -1284,7 +1288,11 @@ cc_test { "test/common/mock_stack_avdt_msg.cc", "test/stack_avdtp_test.cc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ + "libbinder", "libcrypto", "libcutils", "server_configurable_flags", @@ -1392,7 +1400,11 @@ cc_test { "test/a2dp/wav_reader.cc", "test/a2dp/wav_reader_unittest.cc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ + "libbinder", "libcrypto", "libcutils", "libprotobuf-cpp-lite", @@ -1449,7 +1461,11 @@ cc_test { "test/a2dp/a2dp_vendor_ldac_decoder_test.cc", "test/a2dp/misc_fake.cc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ + "libbinder", "libcrypto", "libcutils", ], @@ -1506,8 +1522,12 @@ cc_test { "test/gatt/mock_gatt_utils_ref.cc", "test/stack_gatt_sr_hash_test.cc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", + "libbinder", "libcrypto", "libcutils", "server_configurable_flags", @@ -1797,8 +1817,12 @@ cc_test { "libprotobuf-cpp-lite", "libudrv-uipc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", + "libbinder", "libcrypto", "libcutils", "server_configurable_flags", @@ -1986,7 +2010,11 @@ cc_test { "libosi", "server_configurable_flags", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ + "libbinder", "libbinder_ndk", "libcrypto", ], @@ -2077,9 +2105,13 @@ cc_test { "libprotobuf-cpp-lite", "libstatslog_bt", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", "libbase", + "libbinder", "libbinder_ndk", "libcrypto", "libcutils", @@ -2169,9 +2201,13 @@ cc_test { "libprotobuf-cpp-lite", "libstatslog_bt", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", "libbase", + "libbinder", "libbinder_ndk", "libcrypto", "libcutils", @@ -2263,9 +2299,13 @@ cc_test { "libosi", "libstatslog_bt", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", "libbase", + "libbinder", "libbinder_ndk", "libcrypto", "server_configurable_flags", @@ -2367,8 +2407,12 @@ cc_test { "libprotobuf-cpp-lite", "libudrv-uipc", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", + "libbinder", "libcrypto", "libcutils", "server_configurable_flags", @@ -2432,8 +2476,12 @@ cc_test { "libgmock", "liblog", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", + "libbinder", "libcrypto", "libcutils", "server_configurable_flags", diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp index 846f9ec4ccc..af86f9f6645 100644 --- a/system/test/headless/Android.bp +++ b/system/test/headless/Android.bp @@ -71,6 +71,7 @@ cc_binary { "packages/modules/Bluetooth/system/stack/include", ], static_libs: [ + "aics", "android.hardware.audio.common@5.0", "android.hardware.common-V2-ndk", "android.hardware.common.fmq-V1-ndk", @@ -119,9 +120,13 @@ cc_binary { "libudrv-uipc", "libz", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libPlatformProperties", "libaconfig_storage_read_api_cc", + "libbinder", "libcrypto", "libcutils", // property_get_bool "libhidlbase", diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp index 09e8fda4135..d495cc034d5 100644 --- a/system/test/suite/Android.bp +++ b/system/test/suite/Android.bp @@ -120,6 +120,7 @@ cc_test { "gatt/gatt_unittest.cc", ], static_libs: [ + "aics", "bluetooth_flags_c_lib_for_test", "libbluetooth_crypto_toolbox", "libbluetooth_gd", @@ -133,9 +134,13 @@ cc_test { "libflags_rust_cpp_bridge", "libprotobuf-cpp-lite", ], + aidl: { + libs: ["bluetooth_constants"], + }, shared_libs: [ "libaconfig_storage_read_api_cc", "libbase", + "libbinder", "server_configurable_flags", ], generated_headers: [ -- GitLab From c28ac6676cbace787886885828a9bbaecc41f5d4 Mon Sep 17 00:00:00 2001 From: Omair Kamil Date: Mon, 4 Nov 2024 16:19:44 -0800 Subject: [PATCH 553/875] Log attribution tag for last scans in dumpsys. Bug: 372576833 Flag: EXEMPT, logging change Test: atest BluetoothInstrumentationTests Change-Id: I23491145326aff3cfd8eaaf38170e849f0910d6e --- .../android/bluetooth/le_scan/AppScanStats.java | 15 ++++++++++++--- .../bluetooth/le_scan/TransitionalScanHelper.java | 15 +++++++++++++-- .../bluetooth/le_scan/AppScanStatsTest.java | 3 ++- .../bluetooth/le_scan/ScanManagerTest.java | 4 ++-- .../le_scan/TransitionalScanHelperTest.java | 4 ++-- .../src/android/bluetooth/LeScanningTest.java | 3 ++- 6 files changed, 33 insertions(+), 11 deletions(-) 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 7438921f332..a7e3bffba33 100644 --- a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java +++ b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java @@ -16,6 +16,7 @@ package com.android.bluetooth.le_scan; +import android.annotation.Nullable; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanSettings; @@ -104,6 +105,7 @@ public class AppScanStats { public int scanMode; public int scanCallbackType; public StringBuilder filterString; + @Nullable public String attributionTag; LastScan( long timestamp, @@ -112,7 +114,8 @@ public class AppScanStats { boolean isCallbackScan, int scannerId, int scanMode, - int scanCallbackType) { + int scanCallbackType, + @Nullable String attributionTag) { this.duration = 0; this.timestamp = timestamp; this.reportDelayMillis = reportDelayMillis; @@ -126,6 +129,7 @@ public class AppScanStats { this.isAutoBatchScan = false; this.scanMode = scanMode; this.scanCallbackType = scanCallbackType; + this.attributionTag = attributionTag; this.results = 0; this.scannerId = scannerId; this.suspendDuration = 0; @@ -239,7 +243,8 @@ public class AppScanStats { List filters, boolean isFilterScan, boolean isCallbackScan, - int scannerId) { + int scannerId, + @Nullable String attributionTag) { LastScan existingScan = getScanFromScannerId(scannerId); if (existingScan != null) { return; @@ -255,7 +260,8 @@ public class AppScanStats { isCallbackScan, scannerId, settings.getScanMode(), - settings.getCallbackType()); + settings.getCallbackType(), + attributionTag); if (settings != null) { scan.isOpportunisticScan = scan.scanMode == ScanSettings.SCAN_MODE_OPPORTUNISTIC; scan.isBackgroundScan = @@ -1065,6 +1071,9 @@ public class AppScanStats { } sb.append(scan.results).append(" results"); sb.append(" (").append(scan.scannerId).append(") "); + if (scan.attributionTag != null) { + sb.append(" [").append(scan.attributionTag).append("] "); + } if (scan.isCallbackScan) { sb.append("CB "); } else { diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java index b164b06693f..adf3b29743e 100644 --- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java +++ b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java @@ -1210,7 +1210,13 @@ public class TransitionalScanHelper { if (cbApp != null) { isCallbackScan = cbApp.mCallback != null; } - app.recordScanStart(settings, filters, isFilteredScan, isCallbackScan, scannerId); + app.recordScanStart( + settings, + filters, + isFilteredScan, + isCallbackScan, + scannerId, + cbApp == null ? null : cbApp.mAttributionTag); } mScanManager.startScan(scanClient); @@ -1317,7 +1323,12 @@ public class TransitionalScanHelper { scanClient.stats = scanStats; boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); scanStats.recordScanStart( - piInfo.settings, piInfo.filters, isFilteredScan, false, scannerId); + piInfo.settings, + piInfo.filters, + isFilteredScan, + false, + scannerId, + app.mAttributionTag); } mScanManager.startScan(scanClient); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java index c70d425f60f..4ae3df58696 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java @@ -112,7 +112,8 @@ public class AppScanStatsTest { boolean isCallbackScan = false; int scannerId = 0; - appScanStats.recordScanStart(settings, filters, isFilterScan, isCallbackScan, scannerId); + appScanStats.recordScanStart( + settings, filters, isFilterScan, isCallbackScan, scannerId, "tag"); appScanStats.isRegistered = true; StringBuilder stringBuilder = new StringBuilder(); 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 c54552ca839..14613b1242e 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 @@ -287,7 +287,7 @@ public class ScanManagerTest { ScanClient client = new ScanClient(id, scanSettings, scanFilterList, appUid); client.stats = appScanStats; - client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id); + client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id, null); return client; } @@ -385,7 +385,7 @@ public class ScanManagerTest { ScanClient client = new ScanClient(id, scanSettings, scanFilterList); client.stats = mMockAppScanStats; - client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id); + client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id, null); return client; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java index f49529c65e5..36cf518c830 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java @@ -174,7 +174,7 @@ public class TransitionalScanHelperTest { mScanHelper.continuePiStartScan(scannerId, mApp); verify(appScanStats) - .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId); + .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId, null); verify(mScanManager).startScan(any()); } @@ -192,7 +192,7 @@ public class TransitionalScanHelperTest { mScanHelper.continuePiStartScan(scannerId, mApp); verify(appScanStats) - .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId); + .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId, null); verify(mScanManager) .startScan( argThat( diff --git a/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java b/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java index 3f728e4a694..ace8251cf49 100644 --- a/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java +++ b/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java @@ -85,7 +85,8 @@ public class LeScanningTest { @Rule(order = 2) public final EnableBluetoothRule mEnableBluetoothRule = new EnableBluetoothRule(false, true); - private final Context mContext = ApplicationProvider.getApplicationContext(); + private final Context mContext = + ApplicationProvider.getApplicationContext().createAttributionContext(TAG); private final BluetoothManager mBluetoothManager = mContext.getSystemService(BluetoothManager.class); private final BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter(); -- GitLab From 04942915a0f471d317fdf2dbd33287a27b88d44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Y=C4=B1lmaz?= Date: Tue, 5 Nov 2024 03:16:49 +0000 Subject: [PATCH 554/875] Obfuscate address logging in GattService and a few other files Bug: 376274765 Test: atest GattServiceTest Flag: Exempt log change Change-Id: If0c57cd783188815360ac0ae8ab02d71e9a5b656 --- .../bluetooth/btservice/InteropUtil.java | 24 +- .../bluetooth/btservice/RemoteDevices.java | 3 +- .../android/bluetooth/gatt/GattService.java | 283 ++++++++++++++---- .../le_scan/TransitionalScanHelper.java | 3 +- .../java/android/bluetooth/BluetoothGatt.java | 44 ++- .../bluetooth/BluetoothGattServer.java | 8 +- 6 files changed, 286 insertions(+), 79 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/InteropUtil.java b/android/app/src/com/android/bluetooth/btservice/InteropUtil.java index 93ab3ac4f2a..da6eb5b76ef 100644 --- a/android/app/src/com/android/bluetooth/btservice/InteropUtil.java +++ b/android/app/src/com/android/bluetooth/btservice/InteropUtil.java @@ -17,6 +17,7 @@ package com.android.bluetooth.btservice; +import android.bluetooth.BluetoothUtils; import android.util.Log; /** @@ -62,7 +63,12 @@ public class InteropUtil { return false; } - Log.d(TAG, "interopMatchAddr: feature=" + feature.name() + ", address=" + address); + Log.d( + TAG, + "interopMatchAddr: feature=" + + feature.name() + + ", address=" + + BluetoothUtils.toAnonymizedAddress(address)); if (address == null) { return false; } @@ -121,7 +127,12 @@ public class InteropUtil { return false; } - Log.d(TAG, "interopMatchAddrOrName: feature=" + feature.name() + ", address=" + address); + Log.d( + TAG, + "interopMatchAddrOrName: feature=" + + feature.name() + + ", address=" + + BluetoothUtils.toAnonymizedAddress(address)); if (address == null) { return false; } @@ -156,7 +167,7 @@ public class InteropUtil { "interopDatabaseAddAddr: feature=" + feature.name() + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", length=" + length); if (address == null || (length <= 0 || length > 6)) { @@ -184,7 +195,12 @@ public class InteropUtil { return; } - Log.d(TAG, "interopDatabaseRemoveAddr: feature=" + feature.name() + ", address=" + address); + Log.d( + TAG, + "interopDatabaseRemoveAddr: feature=" + + feature.name() + + ", address=" + + BluetoothUtils.toAnonymizedAddress(address)); if (address == null) { return; } diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index bd64fb6c7b3..bf52b589256 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -31,6 +31,7 @@ import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothSinkAudioPolicy; +import android.bluetooth.BluetoothUtils; import android.bluetooth.IBluetoothConnectionCallback; import android.content.Context; import android.content.Intent; @@ -183,7 +184,7 @@ public class RemoteDevices { debugLog( "reset(): address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", connected=" + bluetoothDevice.isConnected()); diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index cf50002922e..036fded700b 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -1312,14 +1312,17 @@ public class GattService extends ProfileService { + ", connId=" + connId + ", address=" - + address); + + BluetoothUtils.toAnonymizedAddress(address)); int connectionState = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED; if (status == 0) { mClientMap.addConnection(clientIf, connId, address); // Allow one writeCharacteristic operation at a time for each connected remote device. synchronized (mPermits) { - Log.d(TAG, "onConnected() - adding permit for address=" + address); + Log.d( + TAG, + "onConnected() - adding permit for address=" + + BluetoothUtils.toAnonymizedAddress(address)); mPermits.putIfAbsent(address, -1); } connectionState = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED; @@ -1342,7 +1345,7 @@ public class GattService extends ProfileService { + ", connId=" + connId + ", address=" - + address); + + BluetoothUtils.toAnonymizedAddress(address)); mClientMap.removeConnection(clientIf, connId); ContextMap.App app = mClientMap.getById(clientIf); @@ -1355,13 +1358,19 @@ public class GattService extends ProfileService { // device. if (!mClientMap.getConnectedDevices().contains(address)) { synchronized (mPermits) { - Log.d(TAG, "onDisconnected() - removing permit for address=" + address); + Log.d( + TAG, + "onDisconnected() - removing permit for address=" + + BluetoothUtils.toAnonymizedAddress(address)); mPermits.remove(address); } } else { synchronized (mPermits) { if (mPermits.get(address) == connId) { - Log.d(TAG, "onDisconnected() - set permit -1 for address=" + address); + Log.d( + TAG, + "onDisconnected() - set permit -1 for address=" + + BluetoothUtils.toAnonymizedAddress(address)); mPermits.put(address, -1); } } @@ -1399,7 +1408,7 @@ public class GattService extends ProfileService { Log.d( TAG, "onClientPhyRead() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", status=" + status + ", clientIf=" @@ -1407,7 +1416,10 @@ public class GattService extends ProfileService { Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.d(TAG, "onClientPhyRead() - no connection to " + address); + Log.d( + TAG, + "onClientPhyRead() - no connection to " + + BluetoothUtils.toAnonymizedAddress(address)); return; } @@ -1488,11 +1500,19 @@ public class GattService extends ProfileService { void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) throws RemoteException { - Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status); + Log.d( + TAG, + "onServerPhyRead() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", status=" + + status); Integer connId = mServerMap.connIdByAddress(serverIf, address); if (connId == null) { - Log.d(TAG, "onServerPhyRead() - no connection to " + address); + Log.d( + TAG, + "onServerPhyRead() - no connection to " + + BluetoothUtils.toAnonymizedAddress(address)); return; } @@ -1563,7 +1583,7 @@ public class GattService extends ProfileService { void onGetGattDb(int connId, List db) throws RemoteException { String address = mClientMap.addressByConnId(connId); - Log.d(TAG, "onGetGattDb() - address=" + address); + Log.d(TAG, "onGetGattDb() - address=" + BluetoothUtils.toAnonymizedAddress(address)); ContextMap.App app = mClientMap.getByConnId(connId); if (app == null || app.callback == null) { @@ -1654,7 +1674,7 @@ public class GattService extends ProfileService { Log.d( TAG, "onRegisterForNotifications() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", status=" + status + ", registered=" @@ -1669,7 +1689,7 @@ public class GattService extends ProfileService { Log.v( TAG, "onNotify() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", handle=" + handle + ", length=" @@ -1698,7 +1718,7 @@ public class GattService extends ProfileService { Log.v( TAG, "onReadCharacteristic() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", status=" + status + ", length=" @@ -1714,14 +1734,17 @@ public class GattService extends ProfileService { throws RemoteException { String address = mClientMap.addressByConnId(connId); synchronized (mPermits) { - Log.d(TAG, "onWriteCharacteristic() - increasing permit for address=" + address); + Log.d( + TAG, + "onWriteCharacteristic() - increasing permit for address=" + + BluetoothUtils.toAnonymizedAddress(address)); mPermits.put(address, -1); } Log.v( TAG, "onWriteCharacteristic() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", status=" + status + ", length=" @@ -1749,7 +1772,12 @@ public class GattService extends ProfileService { void onExecuteCompleted(int connId, int status) throws RemoteException { String address = mClientMap.addressByConnId(connId); - Log.v(TAG, "onExecuteCompleted() - address=" + address + ", status=" + status); + Log.v( + TAG, + "onExecuteCompleted() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", status=" + + status); ContextMap.App app = mClientMap.getByConnId(connId); if (app != null) { @@ -1763,7 +1791,7 @@ public class GattService extends ProfileService { Log.v( TAG, "onReadDescriptor() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", status=" + status + ", length=" @@ -1781,7 +1809,7 @@ public class GattService extends ProfileService { Log.v( TAG, "onWriteDescriptor() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", status=" + status + ", length=" @@ -1800,7 +1828,7 @@ public class GattService extends ProfileService { "onReadRemoteRssi() - clientIf=" + clientIf + " address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", rssi=" + rssi + ", status=" @@ -1815,7 +1843,14 @@ public class GattService extends ProfileService { void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { String address = mClientMap.addressByConnId(connId); - Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" + status + ", mtu=" + mtu); + Log.d( + TAG, + "onConfigureMTU() address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", status=" + + status + + ", mtu=" + + mtu); ContextMap.App app = mClientMap.getByConnId(connId); if (app != null) { @@ -2138,7 +2173,7 @@ public class GattService extends ProfileService { Log.d( TAG, "clientConnect() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", addressType=" + addressType + ", isDirect=" @@ -2178,7 +2213,14 @@ public class GattService extends ProfileService { } mNativeInterface.gattClientConnect( - clientIf, address, addressType, isDirect, transport, opportunistic, phy, preferredMtu); + clientIf, + address, + addressType, + isDirect, + transport, + opportunistic, + phy, + preferredMtu); } @RequiresPermission(BLUETOOTH_CONNECT) @@ -2189,7 +2231,12 @@ public class GattService extends ProfileService { } Integer connId = mClientMap.connIdByAddress(clientIf, address); - Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); + Log.d( + TAG, + "clientDisconnect() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", connId=" + + connId); statsLogGattConnectionStateChange( BluetoothProfile.GATT, address, @@ -2214,11 +2261,19 @@ public class GattService extends ProfileService { Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address); + Log.d( + TAG, + "clientSetPreferredPhy() - no connection to " + + BluetoothUtils.toAnonymizedAddress(address)); return; } - Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId); + Log.d( + TAG, + "clientSetPreferredPhy() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", connId=" + + connId); mNativeInterface.gattClientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions); } @@ -2231,11 +2286,19 @@ public class GattService extends ProfileService { Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.d(TAG, "clientReadPhy() - no connection to " + address); + Log.d( + TAG, + "clientReadPhy() - no connection to " + + BluetoothUtils.toAnonymizedAddress(address)); return; } - Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId); + Log.d( + TAG, + "clientReadPhy() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", connId=" + + connId); mNativeInterface.gattClientReadPhy(clientIf, address); } @@ -2271,7 +2334,7 @@ public class GattService extends ProfileService { return; } - Log.d(TAG, "refreshDevice() - address=" + address); + Log.d(TAG, "refreshDevice() - address=" + BluetoothUtils.toAnonymizedAddress(address)); mNativeInterface.gattClientRefresh(clientIf, address); } @@ -2283,12 +2346,21 @@ public class GattService extends ProfileService { } Integer connId = mClientMap.connIdByAddress(clientIf, address); - Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); + Log.d( + TAG, + "discoverServices() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", connId=" + + connId); if (connId != null) { mNativeInterface.gattClientSearchService(connId, true, 0, 0); } else { - Log.e(TAG, "discoverServices() - No connection for " + address + "..."); + Log.e( + TAG, + "discoverServices() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); } } @@ -2305,7 +2377,11 @@ public class GattService extends ProfileService { mNativeInterface.gattClientDiscoverServiceByUuid( connId, uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); } else { - Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "..."); + Log.e( + TAG, + "discoverServiceByUuid() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); } } @@ -2321,11 +2397,15 @@ public class GattService extends ProfileService { return; } - Log.v(TAG, "readCharacteristic() - address=" + address); + Log.v(TAG, "readCharacteristic() - address=" + BluetoothUtils.toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); + Log.e( + TAG, + "readCharacteristic() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); return; } @@ -2358,11 +2438,18 @@ public class GattService extends ProfileService { return; } - Log.v(TAG, "readUsingCharacteristicUuid() - address=" + address); + Log.v( + TAG, + "readUsingCharacteristicUuid() - address=" + + BluetoothUtils.toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "..."); + Log.e( + TAG, + "readUsingCharacteristicUuid() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); return; } @@ -2401,7 +2488,9 @@ public class GattService extends ProfileService { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } - Log.v(TAG, "writeCharacteristic() - address=" + address); + Log.v( + TAG, + "writeCharacteristic() - address=" + BluetoothUtils.toAnonymizedAddress(address)); if (mReliableQueue.contains(address)) { writeType = 3; // Prepared write @@ -2409,7 +2498,11 @@ public class GattService extends ProfileService { Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); + Log.e( + TAG, + "writeCharacteristic() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } permissionCheck(connId, handle); @@ -2447,11 +2540,15 @@ public class GattService extends ProfileService { return; } - Log.v(TAG, "readDescriptor() - address=" + address); + Log.v(TAG, "readDescriptor() - address=" + BluetoothUtils.toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); + Log.e( + TAG, + "readDescriptor() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); return; } @@ -2482,11 +2579,15 @@ public class GattService extends ProfileService { this, attributionSource, "GattService writeDescriptor")) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } - Log.v(TAG, "writeDescriptor() - address=" + address); + Log.v(TAG, "writeDescriptor() - address=" + BluetoothUtils.toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); + Log.e( + TAG, + "writeDescriptor() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } permissionCheck(connId, handle); @@ -2502,7 +2603,7 @@ public class GattService extends ProfileService { return; } - Log.d(TAG, "beginReliableWrite() - address=" + address); + Log.d(TAG, "beginReliableWrite() - address=" + BluetoothUtils.toAnonymizedAddress(address)); mReliableQueue.add(address); } @@ -2514,7 +2615,12 @@ public class GattService extends ProfileService { return; } - Log.d(TAG, "endReliableWrite() - address=" + address + " execute: " + execute); + Log.d( + TAG, + "endReliableWrite() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " execute: " + + execute); mReliableQueue.remove(address); Integer connId = mClientMap.connIdByAddress(clientIf, address); @@ -2535,11 +2641,20 @@ public class GattService extends ProfileService { return; } - Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); + Log.d( + TAG, + "registerForNotification() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " enable: " + + enable); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); + Log.e( + TAG, + "registerForNotification() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); return; } @@ -2565,7 +2680,7 @@ public class GattService extends ProfileService { return; } - Log.d(TAG, "readRemoteRssi() - address=" + address); + Log.d(TAG, "readRemoteRssi() - address=" + BluetoothUtils.toAnonymizedAddress(address)); mNativeInterface.gattClientReadRemoteRssi(clientIf, address); } @@ -2576,12 +2691,21 @@ public class GattService extends ProfileService { return; } - Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); + Log.d( + TAG, + "configureMTU() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " mtu=" + + mtu); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId != null) { mNativeInterface.gattClientConfigureMTU(connId, mtu); } else { - Log.e(TAG, "configureMTU() - No connection for " + address + "..."); + Log.e( + TAG, + "configureMTU() - No connection for " + + BluetoothUtils.toAnonymizedAddress(address) + + "..."); } } @@ -2620,7 +2744,7 @@ public class GattService extends ProfileService { Log.d( TAG, "connectionParameterUpdate() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + " params=" + connectionPriority + " interval=" @@ -2653,7 +2777,7 @@ public class GattService extends ProfileService { Log.d( TAG, "leConnectionUpdate() - address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", intervals=" + minInterval + "/" @@ -2887,7 +3011,7 @@ public class GattService extends ProfileService { "onClientConnected() connId=" + connId + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", connected=" + connected); @@ -2928,7 +3052,7 @@ public class GattService extends ProfileService { "onServerReadCharacteristic() connId=" + connId + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -2959,7 +3083,7 @@ public class GattService extends ProfileService { "onServerReadDescriptor() connId=" + connId + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -2998,7 +3122,7 @@ public class GattService extends ProfileService { "onServerWriteCharacteristic() connId=" + connId + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -3040,7 +3164,7 @@ public class GattService extends ProfileService { "onAttributeWrite() connId=" + connId + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -3073,7 +3197,7 @@ public class GattService extends ProfileService { "onExecuteWrite() connId=" + connId + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", transId=" + transId); @@ -3195,7 +3319,7 @@ public class GattService extends ProfileService { return; } - Log.d(TAG, "serverConnect() - address=" + address); + Log.d(TAG, "serverConnect() - address=" + BluetoothUtils.toAnonymizedAddress(address)); logServerForegroundInfo(attributionSource.getUid(), isDirect); @@ -3210,7 +3334,12 @@ public class GattService extends ProfileService { } Integer connId = mServerMap.connIdByAddress(serverIf, address); - Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); + Log.d( + TAG, + "serverDisconnect() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", connId=" + + connId); mNativeInterface.gattServerDisconnect(serverIf, address, connId != null ? connId : 0); } @@ -3230,11 +3359,19 @@ public class GattService extends ProfileService { Integer connId = mServerMap.connIdByAddress(serverIf, address); if (connId == null) { - Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address); + Log.d( + TAG, + "serverSetPreferredPhy() - no connection to " + + BluetoothUtils.toAnonymizedAddress(address)); return; } - Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId); + Log.d( + TAG, + "serverSetPreferredPhy() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", connId=" + + connId); mNativeInterface.gattServerSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions); } @@ -3247,11 +3384,19 @@ public class GattService extends ProfileService { Integer connId = mServerMap.connIdByAddress(serverIf, address); if (connId == null) { - Log.d(TAG, "serverReadPhy() - no connection to " + address); + Log.d( + TAG, + "serverReadPhy() - no connection to " + + BluetoothUtils.toAnonymizedAddress(address)); return; } - Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId); + Log.d( + TAG, + "serverReadPhy() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", connId=" + + connId); mNativeInterface.gattServerReadPhy(serverIf, address); } @@ -3339,7 +3484,12 @@ public class GattService extends ProfileService { return; } - Log.v(TAG, "sendResponse() - address=" + address + ", requestId=" + requestId); + Log.v( + TAG, + "sendResponse() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", requestId=" + + requestId); int handle = 0; Integer connId = 0; @@ -3384,7 +3534,12 @@ public class GattService extends ProfileService { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } - Log.v(TAG, "sendNotification() - address=" + address + " handle=" + handle); + Log.v( + TAG, + "sendNotification() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " handle=" + + handle); Integer connId = mServerMap.connIdByAddress(serverIf, address); if (connId == null || connId == 0) { diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java index 09f3626ad7c..8c4b290bd69 100644 --- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java +++ b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java @@ -28,6 +28,7 @@ import android.app.AppOpsManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothUtils; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.IPeriodicAdvertisingCallback; import android.bluetooth.le.IScannerCallback; @@ -342,7 +343,7 @@ public class TransitionalScanHelper { + ", addressType=" + addressType + ", address=" - + address + + BluetoothUtils.toAnonymizedAddress(address) + ", primaryPhy=" + primaryPhy + ", secondaryPhy=" diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java index 92d058207f6..4631953202a 100644 --- a/framework/java/android/bluetooth/BluetoothGatt.java +++ b/framework/java/android/bluetooth/BluetoothGatt.java @@ -299,7 +299,8 @@ public final class BluetoothGatt implements BluetoothProfile { TAG, "onPhyUpdate() -" + (" status=" + status) - + (" address=" + address) + + (" address=" + + BluetoothUtils.toAnonymizedAddress(address)) + (" txPhy=" + txPhy) + (" rxPhy=" + rxPhy)); } @@ -332,7 +333,8 @@ public final class BluetoothGatt implements BluetoothProfile { TAG, "onPhyRead() -" + (" status=" + status) - + (" address=" + address) + + (" address=" + + BluetoothUtils.toAnonymizedAddress(address)) + (" txPhy=" + txPhy) + (" rxPhy=" + rxPhy)); } @@ -414,7 +416,12 @@ public final class BluetoothGatt implements BluetoothProfile { public void onSearchComplete( String address, List services, int status) { if (DBG) { - Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status); + Log.d( + TAG, + "onSearchComplete() = address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " status=" + + status); } if (!address.equals(mDevice.getAddress())) { return; @@ -613,8 +620,14 @@ public final class BluetoothGatt implements BluetoothProfile { */ @Override public void onNotify(String address, int handle, byte[] value) { - if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle); - + if (VDBG) { + Log.d( + TAG, + "onNotify() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " handle=" + + handle); + } if (!address.equals(mDevice.getAddress())) { return; } @@ -646,7 +659,12 @@ public final class BluetoothGatt implements BluetoothProfile { @SuppressLint("AndroidFrameworkRequiresPermission") public void onDescriptorRead(String address, int status, int handle, byte[] value) { if (VDBG) { - Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle); + Log.d( + TAG, + "onDescriptorRead() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " handle=" + + handle); } if (!address.equals(mDevice.getAddress())) { @@ -703,7 +721,12 @@ public final class BluetoothGatt implements BluetoothProfile { public void onDescriptorWrite( String address, int status, int handle, byte[] value) { if (VDBG) { - Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle); + Log.d( + TAG, + "onDescriptorWrite() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " handle=" + + handle); } if (!address.equals(mDevice.getAddress())) { @@ -757,7 +780,12 @@ public final class BluetoothGatt implements BluetoothProfile { @Override public void onExecuteWrite(String address, int status) { if (VDBG) { - Log.d(TAG, "onExecuteWrite() - Device=" + address + " status=" + status); + Log.d( + TAG, + "onExecuteWrite() - address=" + + BluetoothUtils.toAnonymizedAddress(address) + + " status=" + + status); } if (!address.equals(mDevice.getAddress())) { return; diff --git a/framework/java/android/bluetooth/BluetoothGattServer.java b/framework/java/android/bluetooth/BluetoothGattServer.java index 289b587b433..53b491e1b30 100644 --- a/framework/java/android/bluetooth/BluetoothGattServer.java +++ b/framework/java/android/bluetooth/BluetoothGattServer.java @@ -357,7 +357,13 @@ public final class BluetoothGattServer implements BluetoothProfile { @Override public void onMtuChanged(String address, int mtu) { if (DBG) { - Log.d(TAG, "onMtuChanged() - " + "device=" + address + ", mtu=" + mtu); + Log.d( + TAG, + "onMtuChanged() - " + + "device=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", mtu=" + + mtu); } BluetoothDevice device = mAdapter.getRemoteDevice(address); -- GitLab From de941d1f88188a4b83b977a9095f6886de4ab14e Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 4 Nov 2024 20:58:14 -0800 Subject: [PATCH 555/875] Lint as error: GetterSetterNullability Prevent spreading of usage Bug: 311772251 Flag: Exempt adding lint error Test: m . Change-Id: I83f450da91a1d5cea9faa0c18674ac7e7a403a03 --- android/app/Android.bp | 1 + framework/Android.bp | 1 + 2 files changed, 2 insertions(+) diff --git a/android/app/Android.bp b/android/app/Android.bp index 83de2861e97..f1cf8e3e8a8 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -306,6 +306,7 @@ android_app { "ExtraText", "ExtraTranslation", "GestureBackNavigation", + "GetterSetterNullability", "GuardedLogInvocation", "HandlerLeak", "InflateParams", diff --git a/framework/Android.bp b/framework/Android.bp index 2eca8df89bc..7c0d3e925f1 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -104,6 +104,7 @@ java_sdk_library { "ExtraTranslation", "FlaggedApi", "GestureBackNavigation", + "GetterSetterNullability", "GuardedLogInvocation", "HandlerLeak", "InflateParams", -- GitLab From ac31113456e9d4f1bf98c31c5118542f73505584 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 4 Nov 2024 21:41:10 -0800 Subject: [PATCH 556/875] Update owners file Bug: 311772251 Test: m . Flag: exempt owner only Change-Id: Ied2220c323da7a4a216f1218415af50ba5d30b17 --- OWNERS_hearingaid | 2 +- android/pandora/OWNERS | 1 - android/pandora/test/OWNERS | 3 --- framework/tests/bumble/OWNERS | 5 ----- pandora/OWNERS | 1 - 5 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 android/pandora/test/OWNERS delete mode 100644 framework/tests/bumble/OWNERS diff --git a/OWNERS_hearingaid b/OWNERS_hearingaid index e70772a9527..d1c75de9006 100644 --- a/OWNERS_hearingaid +++ b/OWNERS_hearingaid @@ -1 +1 @@ -charliebout@google.com +henrichataing@google.com diff --git a/android/pandora/OWNERS b/android/pandora/OWNERS index ffae7f10689..c199a82a60d 100644 --- a/android/pandora/OWNERS +++ b/android/pandora/OWNERS @@ -1,3 +1,2 @@ # Bug component: 1099313 girardier@google.com -charliebout@google.com diff --git a/android/pandora/test/OWNERS b/android/pandora/test/OWNERS deleted file mode 100644 index ffae7f10689..00000000000 --- a/android/pandora/test/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# Bug component: 1099313 -girardier@google.com -charliebout@google.com diff --git a/framework/tests/bumble/OWNERS b/framework/tests/bumble/OWNERS deleted file mode 100644 index 5bc200e24b5..00000000000 --- a/framework/tests/bumble/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -# Bug component: 1099313 -# Project owners -set noparent -girardier@google.com -charliebout@google.com diff --git a/pandora/OWNERS b/pandora/OWNERS index f45a253e5c5..14634f3b784 100644 --- a/pandora/OWNERS +++ b/pandora/OWNERS @@ -1,3 +1,2 @@ # Project owners girardier@google.com -charliebout@google.com -- GitLab From 8f53a23f3c00b6101d166a0ff470aa1a2c1a0d6b Mon Sep 17 00:00:00 2001 From: Kokoa Matsuda Date: Thu, 31 Oct 2024 15:39:11 +0900 Subject: [PATCH 557/875] Replace libchrome StringPrintf in system/bta/test/ files This change is to remove the direct dependency on libchrome. Replaces StringPrintf in with android::base::StringPrintf in . This change is very mechanical, no change in program behavior. Test: m . Bug: 360917504 Change-Id: I168437505d6e82c7c964e7e01765a521cb72ca9f --- system/bta/test/bta_api_test.cc | 3 ++- system/bta/test/bta_disc_test.cc | 2 +- system/bta/test/bta_dm_test.cc | 10 ++++++---- system/bta/test/bta_gatt_client_test.cc | 6 +++--- system/bta/test/bta_sec_test.cc | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/system/bta/test/bta_api_test.cc b/system/bta/test/bta_api_test.cc index 5172e93100c..0075fa560a5 100644 --- a/system/bta/test/bta_api_test.cc +++ b/system/bta/test/bta_api_test.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -46,7 +47,7 @@ TEST_F(BtaApiTest, bta_status_text) { for (const auto& status : statuses) { ASSERT_STREQ(status.second.c_str(), bta_status_text(status.first).c_str()); } - auto unknown = base::StringPrintf("UNKNOWN[%d]", std::numeric_limits::max()); + auto unknown = fmt::format("UNKNOWN[{}]", std::numeric_limits::max()); ASSERT_STREQ( unknown.c_str(), bta_status_text(static_cast(std::numeric_limits::max())).c_str()); diff --git a/system/bta/test/bta_disc_test.cc b/system/bta/test/bta_disc_test.cc index 6a9aa3b005b..0979226b9dd 100644 --- a/system/bta/test/bta_disc_test.cc +++ b/system/bta/test/bta_disc_test.cc @@ -16,11 +16,11 @@ #define LOG_TAG "bt_bta_dm_test" -#include #include #include #include #include +#include #include #include #include diff --git a/system/bta/test/bta_dm_test.cc b/system/bta/test/bta_dm_test.cc index 4f91d74e299..e4d2fb9f916 100644 --- a/system/bta/test/bta_dm_test.cc +++ b/system/bta/test/bta_dm_test.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -426,10 +427,11 @@ TEST_F(BtaDmTest, bta_dm_search_evt_text) { for (const auto& event : events) { ASSERT_STREQ(event.second.c_str(), bta_dm_search_evt_text(event.first).c_str()); } - ASSERT_STREQ(base::StringPrintf("UNKNOWN[%hhu]", std::numeric_limits::max()).c_str(), - bta_dm_search_evt_text( - static_cast(std::numeric_limits::max())) - .c_str()); + ASSERT_STREQ( + fmt::format("UNKNOWN[{}]", std::numeric_limits::max()).c_str(), + bta_dm_search_evt_text( + static_cast(std::numeric_limits::max())) + .c_str()); } TEST_F(BtaDmTest, bta_dm_remote_name_cmpl) { diff --git a/system/bta/test/bta_gatt_client_test.cc b/system/bta/test/bta_gatt_client_test.cc index 60a7fd943e3..5dca10548eb 100644 --- a/system/bta/test/bta_gatt_client_test.cc +++ b/system/bta/test/bta_gatt_client_test.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -54,11 +54,11 @@ TEST_F(BtaDiscTest, gatt_history_callback) { }; // C string - gatt_history_callback(base::StringPrintf("%s", a[0].c_str())); + gatt_history_callback(fmt::format("{}", a[0].c_str())); // Cpp string gatt_history_callback(a[1]); // Third entry for "fun" - gatt_history_callback(base::StringPrintf("%s", a[2].c_str())); + gatt_history_callback(fmt::format("{}", a[2].c_str())); std::vector> history = bluetooth::legacy::testing::PullCopyOfGattHistory(); diff --git a/system/bta/test/bta_sec_test.cc b/system/bta/test/bta_sec_test.cc index bee18526284..ddf83e5e5dc 100644 --- a/system/bta/test/bta_sec_test.cc +++ b/system/bta/test/bta_sec_test.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include +#include #include #include #include -- GitLab From 944a9dcac3030a92d523f59502ac64d4a7ee7e1b Mon Sep 17 00:00:00 2001 From: Chris Manton Date: Wed, 30 Oct 2024 14:41:49 -0700 Subject: [PATCH 558/875] stack::avrc Check alarm state before setting Bug: 343127654 Test: atest net_test_stack Flag: EXEMPT, Null pointer exemption Change-Id: I5ede451510ee749b8cfde953d06929f19ec4b9b1 --- system/stack/avrc/avrc_api.cc | 13 ++++++++++--- system/stack/avrc/avrc_int.h | 1 - system/test/mock/mock_stack_avrc_api.cc | 3 --- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/system/stack/avrc/avrc_api.cc b/system/stack/avrc/avrc_api.cc index 28f6f85064e..ea82921b432 100644 --- a/system/stack/avrc/avrc_api.cc +++ b/system/stack/avrc/avrc_api.cc @@ -82,6 +82,8 @@ static const uint8_t avrc_ctrl_event_map[] = { #define AVRC_MSG_MASK_IS_VENDOR_CMD 0x01 #define AVRC_MSG_MASK_IS_CONTINUATION_RSP 0x02 +static void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask); + /****************************************************************************** * * Function avrcp_absolute_volume_is_enabled @@ -216,14 +218,19 @@ void avrc_send_next_vendor_cmd(uint8_t handle) { * Returns Nothing. * *****************************************************************************/ -void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask) { +static void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask) { + if (!avrc_cb.ccb_int[handle].tle) { + log::warn("Unable to start response timer handle=0x{:02x} label=0x{:02x} msg_mask:0x{:02x}", + handle, label, msg_mask); + return; + } + tAVRC_PARAM* param = static_cast(osi_malloc(sizeof(tAVRC_PARAM))); param->handle = handle; param->label = label; param->msg_mask = msg_mask; - log::verbose("AVRC: starting timer (handle=0x{:02x}, label=0x{:02x})", handle, label); - + log::verbose("AVRC: starting timer (handle=0x{:02x} label=0x{:02x})", handle, label); alarm_set_on_mloop(avrc_cb.ccb_int[handle].tle, AVRC_CMD_TOUT_MS, avrc_process_timeout, param); } diff --git a/system/stack/avrc/avrc_int.h b/system/stack/avrc/avrc_int.h index 3394bb1c7df..cf3a0dec356 100644 --- a/system/stack/avrc/avrc_int.h +++ b/system/stack/avrc/avrc_int.h @@ -159,7 +159,6 @@ tAVRC_STS avrc_pars_pass_thru(tAVRC_MSG_PASS* p_msg, uint16_t* p_vendor_unique_i uint8_t avrc_opcode_from_pdu(uint8_t pdu); bool avrc_is_valid_opcode(uint8_t opcode); void avrc_flush_cmd_q(uint8_t handle); -void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask); void avrc_send_next_vendor_cmd(uint8_t handle); #endif /* AVRC_INT_H */ diff --git a/system/test/mock/mock_stack_avrc_api.cc b/system/test/mock/mock_stack_avrc_api.cc index 655690c7ecd..eedf4339b5d 100644 --- a/system/test/mock/mock_stack_avrc_api.cc +++ b/system/test/mock/mock_stack_avrc_api.cc @@ -77,6 +77,3 @@ uint16_t AVRC_PassRsp(uint8_t /* handle */, uint8_t /* label */, tAVRC_MSG_PASS* } void avrc_flush_cmd_q(uint8_t /* handle */) { inc_func_call_count(__func__); } void avrc_send_next_vendor_cmd(uint8_t /* handle */) { inc_func_call_count(__func__); } -void avrc_start_cmd_timer(uint8_t /* handle */, uint8_t /* label */, uint8_t /* msg_mask */) { - inc_func_call_count(__func__); -} -- GitLab From 1e71c96295e54b024bd76419a867b5bc228a34dc Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 15:12:50 -0700 Subject: [PATCH 559/875] AICS: onExtAudioInStateChanged: skip serialize Bug: 361263965 Test: atest vc_test Flag: com.android.bluetooth.flags.leaudio_add_aics_support Change-Id: Id79e5ae2249ee99eab4749f32e85eb937e60608c --- .../vc/VolumeControlNativeCallback.java | 33 +++++++++++-------- .../bluetooth/vc/VolumeControlService.java | 14 ++------ .../bluetooth/vc/VolumeControlStackEvent.java | 10 ------ .../vc/VolumeControlNativeCallbackTest.java | 16 +++++---- 4 files changed, 31 insertions(+), 42 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java index 8b6202a5bc9..c6bc5706dec 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -20,7 +20,6 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNEC import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; @@ -36,6 +35,9 @@ import android.util.Log; import com.android.bluetooth.btservice.AdapterService; import com.android.internal.annotations.VisibleForTesting; +import java.util.Arrays; +import java.util.function.Consumer; + class VolumeControlNativeCallback { private static final String TAG = VolumeControlNativeCallback.class.getSimpleName(); @@ -52,6 +54,18 @@ class VolumeControlNativeCallback { return mAdapterService.getDeviceFromByte(address); } + private void sendMessageToService(Consumer action) { + if (!mVolumeControlService.isAvailable()) { + StringBuilder sb = new StringBuilder(); + Arrays.stream(new Throwable().getStackTrace()) + .skip(1) // skip the inlineStackTrace method in the outputted stack trace + .forEach(trace -> sb.append(" [at ").append(trace).append("]")); + Log.e(TAG, "Action ignored, service not available: " + sb.toString()); + return; + } + action.accept(mVolumeControlService); + } + @VisibleForTesting void onConnectionStateChanged(int state, byte[] address) { VolumeControlStackEvent event = @@ -141,18 +155,11 @@ class VolumeControlNativeCallback { } @VisibleForTesting - void onExtAudioInStateChanged( - int externalInputId, int gainSetting, int mute, int gainMode, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = gainSetting; - event.valueInt3 = gainMode; - event.valueInt4 = mute; - - Log.d(TAG, "onExtAudioInStateChanged: " + event); - mVolumeControlService.messageFromNative(event); + void onExtAudioInStateChanged(int id, int gainSetting, int gainMode, int mute, byte[] address) { + sendMessageToService( + s -> + s.onExtAudioInStateChanged( + getDevice(address), id, gainSetting, mute, gainMode)); } @VisibleForTesting diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index b267343abe5..ba5ade2aa6e 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -1030,10 +1030,10 @@ public class VolumeControlService extends ProfileService { } } - void handleDeviceExtInputStateChanged( + void onExtAudioInStateChanged( BluetoothDevice device, int id, int gainSetting, int mute, int gainMode) { String logInfo = - "handleDeviceExtInputStateChanged(" + "onExtAudioInStateChanged(" + ("device:" + device) + (", id" + id) + (" gainSetting: " + gainSetting) @@ -1184,16 +1184,6 @@ public class VolumeControlService extends ProfileService { return; } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED) { - handleDeviceExtInputStateChanged( - device, - stackEvent.valueInt1, - stackEvent.valueInt2, - stackEvent.valueInt4, - stackEvent.valueInt3); - return; - } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED) { handleDeviceExtInputStatusChanged(device, stackEvent.valueInt1, stackEvent.valueInt2); return; diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index 5b5fe0d36ae..e30e6e1fb02 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -29,7 +29,6 @@ public class VolumeControlStackEvent { public static final int EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED = 4; public static final int EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED = 5; public static final int EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED = 6; - public static final int EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED = 7; public static final int EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED = 8; public static final int EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED = 9; public static final int EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED = 10; @@ -84,8 +83,6 @@ public class VolumeControlStackEvent { return "EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED"; case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED"; - case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED: - return "EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED"; case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED: return "EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED"; case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: @@ -111,7 +108,6 @@ public class VolumeControlStackEvent { case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED: case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "{ext output id:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: @@ -131,8 +127,6 @@ public class VolumeControlStackEvent { return "{volume:" + value + "}"; case EVENT_TYPE_DEVICE_AVAILABLE: return "{num_ext_inputs:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED: - return "{ext gain val:" + value + "}"; case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED: return "{status:" + value + "}"; case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: @@ -145,8 +139,6 @@ public class VolumeControlStackEvent { private static String eventTypeValue3ToString(int type, int value) { switch (type) { - case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED: - return "{ext gain mode:" + value + "}"; case EVENT_TYPE_VOLUME_STATE_CHANGED: return "{flags:" + value + "}"; default: @@ -159,8 +151,6 @@ public class VolumeControlStackEvent { switch (type) { case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: return "{gain set max:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED: - return "{mute:" + value + "}"; default: break; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java index 1a73e74dec2..d36c60ddfa9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -20,7 +20,6 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNEC import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; @@ -28,6 +27,9 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AU import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; import android.bluetooth.BluetoothProfile; @@ -61,6 +63,8 @@ public class VolumeControlNativeCallbackTest { @Before public void setUp() throws Exception { + doReturn(true).when(mService).isAvailable(); + mNativeCallback = new VolumeControlNativeCallback(mAdapterService, mService); } @@ -158,16 +162,14 @@ public class VolumeControlNativeCallbackTest { @Test public void onExtAudioInStateChanged() { - int externalInputId = 2; + int id = 2; int gainSetting = 1; int gainMode = 0; int mute = 0; - mNativeCallback.onExtAudioInStateChanged(externalInputId, gainSetting, mute, gainMode, null); - verify(mService).messageFromNative(mEvent.capture()); - VolumeControlStackEvent event = mEvent.getValue(); - - expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); + mNativeCallback.onExtAudioInStateChanged(id, gainSetting, mute, gainMode, null); + verify(mService) + .onExtAudioInStateChanged(any(), eq(id), eq(gainSetting), eq(mute), eq(gainMode)); } @Test -- GitLab From d1a4aa17b514a62f06cd54f75d8c1327b4426117 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 16:06:55 -0700 Subject: [PATCH 560/875] AICS: onExtAudioInStatusChanged: skip serialize Bug: 361263965 Test: atest vc_test Flag: com.android.bluetooth.flags.leaudio_add_aics_support Change-Id: Ieac5e4aa76a0d6e6674298c7e83ef775920116ad --- .../bluetooth/vc/VolumeControlNativeCallback.java | 12 ++---------- .../android/bluetooth/vc/VolumeControlService.java | 9 ++------- .../bluetooth/vc/VolumeControlStackEvent.java | 6 ------ .../vc/VolumeControlNativeCallbackTest.java | 10 +++------- 4 files changed, 7 insertions(+), 30 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java index c6bc5706dec..27a819895f6 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -20,7 +20,6 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNEC import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; @@ -163,15 +162,8 @@ class VolumeControlNativeCallback { } @VisibleForTesting - void onExtAudioInStatusChanged(int externalInputId, int status, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = status; - - Log.d(TAG, "onExtAudioInStatusChanged: " + event); - mVolumeControlService.messageFromNative(event); + void onExtAudioInStatusChanged(int id, int status, byte[] address) { + sendMessageToService(s -> s.onExtAudioInStatusChanged(getDevice(address), id, status)); } @VisibleForTesting diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index ba5ade2aa6e..910aabf8f8d 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -1051,9 +1051,9 @@ public class VolumeControlService extends ProfileService { input.setState(id, gainSetting, mute, gainMode); } - void handleDeviceExtInputStatusChanged(BluetoothDevice device, int id, int status) { + void onExtAudioInStatusChanged(BluetoothDevice device, int id, int status) { String logInfo = - "handleDeviceExtInputStatusChanged(" + "onExtAudioInStatusChanged(" + ("device:" + device) + (", id" + id) + (", status" + status) @@ -1184,11 +1184,6 @@ public class VolumeControlService extends ProfileService { return; } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED) { - handleDeviceExtInputStatusChanged(device, stackEvent.valueInt1, stackEvent.valueInt2); - return; - } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED) { handleDeviceExtInputTypeChanged(device, stackEvent.valueInt1, stackEvent.valueInt2); return; diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index e30e6e1fb02..8afc4be9ac4 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -29,7 +29,6 @@ public class VolumeControlStackEvent { public static final int EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED = 4; public static final int EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED = 5; public static final int EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED = 6; - public static final int EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED = 8; public static final int EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED = 9; public static final int EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED = 10; public static final int EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED = 11; @@ -83,8 +82,6 @@ public class VolumeControlStackEvent { return "EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED"; case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED"; - case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED: - return "EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED"; case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: return "EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED"; case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: @@ -108,7 +105,6 @@ public class VolumeControlStackEvent { case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED: case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "{ext output id:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: @@ -127,8 +123,6 @@ public class VolumeControlStackEvent { return "{volume:" + value + "}"; case EVENT_TYPE_DEVICE_AVAILABLE: return "{num_ext_inputs:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED: - return "{status:" + value + "}"; case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: return "{type:" + value + "}"; default: diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java index d36c60ddfa9..0a884ac5069 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -20,7 +20,6 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNEC import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; @@ -174,14 +173,11 @@ public class VolumeControlNativeCallbackTest { @Test public void onExtAudioInStatusChanged() { - int externalInputId = 2; + int id = 2; int status = 1; - mNativeCallback.onExtAudioInStatusChanged(externalInputId, status, null); - verify(mService).messageFromNative(mEvent.capture()); - VolumeControlStackEvent event = mEvent.getValue(); - - expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); + mNativeCallback.onExtAudioInStatusChanged(id, status, null); + verify(mService).onExtAudioInStatusChanged(any(), eq(id), eq(status)); } @Test -- GitLab From cfe847b827f7dfbd660deeabec986fb180e33edd Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 16:16:16 -0700 Subject: [PATCH 561/875] AICS: onExtAudioInTypeChanged: skip serialize Bug: 361263965 Test: atest vc_test Flag: com.android.bluetooth.flags.leaudio_add_aics_support Change-Id: Ibfb4d480933630a37738b2a6664d185ebb421d3c --- .../bluetooth/vc/VolumeControlNativeCallback.java | 12 ++---------- .../android/bluetooth/vc/VolumeControlService.java | 9 ++------- .../bluetooth/vc/VolumeControlStackEvent.java | 6 ------ .../vc/VolumeControlNativeCallbackTest.java | 10 +++------- 4 files changed, 7 insertions(+), 30 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java index 27a819895f6..58ceee3b6b2 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -20,7 +20,6 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNEC import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; @@ -167,15 +166,8 @@ class VolumeControlNativeCallback { } @VisibleForTesting - void onExtAudioInTypeChanged(int externalInputId, int type, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = type; - - Log.d(TAG, "onExtAudioInTypeChanged: " + event); - mVolumeControlService.messageFromNative(event); + void onExtAudioInTypeChanged(int id, int type, byte[] address) { + sendMessageToService(s -> s.onExtAudioInTypeChanged(getDevice(address), id, type)); } @VisibleForTesting diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 910aabf8f8d..81465cc51d8 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -1074,9 +1074,9 @@ public class VolumeControlService extends ProfileService { input.setStatus(id, status); } - void handleDeviceExtInputTypeChanged(BluetoothDevice device, int id, int type) { + void onExtAudioInTypeChanged(BluetoothDevice device, int id, int type) { String logInfo = - "handleDeviceExtInputTypeChanged(" + "onExtAudioInTypeChanged(" + ("device:" + device) + (", id" + id) + (", type" + type) @@ -1184,11 +1184,6 @@ public class VolumeControlService extends ProfileService { return; } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED) { - handleDeviceExtInputTypeChanged(device, stackEvent.valueInt1, stackEvent.valueInt2); - return; - } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED) { handleDeviceExtInputDescriptionChanged( device, stackEvent.valueInt1, stackEvent.valueString1); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index 8afc4be9ac4..83a6941bb3e 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -29,7 +29,6 @@ public class VolumeControlStackEvent { public static final int EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED = 4; public static final int EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED = 5; public static final int EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED = 6; - public static final int EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED = 9; public static final int EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED = 10; public static final int EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED = 11; @@ -82,8 +81,6 @@ public class VolumeControlStackEvent { return "EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED"; case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED"; - case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: - return "EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED"; case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: return "EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED"; case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: @@ -105,7 +102,6 @@ public class VolumeControlStackEvent { case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED: case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "{ext output id:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: return "{ext input id:" + value + "}"; @@ -123,8 +119,6 @@ public class VolumeControlStackEvent { return "{volume:" + value + "}"; case EVENT_TYPE_DEVICE_AVAILABLE: return "{num_ext_inputs:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED: - return "{type:" + value + "}"; default: break; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java index 0a884ac5069..f9ef9eb843c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -20,7 +20,6 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNEC import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; @@ -182,14 +181,11 @@ public class VolumeControlNativeCallbackTest { @Test public void onExtAudioInTypeChanged() { - int externalInputId = 2; + int id = 2; int type = 1; - mNativeCallback.onExtAudioInTypeChanged(externalInputId, type, null); - verify(mService).messageFromNative(mEvent.capture()); - VolumeControlStackEvent event = mEvent.getValue(); - - expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); + mNativeCallback.onExtAudioInTypeChanged(id, type, null); + verify(mService).onExtAudioInTypeChanged(any(), eq(id), eq(type)); } @Test -- GitLab From 57679d53567fe1f82f951290c75442d60c9cd6c2 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 14:23:27 -0700 Subject: [PATCH 562/875] VCP: Split nativeInterface from nativeCallback One is going down to the native, the other from. This allow to have a couple final method in the nativeCallback and remove the need for null pointer check (by design) Similar as HAP implementation https://r.android.com/2953314 -> direct use of native interface https://r.android.com/3199943 -> callback split Bug: 311772251 Bug: 361263965 Test: atest BluetoothInstrumentationTests Test: atest VolumeControlNativeCallbackTest Flag: com.android.bluetooth.flags.leaudio_add_aics_support Change-Id: Ia167c8db9f5de5f9dd6508abde1bf9b8e4b0cbb8 --- Android.bp | 5 +- android/app/jni/com_android_bluetooth_vc.cpp | 13 +- .../vc/VolumeControlNativeCallback.java | 208 ++++++++ .../vc/VolumeControlNativeInterface.java | 459 ++---------------- .../bluetooth/vc/VolumeControlService.java | 14 +- .../btservice/ProfileServiceTest.java | 5 +- .../vc/VolumeControlNativeCallbackTest.java | 222 +++++++++ .../vc/VolumeControlNativeInterfaceTest.java | 245 ---------- 8 files changed, 498 insertions(+), 673 deletions(-) create mode 100644 android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java create mode 100644 android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java delete mode 100644 android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java diff --git a/Android.bp b/Android.bp index 71d6d402c26..582182c104a 100644 --- a/Android.bp +++ b/Android.bp @@ -165,6 +165,7 @@ java_defaults { "-Xep:UnusedMethod:ERROR", "-Xep:UnusedNestedClass:ERROR", "-Xep:UnusedVariable:ERROR", + "-Xep:VariableNameSameAsType:ERROR", "-Xep:WaitNotInLoop:ERROR", "-Xep:WakelockReleasedDangerously:ERROR", @@ -172,8 +173,8 @@ java_defaults { "-XepExcludedPaths:.*/srcjars/.*", // The @InlineMe annotation could be made available, but it would - // apply on external facing API. This is not desired. For more - // context, see https://r.android.com/3303475 + // apply on external facing API. This is not desired. + // For more context, see https://r.android.com/3303475 "-Xep:InlineMeSuggester:OFF", ], }, diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp index 80ef9d71848..166d212939e 100644 --- a/android/app/jni/com_android_bluetooth_vc.cpp +++ b/android/app/jni/com_android_bluetooth_vc.cpp @@ -62,6 +62,8 @@ static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; +static jfieldID sCallbacksField; + class VolumeControlCallbacksImpl : public VolumeControlCallbacks { public: ~VolumeControlCallbacksImpl() = default; @@ -362,7 +364,8 @@ static void initNative(JNIEnv* env, jobject object) { mCallbacksObj = nullptr; } - if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { + if ((mCallbacksObj = env->NewGlobalRef(env->GetObjectField(object, sCallbacksField))) == + nullptr) { log::error("Failed to allocate Global Ref for Volume control Callbacks"); return; } @@ -888,6 +891,12 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { return result; } + jclass jniVolumeControlNativeInterfaceClass = + env->FindClass("com/android/bluetooth/vc/VolumeControlNativeInterface"); + sCallbacksField = env->GetFieldID(jniVolumeControlNativeInterfaceClass, "mNativeCallback", + "Lcom/android/bluetooth/vc/VolumeControlNativeCallback;"); + env->DeleteLocalRef(jniVolumeControlNativeInterfaceClass); + const JNIJavaMethod javaMethods[] = { {"onConnectionStateChanged", "(I[B)V", &method_onConnectionStateChanged}, {"onVolumeStateChanged", "(IZI[BZ)V", &method_onVolumeStateChanged}, @@ -904,7 +913,7 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { {"onExtAudioInDescriptionChanged", "(ILjava/lang/String;[B)V", &method_onExtAudioInDescriptionChanged}, }; - GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeInterface", javaMethods); + GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeCallback", javaMethods); return 0; } diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java new file mode 100644 index 00000000000..3fd9db4e319 --- /dev/null +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -0,0 +1,208 @@ +/* + * 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. + */ + +package com.android.bluetooth.vc; + +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED; + +import static java.util.Objects.requireNonNull; + +import android.bluetooth.BluetoothDevice; +import android.util.Log; + +import com.android.bluetooth.btservice.AdapterService; +import com.android.internal.annotations.VisibleForTesting; + +class VolumeControlNativeCallback { + private static final String TAG = VolumeControlNativeCallback.class.getSimpleName(); + + private final AdapterService mAdapterService; + private final VolumeControlService mVolumeControlService; + + VolumeControlNativeCallback( + AdapterService adapterService, VolumeControlService volumeControlService) { + mAdapterService = requireNonNull(adapterService); + mVolumeControlService = requireNonNull(volumeControlService); + } + + private BluetoothDevice getDevice(byte[] address) { + return mAdapterService.getDeviceFromByte(address); + } + + @VisibleForTesting + void onConnectionStateChanged(int state, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED); + event.device = getDevice(address); + event.valueInt1 = state; + + Log.d(TAG, "onConnectionStateChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onVolumeStateChanged( + int volume, boolean mute, int flags, byte[] address, boolean isAutonomous) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED); + event.device = getDevice(address); + event.valueInt1 = -1; + event.valueInt2 = volume; + event.valueInt3 = flags; + event.valueBool1 = mute; + event.valueBool2 = isAutonomous; + + Log.d(TAG, "onVolumeStateChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED); + event.device = null; + event.valueInt1 = groupId; + event.valueInt2 = volume; + event.valueBool1 = mute; + event.valueBool2 = isAutonomous; + + Log.d(TAG, "onGroupVolumeStateChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address) { + VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_DEVICE_AVAILABLE); + event.device = getDevice(address); + event.valueInt1 = numOfExternalOutputs; + event.valueInt2 = numOfExternalInputs; + + Log.d(TAG, "onDeviceAvailable: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalOutputId; + event.valueInt2 = offset; + + Log.d(TAG, "onExtAudioOutVolumeOffsetChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalOutputId; + event.valueInt2 = location; + + Log.d(TAG, "onExtAudioOutLocationChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalOutputId; + event.valueString1 = descr; + + Log.d(TAG, "onExtAudioOutLocationChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioInStateChanged( + int externalInputId, int gainValue, int gainMode, int mute, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalInputId; + event.valueInt2 = gainValue; + event.valueInt3 = gainMode; + event.valueInt4 = mute; + + Log.d(TAG, "onExtAudioInStateChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioInStatusChanged(int externalInputId, int status, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalInputId; + event.valueInt2 = status; + + Log.d(TAG, "onExtAudioInStatusChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioInTypeChanged(int externalInputId, int type, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalInputId; + event.valueInt2 = type; + + Log.d(TAG, "onExtAudioInTypeChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioInDescriptionChanged(int externalInputId, String descr, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalInputId; + event.valueString1 = descr; + + Log.d(TAG, "onExtAudioInDescriptionChanged: " + event); + mVolumeControlService.messageFromNative(event); + } + + @VisibleForTesting + void onExtAudioInGainPropsChanged( + int externalInputId, int unit, int min, int max, byte[] address) { + VolumeControlStackEvent event = + new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); + event.device = getDevice(address); + event.valueInt1 = externalInputId; + event.valueInt2 = unit; + event.valueInt3 = min; + event.valueInt4 = max; + + Log.d(TAG, "onExtAudioInGainPropsChanged: " + event); + mVolumeControlService.messageFromNative(event); + } +} diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java index f7e22828b9c..bbf57437afb 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java @@ -17,145 +17,76 @@ package com.android.bluetooth.vc; -import android.bluetooth.BluetoothAdapter; +import static java.util.Objects.requireNonNull; + import android.bluetooth.BluetoothDevice; -import android.util.Log; import com.android.bluetooth.Utils; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -public class VolumeControlNativeInterface { - private static final String TAG = "VolumeControlNativeInterface"; - private BluetoothAdapter mAdapter; - - @GuardedBy("INSTANCE_LOCK") - private static VolumeControlNativeInterface sInstance; - private static final Object INSTANCE_LOCK = new Object(); +import java.lang.annotation.Native; - private VolumeControlNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.wtf(TAG, "No Bluetooth Adapter Available"); - } - } +public class VolumeControlNativeInterface { + private static final String TAG = VolumeControlNativeInterface.class.getSimpleName(); - /** Get singleton instance. */ - public static VolumeControlNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new VolumeControlNativeInterface(); - } - return sInstance; - } - } + // Value access from native, see com_android_bluetooth_vc.cpp + @Native private final VolumeControlNativeCallback mNativeCallback; - /** Set singleton instance. */ - @VisibleForTesting - public static void setInstance(VolumeControlNativeInterface instance) { - synchronized (INSTANCE_LOCK) { - sInstance = instance; - } + VolumeControlNativeInterface(VolumeControlNativeCallback nativeCallback) { + mNativeCallback = requireNonNull(nativeCallback); } - /** - * Initializes the native interface. - * - *

    priorities to configure. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void init() { + void init() { initNative(); } - /** Cleanup the native interface. */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void cleanup() { + void cleanup() { cleanupNative(); } - /** - * Initiates VolumeControl connection to a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean connectVolumeControl(BluetoothDevice device) { + private byte[] getByteAddress(BluetoothDevice device) { + if (device == null) { + return Utils.getBytesFromAddress("00:00:00:00:00:00"); + } + return Utils.getBytesFromAddress(device.getAddress()); + } + + boolean connectVolumeControl(BluetoothDevice device) { return connectVolumeControlNative(getByteAddress(device)); } - /** - * Disconnects VolumeControl from a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean disconnectVolumeControl(BluetoothDevice device) { + boolean disconnectVolumeControl(BluetoothDevice device) { return disconnectVolumeControlNative(getByteAddress(device)); } - /** Sets the VolumeControl volume */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void setVolume(BluetoothDevice device, int volume) { + void setVolume(BluetoothDevice device, int volume) { setVolumeNative(getByteAddress(device), volume); } - /** Sets the VolumeControl volume for the group */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void setGroupVolume(int groupId, int volume) { + void setGroupVolume(int groupId, int volume) { setGroupVolumeNative(groupId, volume); } - /** Mute the VolumeControl volume */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void mute(BluetoothDevice device) { + void mute(BluetoothDevice device) { muteNative(getByteAddress(device)); } - /** Mute the VolumeControl volume in the group */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void muteGroup(int groupId) { + void muteGroup(int groupId) { muteGroupNative(groupId); } - /** Unmute the VolumeControl volume */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void unmute(BluetoothDevice device) { + void unmute(BluetoothDevice device) { unmuteNative(getByteAddress(device)); } - /** Unmute the VolumeControl volume group */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void unmuteGroup(int groupId) { + void unmuteGroup(int groupId) { unmuteGroupNative(groupId); } - /** - * Gets external audio output volume offset from a remote device. - * - * @param device the remote device - * @param externalOutputId external audio output id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId) { + boolean getExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId) { return getExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId); } - /** - * Sets external audio output volume offset to a remote device. - * - * @param device the remote device - * @param externalOutputId external audio output id - * @param offset requested offset - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setExtAudioOutVolumeOffset( - BluetoothDevice device, int externalOutputId, int offset) { + boolean setExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId, int offset) { if (Utils.isPtsTestMode()) { setVolumeNative(getByteAddress(device), offset); return true; @@ -163,366 +94,58 @@ public class VolumeControlNativeInterface { return setExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId, offset); } - /** - * Gets external audio output location from a remote device. - * - * @param device the remote device - * @param externalOutputId external audio output id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioOutLocation(BluetoothDevice device, int externalOutputId) { + boolean getExtAudioOutLocation(BluetoothDevice device, int externalOutputId) { return getExtAudioOutLocationNative(getByteAddress(device), externalOutputId); } - /** - * Sets external audio volume offset to a remote device. - * - * @param device the remote device - * @param externalOutputId external audio output id - * @param location requested location - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setExtAudioOutLocation( - BluetoothDevice device, int externalOutputId, int location) { + boolean setExtAudioOutLocation(BluetoothDevice device, int externalOutputId, int location) { return setExtAudioOutLocationNative(getByteAddress(device), externalOutputId, location); } - /** - * Gets external audio output description from a remote device. - * - * @param device the remote device - * @param externalOutputId external audio output id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioOutDescription(BluetoothDevice device, int externalOutputId) { + boolean getExtAudioOutDescription(BluetoothDevice device, int externalOutputId) { return getExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId); } - /** - * Sets external audio volume description to a remote device. - * - * @param device the remote device - * @param externalOutputId external audio output id - * @param descr requested description - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setExtAudioOutDescription( - BluetoothDevice device, int externalOutputId, String descr) { + boolean setExtAudioOutDescription(BluetoothDevice device, int externalOutputId, String descr) { return setExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId, descr); } - /** - * Gets external audio input state from a remote device. - * - *

    note: state describes configuration - * - * @param device the remote device - * @param externalInputId external audio input id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioInState(BluetoothDevice device, int externalInputId) { + boolean getExtAudioInState(BluetoothDevice device, int externalInputId) { return getExtAudioInStateNative(getByteAddress(device), externalInputId); } - /** - * Gets external audio input status from a remote device. - * - *

    note: status says if input is active or not. - * - * @param device the remote device - * @param externalInputId external audio input id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioInStatus(BluetoothDevice device, int externalInputId) { + boolean getExtAudioInStatus(BluetoothDevice device, int externalInputId) { return getExtAudioInStatusNative(getByteAddress(device), externalInputId); } - /** - * Gets external audio input type from a remote device. - * - * @param device the remote device - * @param externalInputId external audio input id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioInType(BluetoothDevice device, int externalInputId) { + boolean getExtAudioInType(BluetoothDevice device, int externalInputId) { return getExtAudioInTypeNative(getByteAddress(device), externalInputId); } - /** - * Gets external audio input gain properties from a remote device. - * - * @param device the remote device - * @param externalInputId external audio input id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioInGainProps(BluetoothDevice device, int externalInputId) { + boolean getExtAudioInGainProps(BluetoothDevice device, int externalInputId) { return getExtAudioInGainPropsNative(getByteAddress(device), externalInputId); } - /** - * Gets external audio input description from a remote device. - * - * @param device the remote device - * @param externalInputId external audio input id - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean getExtAudioInDescription(BluetoothDevice device, int externalInputId) { + boolean getExtAudioInDescription(BluetoothDevice device, int externalInputId) { return getExtAudioInDescriptionNative(getByteAddress(device), externalInputId); } - /** - * Sets external audio input description from a remote device. - * - * @param device the remote device - * @param externalInputId external audio input id - * @param descr requested description - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setExtAudioInDescription( - BluetoothDevice device, int externalInputId, String descr) { + boolean setExtAudioInDescription(BluetoothDevice device, int externalInputId, String descr) { return setExtAudioInDescriptionNative(getByteAddress(device), externalInputId, descr); } - /** - * Sets external audio input gain value to a remote device. - * - * @param device the remote device - * @param externalInputId external audio input id - * @param value requested gain value - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setExtAudioInGainValue(BluetoothDevice device, int externalInputId, int value) { + boolean setExtAudioInGainValue(BluetoothDevice device, int externalInputId, int value) { return setExtAudioInGainValueNative(getByteAddress(device), externalInputId, value); } - /** - * Sets external audio input gain mode to a remote device. - * - * @param device the remote device - * @param externalInputId external audio input id - * @param autoMode true when auto mode requested - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setExtAudioInGainMode( - BluetoothDevice device, int externalInputId, boolean autoMode) { + boolean setExtAudioInGainMode(BluetoothDevice device, int externalInputId, boolean autoMode) { return setExtAudioInGainModeNative(getByteAddress(device), externalInputId, autoMode); } - /** - * Sets external audio input gain mode to a remote device. - * - * @param device the remote device - * @param externalInputId external audio input id - * @param mute true when mute requested - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setExtAudioInGainMute( - BluetoothDevice device, int externalInputId, boolean mute) { + boolean setExtAudioInGainMute(BluetoothDevice device, int externalInputId, boolean mute) { return setExtAudioInGainMuteNative(getByteAddress(device), externalInputId, mute); } - private BluetoothDevice getDevice(byte[] address) { - return mAdapter.getRemoteDevice(address); - } - - private byte[] getByteAddress(BluetoothDevice device) { - if (device == null) { - return Utils.getBytesFromAddress("00:00:00:00:00:00"); - } - return Utils.getBytesFromAddress(device.getAddress()); - } - - private void sendMessageToService(VolumeControlStackEvent event) { - VolumeControlService service = VolumeControlService.getVolumeControlService(); - if (service != null) { - service.messageFromNative(event); - } else { - Log.e(TAG, "Event ignored, service not available: " + event); - } - } - - // Callbacks from the native stack back into the Java framework. - // All callbacks are routed via the Service which will disambiguate which - // state machine the message should be routed to. - @VisibleForTesting - void onConnectionStateChanged(int state, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = state; - - Log.d(TAG, "onConnectionStateChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onVolumeStateChanged( - int volume, boolean mute, int flags, byte[] address, boolean isAutonomous) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = -1; - event.valueInt2 = volume; - event.valueInt3 = flags; - event.valueBool1 = mute; - event.valueBool2 = isAutonomous; - - Log.d(TAG, "onVolumeStateChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); - event.device = null; - event.valueInt1 = groupId; - event.valueInt2 = volume; - event.valueBool1 = mute; - event.valueBool2 = isAutonomous; - - Log.d(TAG, "onGroupVolumeStateChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent(VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); - event.device = getDevice(address); - event.valueInt1 = numOfExternalOutputs; - event.valueInt2 = numOfExternalInputs; - - Log.d(TAG, "onDeviceAvailable: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalOutputId; - event.valueInt2 = offset; - - Log.d(TAG, "onExtAudioOutVolumeOffsetChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalOutputId; - event.valueInt2 = location; - - Log.d(TAG, "onExtAudioOutLocationChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalOutputId; - event.valueString1 = descr; - - Log.d(TAG, "onExtAudioOutLocationChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioInStateChanged( - int externalInputId, int gainValue, int gainMode, int mute, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = gainValue; - event.valueInt3 = gainMode; - event.valueInt4 = mute; - - Log.d(TAG, "onExtAudioInStateChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioInStatusChanged(int externalInputId, int status, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = status; - - Log.d(TAG, "onExtAudioInStatusChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioInTypeChanged(int externalInputId, int type, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = type; - - Log.d(TAG, "onExtAudioInTypeChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioInDescriptionChanged(int externalInputId, String descr, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueString1 = descr; - - Log.d(TAG, "onExtAudioInDescriptionChanged: " + event); - sendMessageToService(event); - } - - @VisibleForTesting - void onExtAudioInGainPropsChanged( - int externalInputId, int unit, int min, int max, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent( - VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = unit; - event.valueInt3 = min; - event.valueInt4 = max; - - Log.d(TAG, "onExtAudioInGainPropsChanged: " + event); - sendMessageToService(event); - } - // Native methods that call into the JNI interface private native void initNative(); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index a54142899ad..520d421c534 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -29,6 +29,7 @@ import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; import static java.util.Objects.requireNonNull; +import static java.util.Objects.requireNonNullElseGet; import android.annotation.RequiresPermission; import android.bluetooth.BluetoothDevice; @@ -114,7 +115,7 @@ public class VolumeControlService extends ProfileService { @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); public VolumeControlService(AdapterService adapterService) { - this(adapterService, null, VolumeControlNativeInterface.getInstance()); + this(adapterService, null, null); } @VisibleForTesting @@ -125,7 +126,12 @@ public class VolumeControlService extends ProfileService { super(requireNonNull(adapterService)); mAdapterService = adapterService; mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); - mNativeInterface = requireNonNull(nativeInterface); + mNativeInterface = + requireNonNullElseGet( + nativeInterface, + () -> + new VolumeControlNativeInterface( + new VolumeControlNativeCallback(adapterService, this))); mAudioManager = requireNonNull(getSystemService(AudioManager.class)); if (looper == null) { mHandler = new Handler(requireNonNull(Looper.getMainLooper())); @@ -1135,6 +1141,10 @@ public class VolumeControlService extends ProfileService { } void messageFromNative(VolumeControlStackEvent stackEvent) { + if (!isAvailable()) { + Log.e(TAG, "Event ignored, service not available: " + stackEvent); + return; + } Log.d(TAG, "messageFromNative: " + stackEvent); if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java index 1f9540fae21..7372288fac7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java @@ -45,7 +45,6 @@ import com.android.bluetooth.hid.HidDeviceNativeInterface; import com.android.bluetooth.hid.HidHostNativeInterface; import com.android.bluetooth.le_audio.LeAudioNativeInterface; import com.android.bluetooth.pan.PanNativeInterface; -import com.android.bluetooth.vc.VolumeControlNativeInterface; import org.junit.After; import org.junit.Assert; @@ -94,7 +93,6 @@ public class ProfileServiceTest { @Mock private PanNativeInterface mPanNativeInterface; @Mock private CsipSetCoordinatorNativeInterface mCsipSetCoordinatorInterface; @Mock private LeAudioNativeInterface mLeAudioInterface; - @Mock private VolumeControlNativeInterface mVolumeControlInterface; private void setProfileState(int profile, int state) { FutureTask task = @@ -157,6 +155,7 @@ public class ProfileServiceTest { .filter( profile -> profile != BluetoothProfile.HAP_CLIENT + && profile != BluetoothProfile.VOLUME_CONTROL && profile != BluetoothProfile.GATT) .toArray(); TestUtils.setAdapterService(mAdapterService); @@ -175,7 +174,6 @@ public class ProfileServiceTest { PanNativeInterface.setInstance(mPanNativeInterface); CsipSetCoordinatorNativeInterface.setInstance(mCsipSetCoordinatorInterface); LeAudioNativeInterface.setInstance(mLeAudioInterface); - VolumeControlNativeInterface.setInstance(mVolumeControlInterface); } @After @@ -196,7 +194,6 @@ public class ProfileServiceTest { PanNativeInterface.setInstance(null); CsipSetCoordinatorNativeInterface.setInstance(null); LeAudioNativeInterface.setInstance(null); - VolumeControlNativeInterface.setInstance(null); } /** diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java new file mode 100644 index 00000000000..726358022a0 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -0,0 +1,222 @@ +/* + * 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. + */ + +package com.android.bluetooth.vc; + +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; +import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED; + +import static org.mockito.Mockito.verify; + +import android.bluetooth.BluetoothProfile; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.bluetooth.btservice.AdapterService; + +import com.google.common.truth.Expect; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@RunWith(AndroidJUnit4.class) +public class VolumeControlNativeCallbackTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Rule public Expect expect = Expect.create(); + + @Mock private AdapterService mAdapterService; + @Mock private VolumeControlService mService; + @Captor private ArgumentCaptor mEvent; + + private VolumeControlNativeCallback mNativeCallback; + + @Before + public void setUp() throws Exception { + mNativeCallback = new VolumeControlNativeCallback(mAdapterService, mService); + } + + @Test + public void onConnectionStateChanged() { + int state = BluetoothProfile.STATE_CONNECTED; + + mNativeCallback.onConnectionStateChanged(state, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_CONNECTION_STATE_CHANGED); + expect.that(event.valueInt1).isEqualTo(state); + } + + @Test + public void onVolumeStateChanged() { + int volume = 3; + boolean mute = false; + int flags = 1; + boolean isAutonomous = false; + + mNativeCallback.onVolumeStateChanged(volume, mute, flags, null, isAutonomous); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_VOLUME_STATE_CHANGED); + } + + @Test + public void onGroupVolumeStateChanged() { + int volume = 3; + boolean mute = false; + int groupId = 1; + boolean isAutonomous = false; + + mNativeCallback.onGroupVolumeStateChanged(volume, mute, groupId, isAutonomous); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_VOLUME_STATE_CHANGED); + expect.that(event.valueInt1).isEqualTo(groupId); + expect.that(event.valueInt2).isEqualTo(volume); + expect.that(event.valueBool1).isEqualTo(mute); + expect.that(event.valueBool2).isEqualTo(isAutonomous); + } + + @Test + public void onDeviceAvailable() { + int numOfExternalOutputs = 3; + int numOfExternalInputs = 0; + + mNativeCallback.onDeviceAvailable(numOfExternalOutputs, numOfExternalInputs, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_DEVICE_AVAILABLE); + } + + @Test + public void onExtAudioOutVolumeOffsetChanged() { + int externalOutputId = 2; + int offset = 0; + + mNativeCallback.onExtAudioOutVolumeOffsetChanged(externalOutputId, offset, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED); + } + + @Test + public void onExtAudioOutLocationChanged() { + int externalOutputId = 2; + int location = 100; + + mNativeCallback.onExtAudioOutLocationChanged(externalOutputId, location, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED); + } + + @Test + public void onExtAudioOutDescriptionChanged() { + int externalOutputId = 2; + String descr = "test-descr"; + + mNativeCallback.onExtAudioOutDescriptionChanged(externalOutputId, descr, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED); + } + + @Test + public void onExtAudioInStateChanged() { + int externalInputId = 2; + int gainValue = 1; + int gainMode = 0; + int mute = 0; + + mNativeCallback.onExtAudioInStateChanged(externalInputId, gainValue, gainMode, mute, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); + } + + @Test + public void onExtAudioInStatusChanged() { + int externalInputId = 2; + int status = 1; + + mNativeCallback.onExtAudioInStatusChanged(externalInputId, status, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); + } + + @Test + public void onExtAudioInTypeChanged() { + int externalInputId = 2; + int type = 1; + + mNativeCallback.onExtAudioInTypeChanged(externalInputId, type, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); + } + + @Test + public void onExtAudioInDescriptionChanged() { + int externalInputId = 2; + String descr = "microphone"; + + mNativeCallback.onExtAudioInDescriptionChanged(externalInputId, descr, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); + } + + @Test + public void onExtAudioInGainPropsChanged() { + int externalInputId = 2; + int unit = 1; + int min = 0; + int max = 100; + + mNativeCallback.onExtAudioInGainPropsChanged(externalInputId, unit, min, max, null); + verify(mService).messageFromNative(mEvent.capture()); + VolumeControlStackEvent event = mEvent.getValue(); + + expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); + } +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java deleted file mode 100644 index de7b405c2f1..00000000000 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 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.vc; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.bluetooth.BluetoothProfile; - -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.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -@RunWith(AndroidJUnit4.class) -public class VolumeControlNativeInterfaceTest { - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock private VolumeControlService mService; - - private VolumeControlNativeInterface mNativeInterface; - - @Before - public void setUp() throws Exception { - when(mService.isAvailable()).thenReturn(true); - VolumeControlService.setVolumeControlService(mService); - mNativeInterface = VolumeControlNativeInterface.getInstance(); - } - - @After - public void tearDown() { - VolumeControlService.setVolumeControlService(null); - } - - @Test - public void onConnectionStateChanged() { - int state = BluetoothProfile.STATE_CONNECTED; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onConnectionStateChanged(state, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - } - - @Test - public void onVolumeStateChanged() { - int volume = 3; - boolean mute = false; - int flags = 1; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - boolean isAutonomous = false; - - mNativeInterface.onVolumeStateChanged(volume, mute, flags, address, isAutonomous); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); - } - - @Test - public void onGroupVolumeStateChanged() { - int volume = 3; - boolean mute = false; - int groupId = 1; - boolean isAutonomous = false; - - mNativeInterface.onGroupVolumeStateChanged(volume, mute, groupId, isAutonomous); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); - assertThat(event.getValue().valueInt1).isEqualTo(groupId); - } - - @Test - public void onDeviceAvailable() { - int numOfExternalOutputs = 3; - int numOfExternalInputs = 0; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onDeviceAvailable(numOfExternalOutputs, numOfExternalInputs, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); - } - - @Test - public void onExtAudioOutVolumeOffsetChanged() { - int externalOutputId = 2; - int offset = 0; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioOutVolumeOffsetChanged(externalOutputId, offset, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED); - } - - @Test - public void onExtAudioOutLocationChanged() { - int externalOutputId = 2; - int location = 100; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioOutLocationChanged(externalOutputId, location, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED); - } - - @Test - public void onExtAudioOutDescriptionChanged() { - int externalOutputId = 2; - String descr = "test-descr"; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioOutDescriptionChanged(externalOutputId, descr, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED); - } - - @Test - public void onExtAudioInStateChanged() { - int externalInputId = 2; - int gainValue = 1; - int gainMode = 0; - int mute = 0; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioInStateChanged( - externalInputId, gainValue, gainMode, mute, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); - } - - @Test - public void onExtAudioInStatusChanged() { - int externalInputId = 2; - int status = 1; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioInStatusChanged(externalInputId, status, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); - } - - @Test - public void onExtAudioInTypeChanged() { - int externalInputId = 2; - int type = 1; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioInTypeChanged(externalInputId, type, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); - } - - @Test - public void onExtAudioInDescriptionChanged() { - int externalInputId = 2; - String descr = "microphone"; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioInDescriptionChanged(externalInputId, descr, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); - } - - @Test - public void onExtAudioInGainPropsChanged() { - int externalInputId = 2; - int unit = 1; - int min = 0; - int max = 100; - byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - - mNativeInterface.onExtAudioInGainPropsChanged(externalInputId, unit, min, max, address); - - ArgumentCaptor event = - ArgumentCaptor.forClass(VolumeControlStackEvent.class); - verify(mService).messageFromNative(event.capture()); - assertThat(event.getValue().type) - .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); - } -} -- GitLab From 48410cf0bde13f5859cc878f555c155672b373ba Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 16:18:34 -0700 Subject: [PATCH 563/875] AICS: onExtAudioInDescriptionChanged: skip serialize Bug: 361263965 Test: atest vc_test Flag: com.android.bluetooth.flags.leaudio_add_aics_support Change-Id: I9708db6275710b7f322f62cae8c1c4d079caa1ad --- .../bluetooth/vc/VolumeControlNativeCallback.java | 12 ++---------- .../android/bluetooth/vc/VolumeControlService.java | 11 ++--------- .../bluetooth/vc/VolumeControlStackEvent.java | 5 ----- .../vc/VolumeControlNativeCallbackTest.java | 10 +++------- 4 files changed, 7 insertions(+), 31 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java index 58ceee3b6b2..07433a66ee3 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -18,7 +18,6 @@ package com.android.bluetooth.vc; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; @@ -171,15 +170,8 @@ class VolumeControlNativeCallback { } @VisibleForTesting - void onExtAudioInDescriptionChanged(int externalInputId, String descr, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueString1 = descr; - - Log.d(TAG, "onExtAudioInDescriptionChanged: " + event); - mVolumeControlService.messageFromNative(event); + void onExtAudioInDescriptionChanged(int id, String descr, byte[] address) { + sendMessageToService(s -> s.onExtAudioInDescriptionChanged(getDevice(address), id, descr)); } @VisibleForTesting diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 81465cc51d8..805397d7c25 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -1097,10 +1097,9 @@ public class VolumeControlService extends ProfileService { input.setType(id, type); } - void handleDeviceExtInputDescriptionChanged( - BluetoothDevice device, int id, String description) { + void onExtAudioInDescriptionChanged(BluetoothDevice device, int id, String description) { String logInfo = - "handleDeviceExtInputDescriptionChanged(" + "onExtAudioInDescriptionChanged(" + ("device:" + device) + (", id" + id) + (", description" + description) @@ -1184,12 +1183,6 @@ public class VolumeControlService extends ProfileService { return; } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED) { - handleDeviceExtInputDescriptionChanged( - device, stackEvent.valueInt1, stackEvent.valueString1); - return; - } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED) { handleDeviceExtInputGainPropsChanged( device, diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index 83a6941bb3e..3e5c708ba75 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -29,7 +29,6 @@ public class VolumeControlStackEvent { public static final int EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED = 4; public static final int EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED = 5; public static final int EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED = 6; - public static final int EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED = 10; public static final int EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED = 11; public int type; @@ -81,8 +80,6 @@ public class VolumeControlStackEvent { return "EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED"; case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED"; - case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: - return "EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED"; case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: return "EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED"; default: @@ -102,7 +99,6 @@ public class VolumeControlStackEvent { case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED: case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "{ext output id:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: return "{ext input id:" + value + "}"; default: @@ -168,7 +164,6 @@ public class VolumeControlStackEvent { private static String eventTypeString1ToString(int type, String value) { switch (type) { case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: - case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED: return "{description:" + value + "}"; default: break; diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java index f9ef9eb843c..49e097d7eb0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -18,7 +18,6 @@ package com.android.bluetooth.vc; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; @@ -190,14 +189,11 @@ public class VolumeControlNativeCallbackTest { @Test public void onExtAudioInDescriptionChanged() { - int externalInputId = 2; + int id = 2; String descr = "microphone"; - mNativeCallback.onExtAudioInDescriptionChanged(externalInputId, descr, null); - verify(mService).messageFromNative(mEvent.capture()); - VolumeControlStackEvent event = mEvent.getValue(); - - expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); + mNativeCallback.onExtAudioInDescriptionChanged(id, descr, null); + verify(mService).onExtAudioInDescriptionChanged(any(), eq(id), eq(descr)); } @Test -- GitLab From 5c4b8b1bef6ef5f497bce323e43d75796dab2a8f Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 14:50:30 -0700 Subject: [PATCH 564/875] AICS: spec rename gainValue -> gainSetting Test: m . Flag: com.android.bluetooth.flags.leaudio_add_aics_support Bug: 361263965 Change-Id: Icaae7322f0e21ec009f4c4a98b93cc59c6aef7dd --- android/app/jni/com_android_bluetooth_vc.cpp | 17 +++++++++-------- .../vc/VolumeControlInputDescriptor.java | 19 ++++++++++--------- .../vc/VolumeControlNativeCallback.java | 4 ++-- .../vc/VolumeControlNativeInterface.java | 8 ++++---- .../bluetooth/vc/VolumeControlService.java | 10 +++++----- .../vc/VolumeControlInputDescriptorTest.java | 8 ++++---- .../vc/VolumeControlNativeCallbackTest.java | 4 ++-- system/bta/include/bta_vc_api.h | 4 ++-- system/bta/vc/types.h | 2 +- system/bta/vc/vc.cc | 16 ++++++++-------- system/bta/vc/vc_test.cc | 14 +++++++------- system/btif/src/btif_vc.cc | 14 +++++++------- system/gd/rust/topshim/vc/vc_shim.cc | 9 +++++---- system/include/hardware/bt_vc.h | 6 +++--- 14 files changed, 69 insertions(+), 66 deletions(-) diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp index 166d212939e..e7cf0ab0807 100644 --- a/android/app/jni/com_android_bluetooth_vc.cpp +++ b/android/app/jni/com_android_bluetooth_vc.cpp @@ -223,8 +223,8 @@ public: (jint)ext_output_id, description, addr.get()); } - void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode, Mute mute) override { + void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, + int8_t gain_setting, Mute mute, uint8_t gain_mode) override { log::info(""); std::shared_lock lock(callbacks_mutex); @@ -243,7 +243,7 @@ public: sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), reinterpret_cast(&bd_addr)); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInStateChanged, (jint)ext_input_id, - (jint)gain_val, (jint)gain_mode, (jint)mute, addr.get()); + (jint)gain_setting, (jint)mute, (jint)gain_mode, addr.get()); } void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id, @@ -782,8 +782,9 @@ static jboolean setExtAudioInDescriptionNative(JNIEnv* env, jobject /* object */ return JNI_TRUE; } -static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, jbyteArray address, - jint ext_input_id, jint gain_val) { +static jboolean setExtAudioInGainSettingNative(JNIEnv* env, jobject /* object */, + jbyteArray address, jint ext_input_id, + jint gain_setting) { log::info(""); std::shared_lock lock(interface_mutex); if (!sVolumeControlInterface) { @@ -797,7 +798,7 @@ static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, } RawAddress* tmpraw = reinterpret_cast(addr); - sVolumeControlInterface->SetExtAudioInGainValue(*tmpraw, ext_input_id, gain_val); + sVolumeControlInterface->SetExtAudioInGainSetting(*tmpraw, ext_input_id, gain_setting); env->ReleaseByteArrayElements(address, addr, 0); return JNI_TRUE; } @@ -878,8 +879,8 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { reinterpret_cast(getExtAudioInDescriptionNative)}, {"setExtAudioInDescriptionNative", "([BILjava/lang/String;)Z", reinterpret_cast(setExtAudioInDescriptionNative)}, - {"setExtAudioInGainValueNative", "([BII)Z", - reinterpret_cast(setExtAudioInGainValueNative)}, + {"setExtAudioInGainSettingNative", "([BII)Z", + reinterpret_cast(setExtAudioInGainSettingNative)}, {"setExtAudioInGainModeNative", "([BIZ)Z", reinterpret_cast(setExtAudioInGainModeNative)}, {"setExtAudioInGainMuteNative", "([BIZ)Z", diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java index 5055ee43a4c..4e81095a313 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java @@ -43,14 +43,14 @@ class VolumeControlInputDescriptor { int mType = AudioInputType.UNSPECIFIED; - int mGainValue = 0; + int mGainSetting = 0; int mGainMode = GainMode.MANUAL_ONLY; int mMute = Mute.DISABLED; /* See AICS 1.0 - * The Gain_Setting (mGainValue) field is a signed value for which a single increment or + * The Gain_Setting (mGainSetting) field is a signed value for which a single increment or * decrement should result in a corresponding increase or decrease of the input amplitude by * the value of the Gain_Setting_Units (mGainSettingsUnits) field of the Gain Setting * Properties characteristic value. @@ -105,9 +105,9 @@ class VolumeControlInputDescriptor { return mVolumeInputs[id].mType; } - int getGain(int id) { + int getGainSetting(int id) { if (!isValidId(id)) return 0; - return mVolumeInputs[id].mGainValue; + return mVolumeInputs[id].mGainSetting; } int getMute(int id) { @@ -123,17 +123,18 @@ class VolumeControlInputDescriptor { mVolumeInputs[id].mGainSettingsMaxSetting = gainMax; } - void setState(int id, int gainValue, int gainMode, int mute) { + void setState(int id, int gainSetting, int mute, int gainMode) { if (!isValidId(id)) return; Descriptor desc = mVolumeInputs[id]; - if (gainValue > desc.mGainSettingsMaxSetting || gainValue < desc.mGainSettingsMinSetting) { - Log.e(TAG, "Request fail. Illegal gainValue argument: " + gainValue); + if (gainSetting > desc.mGainSettingsMaxSetting + || gainSetting < desc.mGainSettingsMinSetting) { + Log.e(TAG, "Request fail. Illegal gainSetting argument: " + gainSetting); return; } - desc.mGainValue = gainValue; + desc.mGainSetting = gainSetting; desc.mGainMode = gainMode; desc.mMute = mute; } @@ -145,7 +146,7 @@ class VolumeControlInputDescriptor { ProfileService.println(sb, " description: " + desc.mDescription); ProfileService.println(sb, " type: " + desc.mType); ProfileService.println(sb, " status: " + desc.mStatus); - ProfileService.println(sb, " gainValue: " + desc.mGainValue); + ProfileService.println(sb, " gainSetting: " + desc.mGainSetting); ProfileService.println(sb, " gainMode: " + desc.mGainMode); ProfileService.println(sb, " mute: " + desc.mMute); ProfileService.println(sb, " units:" + desc.mGainSettingsUnits); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java index 3fd9db4e319..8b6202a5bc9 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -142,12 +142,12 @@ class VolumeControlNativeCallback { @VisibleForTesting void onExtAudioInStateChanged( - int externalInputId, int gainValue, int gainMode, int mute, byte[] address) { + int externalInputId, int gainSetting, int mute, int gainMode, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; - event.valueInt2 = gainValue; + event.valueInt2 = gainSetting; event.valueInt3 = gainMode; event.valueInt4 = mute; diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java index bbf57437afb..95db676ae01 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java @@ -134,8 +134,8 @@ public class VolumeControlNativeInterface { return setExtAudioInDescriptionNative(getByteAddress(device), externalInputId, descr); } - boolean setExtAudioInGainValue(BluetoothDevice device, int externalInputId, int value) { - return setExtAudioInGainValueNative(getByteAddress(device), externalInputId, value); + boolean setExtAudioInGainSetting(BluetoothDevice device, int externalInputId, int gainSetting) { + return setExtAudioInGainSettingNative(getByteAddress(device), externalInputId, gainSetting); } boolean setExtAudioInGainMode(BluetoothDevice device, int externalInputId, boolean autoMode) { @@ -196,8 +196,8 @@ public class VolumeControlNativeInterface { private native boolean setExtAudioInDescriptionNative( byte[] address, int externalInputId, String descr); - private native boolean setExtAudioInGainValueNative( - byte[] address, int externalInputId, int gainValue); + private native boolean setExtAudioInGainSettingNative( + byte[] address, int externalInputId, int gainSetting); private native boolean setExtAudioInGainModeNative( byte[] address, int externalInputId, boolean modeAuto); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 520d421c534..b267343abe5 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -1031,12 +1031,12 @@ public class VolumeControlService extends ProfileService { } void handleDeviceExtInputStateChanged( - BluetoothDevice device, int id, int gainValue, int gainMode, int mute) { + BluetoothDevice device, int id, int gainSetting, int mute, int gainMode) { String logInfo = "handleDeviceExtInputStateChanged(" + ("device:" + device) + (", id" + id) - + (" gainValue: " + gainValue) + + (" gainSetting: " + gainSetting) + (" gainMode: " + gainMode) + (" mute: " + mute) + ")"; @@ -1048,7 +1048,7 @@ public class VolumeControlService extends ProfileService { } Log.d(TAG, logInfo); - input.setState(id, gainValue, gainMode, mute); + input.setState(id, gainSetting, mute, gainMode); } void handleDeviceExtInputStatusChanged(BluetoothDevice device, int id, int status) { @@ -1189,8 +1189,8 @@ public class VolumeControlService extends ProfileService { device, stackEvent.valueInt1, stackEvent.valueInt2, - stackEvent.valueInt3, - stackEvent.valueInt4); + stackEvent.valueInt4, + stackEvent.valueInt3); return; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java index 48487d6efc0..0811f4e2e0e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java @@ -116,7 +116,7 @@ public class VolumeControlInputDescriptorTest { int mute = Mute.NOT_MUTED; mDescriptor.setState(VALID_ID, newGainMode, newGainMode, mute); - assertThat(mDescriptor.getGain(VALID_ID)).isNotEqualTo(newGainValue); + assertThat(mDescriptor.getGainSetting(VALID_ID)).isNotEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); assertThat(mDescriptor.getMute(VALID_ID)).isNotEqualTo(mute); } @@ -131,9 +131,9 @@ public class VolumeControlInputDescriptorTest { int newGainValue = 42; int newGainMode = 42; int mute = Mute.MUTED; - mDescriptor.setState(VALID_ID, newGainMode, newGainMode, mute); + mDescriptor.setState(VALID_ID, newGainMode, mute, newGainMode); - assertThat(mDescriptor.getGain(VALID_ID)).isEqualTo(newGainValue); + assertThat(mDescriptor.getGainSetting(VALID_ID)).isEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); assertThat(mDescriptor.getMute(VALID_ID)).isEqualTo(mute); } @@ -151,7 +151,7 @@ public class VolumeControlInputDescriptorTest { int mute = Mute.MUTED; mDescriptor.setState(INVALID_ID, newGainMode, newGainMode, mute); - assertThat(mDescriptor.getGain(INVALID_ID)).isNotEqualTo(newGainValue); + assertThat(mDescriptor.getGainSetting(INVALID_ID)).isNotEqualTo(newGainValue); // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode); assertThat(mDescriptor.getMute(INVALID_ID)).isEqualTo(Mute.DISABLED); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java index 726358022a0..1a73e74dec2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -159,11 +159,11 @@ public class VolumeControlNativeCallbackTest { @Test public void onExtAudioInStateChanged() { int externalInputId = 2; - int gainValue = 1; + int gainSetting = 1; int gainMode = 0; int mute = 0; - mNativeCallback.onExtAudioInStateChanged(externalInputId, gainValue, gainMode, mute, null); + mNativeCallback.onExtAudioInStateChanged(externalInputId, gainSetting, mute, gainMode, null); verify(mService).messageFromNative(mEvent.capture()); VolumeControlStackEvent event = mEvent.getValue(); diff --git a/system/bta/include/bta_vc_api.h b/system/bta/include/bta_vc_api.h index bba5b418cc6..2eb33c2f591 100644 --- a/system/bta/include/bta_vc_api.h +++ b/system/bta/include/bta_vc_api.h @@ -65,8 +65,8 @@ public: virtual void GetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id) = 0; virtual void SetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id, std::string descr) = 0; - virtual void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id, - int8_t value) = 0; + virtual void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id, + int8_t gain_setting) = 0; /* Set Gain Mode as per AIS */ virtual void SetExtAudioInGainMode(const RawAddress& address, uint8_t ext_input_id, bool auto_mode) = 0; diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h index a0077f03010..65d83550beb 100644 --- a/system/bta/vc/types.h +++ b/system/bta/vc/types.h @@ -138,7 +138,7 @@ struct GainSettings { struct VolumeAudioInput { /* const */ uint8_t id; Mute mute = bluetooth::aics::Mute::DISABLED; - int8_t gain_value = 0; + int8_t gain_setting = 0; VolumeInputStatus status = VolumeInputStatus::Inactive; VolumeInputType type = VolumeInputType::Unspecified; uint8_t change_counter = 0; diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index 9131274e1e1..9c89b9887eb 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -581,7 +581,7 @@ public: } uint8_t* pp = value; - STREAM_TO_INT8(input->gain_value, pp); + STREAM_TO_INT8(input->gain_setting, pp); uint8_t mute; STREAM_TO_UINT8(mute, pp); if (!bluetooth::aics::isValidAudioInputMuteValue(mute)) { @@ -595,17 +595,17 @@ public: bluetooth::log::verbose("{}, data:{}", device->address, base::HexEncode(value, len)); bluetooth::log::info( - "{} id={:#x}gain_value {:#x}, mute: {:#x}, mode: {:#x}, " + "{} id={:#x}gain_setting {:#x}, mute: {:#x}, mode: {:#x}, " "change_counter: {}", - device->address, input->id, input->gain_value, mute, input->mode, + device->address, input->id, input->gain_setting, mute, input->mode, input->change_counter); if (!device->device_ready) { return; } - callbacks_->OnExtAudioInStateChanged(device->address, input->id, input->gain_value, input->mode, - input->mute); + callbacks_->OnExtAudioInStateChanged(device->address, input->id, input->gain_setting, + input->mute, input->mode); } void OnExtAudioInTypeChanged(VolumeControlDevice* device, VolumeAudioInput* input, uint16_t len, @@ -1292,9 +1292,9 @@ public: device->SetExtAudioInDescription(ext_input_id, descr); } - void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id, - int8_t value) override { - std::vector arg({(uint8_t)value}); + void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id, + int8_t gain_setting) override { + std::vector arg({(uint8_t)gain_setting}); ext_audio_in_control_point_helper(address, ext_input_id, kVolumeInputControlPointOpcodeSetGain, &arg); } diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index aac4736460f..8b69fb3c864 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -105,8 +105,8 @@ public: MOCK_METHOD((void), OnExtAudioOutDescriptionChanged, (const RawAddress& address, uint8_t ext_output_id, std::string descr), (override)); MOCK_METHOD((void), OnExtAudioInStateChanged, - (const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode_auto, Mute mute), + (const RawAddress& address, uint8_t ext_input_id, int8_t gain_setting, Mute mute, + uint8_t gain_mode_auto), (override)); MOCK_METHOD((void), OnExtAudioInStatusChanged, (const RawAddress& address, uint8_t ext_input_id, VolumeInputStatus status), @@ -1344,13 +1344,13 @@ TEST_F(VolumeControlCallbackTest, audio_input_state_changed__invalid_mute__is_re TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__muted) { std::vector value({0x03, (uint8_t)Mute::MUTED, 0x02, 0x04}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, Mute::MUTED)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, Mute::MUTED, 0x02)); GetNotificationEvent(0x0032, value); } TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__disabled) { std::vector value({0x03, (uint8_t)Mute::DISABLED, 0x02, 0x04}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, 0x02, Mute::DISABLED)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, Mute::DISABLED, 0x02)); GetNotificationEvent(0x0032, value); } @@ -1490,7 +1490,7 @@ TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_state) { VolumeControl::Get()->GetExtAudioInState(test_address, 1); EXPECT_TRUE(cb); std::vector value({0x01, (uint8_t)Mute::NOT_MUTED, 0x02, 0x03}); - EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, Mute::NOT_MUTED)); + EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, Mute::NOT_MUTED, 0x02)); cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data); } @@ -1861,10 +1861,10 @@ TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_description_non_writable VolumeControl::Get()->SetExtAudioInDescription(test_address, 0, descr); } -TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_value) { +TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_setting) { std::vector expected_data({0x01, 0x00, 0x34}); EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, expected_data, GATT_WRITE, _, _)); - VolumeControl::Get()->SetExtAudioInGainValue(test_address, 1, 0x34); + VolumeControl::Get()->SetExtAudioInGainSetting(test_address, 1, 0x34); } TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_mode) { diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc index b564a4aef4a..4adaadbf54e 100644 --- a/system/btif/src/btif_vc.cc +++ b/system/btif/src/btif_vc.cc @@ -104,10 +104,10 @@ class VolumeControlInterfaceImpl : public VolumeControlInterface, public VolumeC } /* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */ - void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode, ::Mute mute) override { + void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, + int8_t gain_setting, ::Mute mute, uint8_t gain_mode) override { do_in_jni_thread(Bind(&VolumeControlCallbacks::OnExtAudioInStateChanged, Unretained(callbacks_), - address, ext_input_id, gain_val, gain_mode, mute)); + address, ext_input_id, gain_setting, mute, gain_mode)); } void OnExtAudioInStatusChanged(const RawAddress& address, uint8_t ext_input_id, @@ -353,8 +353,8 @@ class VolumeControlInterfaceImpl : public VolumeControlInterface, public VolumeC Unretained(VolumeControl::Get()), address, ext_input_id, descr)); } - void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id, - int8_t value) override { + void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id, + int8_t gain_setting) override { if (!initialized || !VolumeControl::IsVolumeControlRunning()) { bluetooth::log::verbose( "call ignored, due to already started cleanup procedure or service " @@ -362,8 +362,8 @@ class VolumeControlInterfaceImpl : public VolumeControlInterface, public VolumeC return; } - do_in_main_thread(Bind(&VolumeControl::SetExtAudioInGainValue, Unretained(VolumeControl::Get()), - address, ext_input_id, value)); + do_in_main_thread(Bind(&VolumeControl::SetExtAudioInGainSetting, + Unretained(VolumeControl::Get()), address, ext_input_id, gain_setting)); } void SetExtAudioInGainMode(const RawAddress& address, uint8_t ext_input_id, diff --git a/system/gd/rust/topshim/vc/vc_shim.cc b/system/gd/rust/topshim/vc/vc_shim.cc index 9baceb01116..da0e055d562 100644 --- a/system/gd/rust/topshim/vc/vc_shim.cc +++ b/system/gd/rust/topshim/vc/vc_shim.cc @@ -136,10 +136,11 @@ public: topshim::rust::internal::ext_audio_out_description_cb(address, ext_output_id, descr); } - void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val, - uint8_t gain_mode_auto, bluetooth::aics::Mute mute) { - log::info("address={}, ext_input_id={}, gain_val={}, gain_mode_auto={}, mute={}", address, - ext_input_id, gain_val, gain_mode_auto, static_cast(mute)); + void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, + int8_t gain_setting, bluetooth::aics::Mute mute, + uint8_t gain_mode_auto) { + log::info("address={}, ext_input_id={}, gain_setting={}, gain_mode_auto={}, mute={}", address, + ext_input_id, gain_setting, gain_mode_auto, static_cast(mute)); log::info("Not implemented"); } diff --git a/system/include/hardware/bt_vc.h b/system/include/hardware/bt_vc.h index a3f4fcc191d..5e258b5953b 100644 --- a/system/include/hardware/bt_vc.h +++ b/system/include/hardware/bt_vc.h @@ -76,7 +76,7 @@ public: /* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */ virtual void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, - int8_t gain_val, uint8_t gain_mode_auto, Mute mute) = 0; + int8_t gain_setting, Mute mute, uint8_t gain_mode_auto) = 0; virtual void OnExtAudioInStatusChanged(const RawAddress& address, uint8_t ext_input_id, VolumeInputStatus status) = 0; @@ -134,8 +134,8 @@ public: virtual void GetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id) = 0; virtual void SetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id, std::string descr) = 0; - virtual void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id, - int8_t value) = 0; + virtual void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id, + int8_t gain_setting) = 0; virtual void SetExtAudioInGainMode(const RawAddress& address, uint8_t ext_input_id, bool automatic) = 0; virtual void SetExtAudioInGainMute(const RawAddress& address, uint8_t ext_input_id, -- GitLab From da8c535b3cb11fde0a16bc02b5e7479cb69c4732 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 28 Oct 2024 16:21:42 -0700 Subject: [PATCH 565/875] AICS: onExtAudioInGainPropsChanged: skip serialize Bug: 361263965 Test: atest vc_test Flag: com.android.bluetooth.flags.leaudio_add_aics_support Change-Id: I77552129bd6f6866e8abfd2c641aeccab0bbfee4 --- .../vc/VolumeControlNativeCallback.java | 16 +++------------- .../bluetooth/vc/VolumeControlService.java | 15 ++------------- .../bluetooth/vc/VolumeControlStackEvent.java | 17 ----------------- .../vc/VolumeControlNativeCallbackTest.java | 10 +++------- 4 files changed, 8 insertions(+), 50 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java index 07433a66ee3..56f4cde6990 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -18,7 +18,6 @@ package com.android.bluetooth.vc; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; @@ -175,17 +174,8 @@ class VolumeControlNativeCallback { } @VisibleForTesting - void onExtAudioInGainPropsChanged( - int externalInputId, int unit, int min, int max, byte[] address) { - VolumeControlStackEvent event = - new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); - event.device = getDevice(address); - event.valueInt1 = externalInputId; - event.valueInt2 = unit; - event.valueInt3 = min; - event.valueInt4 = max; - - Log.d(TAG, "onExtAudioInGainPropsChanged: " + event); - mVolumeControlService.messageFromNative(event); + void onExtAudioInGainPropsChanged(int id, int unit, int min, int max, byte[] address) { + sendMessageToService( + s -> s.onExtAudioInGainPropsChanged(getDevice(address), id, unit, min, max)); } } diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 805397d7c25..23c287bd2d1 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -1120,10 +1120,9 @@ public class VolumeControlService extends ProfileService { input.setDescription(id, description); } - void handleDeviceExtInputGainPropsChanged( - BluetoothDevice device, int id, int unit, int min, int max) { + void onExtAudioInGainPropsChanged(BluetoothDevice device, int id, int unit, int min, int max) { String logInfo = - "handleDeviceExtInputGainPropsChanged(" + "onExtAudioInGainPropsChanged(" + ("device:" + device) + (", id" + id) + (" unit: " + unit + " min" + min + " max:" + max) @@ -1183,16 +1182,6 @@ public class VolumeControlService extends ProfileService { return; } - if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED) { - handleDeviceExtInputGainPropsChanged( - device, - stackEvent.valueInt1, - stackEvent.valueInt2, - stackEvent.valueInt3, - stackEvent.valueInt4); - return; - } - synchronized (mStateMachines) { VolumeControlStateMachine sm = mStateMachines.get(device); if (sm == null) { diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index 3e5c708ba75..b1f28406318 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -29,14 +29,12 @@ public class VolumeControlStackEvent { public static final int EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED = 4; public static final int EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED = 5; public static final int EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED = 6; - public static final int EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED = 11; public int type; public BluetoothDevice device; public int valueInt1; public int valueInt2; public int valueInt3; - public int valueInt4; public boolean valueBool1; public boolean valueBool2; public String valueString1; @@ -56,7 +54,6 @@ public class VolumeControlStackEvent { result.append(", valueInt1:").append(eventTypeValue1ToString(type, valueInt1)); result.append(", valueInt2:").append(eventTypeValue2ToString(type, valueInt2)); result.append(", valueInt3:").append(eventTypeValue3ToString(type, valueInt3)); - result.append(", valueInt4:").append(eventTypeValue4ToString(type, valueInt4)); result.append(", valueBool1:").append(eventTypeValueBool1ToString(type, valueBool1)); result.append(", valueBool2:").append(eventTypeValueBool2ToString(type, valueBool2)); result.append(", valueString1:").append(eventTypeString1ToString(type, valueString1)); @@ -80,8 +77,6 @@ public class VolumeControlStackEvent { return "EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED"; case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED"; - case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: - return "EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED"; default: return "EVENT_TYPE_UNKNOWN:" + type; } @@ -99,8 +94,6 @@ public class VolumeControlStackEvent { case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED: case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED: return "{ext output id:" + value + "}"; - case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: - return "{ext input id:" + value + "}"; default: break; } @@ -131,16 +124,6 @@ public class VolumeControlStackEvent { return Integer.toString(value); } - private static String eventTypeValue4ToString(int type, int value) { - switch (type) { - case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED: - return "{gain set max:" + value + "}"; - default: - break; - } - return Integer.toString(value); - } - private static String eventTypeValueBool1ToString(int type, boolean value) { switch (type) { case EVENT_TYPE_VOLUME_STATE_CHANGED: diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java index 49e097d7eb0..51b5f571039 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -18,7 +18,6 @@ package com.android.bluetooth.vc; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; -import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; @@ -198,15 +197,12 @@ public class VolumeControlNativeCallbackTest { @Test public void onExtAudioInGainPropsChanged() { - int externalInputId = 2; + int id = 2; int unit = 1; int min = 0; int max = 100; - mNativeCallback.onExtAudioInGainPropsChanged(externalInputId, unit, min, max, null); - verify(mService).messageFromNative(mEvent.capture()); - VolumeControlStackEvent event = mEvent.getValue(); - - expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); + mNativeCallback.onExtAudioInGainPropsChanged(id, unit, min, max, null); + verify(mService).onExtAudioInGainPropsChanged(any(), eq(id), eq(unit), eq(min), eq(max)); } } -- GitLab From 4d2814783a1c4732e1d3224d81a7fb9d18d86254 Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 31 Oct 2024 07:12:37 +0000 Subject: [PATCH 566/875] VolumeControl: Fix canceling opportunistic connect Opportunistic connect is considered a direct connect therefor it needs to be canceled by direct connect cancel. Bug: 373377157 Test: atest bluetooth_vc_test Flag: EXEMPT; Bug fix covered with unit test Change-Id: Ifb4de1a9571ba6b22a8ea915a903c6a0293015cb --- system/bta/vc/devices.h | 6 ++++-- system/bta/vc/vc.cc | 10 ++++------ system/bta/vc/vc_test.cc | 5 +++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/system/bta/vc/devices.h b/system/bta/vc/devices.h index 8c0a5739c43..27a01af658b 100644 --- a/system/bta/vc/devices.h +++ b/system/bta/vc/devices.h @@ -99,10 +99,12 @@ public: stream << " volume: " << +volume << "\n" << " mute: " << +mute << "\n" + << " change_counter: " << +change_counter << "\n" << " flags: " << +flags << "\n" - << " device read: " << device_ready << "\n" + << " device ready: " << device_ready << "\n" << " connecting_actively: " << connecting_actively << "\n" - << " change_counter: " << +change_counter << "\n"; + << " is encrypted: " << IsEncryptionEnabled() << "\n" + << " GATT operations pending: " << handles_pending.size() << "\n"; dprintf(fd, "%s", stream.str().c_str()); audio_offsets.Dump(fd); diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index 9c89b9887eb..29a78095104 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -195,7 +195,7 @@ public: /* Make sure to remove device from background connect. * It will be added back if needed, when device got disconnected */ - BTA_GATTC_CancelOpen(gatt_if_, address, false); + BTA_GATTC_CancelOpen(gatt_if_, address, true); if (device->IsEncryptionEnabled()) { OnEncryptionComplete(address, tBTM_STATUS::BTM_SUCCESS); @@ -810,14 +810,14 @@ public: bluetooth::log::info("{}", address); /* Removes all registrations for connection. */ - BTA_GATTC_CancelOpen(gatt_if_, address, false); + BTA_GATTC_CancelOpen(gatt_if_, address, true); Disconnect(address); volume_control_devices_.Remove(address); } void OnGattDisconnected(tCONN_ID connection_id, tGATT_IF /*client_if*/, RawAddress remote_bda, - tGATT_DISCONN_REASON reason) { + tGATT_DISCONN_REASON /*reason*/) { VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id); if (!device) { bluetooth::log::error("Skipping unknown device disconnect, connection_id={:#x}", @@ -838,9 +838,7 @@ public: bool notify = device->IsReady() || device->connecting_actively; device_cleanup_helper(device, notify); - if (reason != GATT_CONN_TERMINATE_LOCAL_HOST && device->connecting_actively) { - StartOpportunisticConnect(remote_bda); - } + StartOpportunisticConnect(remote_bda); } void RemoveDeviceFromOperationList(const RawAddress& addr) { diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index 8b69fb3c864..ac6e8848a14 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -572,7 +572,7 @@ protected: } void TestRemove(const RawAddress& address, uint16_t conn_id) { - EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, false)); + EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, true)); if (conn_id) { EXPECT_CALL(gatt_interface, Close(conn_id)); } else { @@ -899,7 +899,7 @@ TEST_F(VolumeControlTest, test_reconnect_after_timeout) { // Disconnect not connected device - upper layer times out and needs a // disconnection event to leave the transient Connecting state EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)); - EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, false)).Times(0); + EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, _)).Times(0); TestDisconnect(address, 0); // Above the device was not connected and we got Disconnect request from the @@ -984,6 +984,7 @@ TEST_F(VolumeControlTest, test_disconnected_while_autoconnect) { TestAppRegister(); TestAddFromStorage(test_address); GetConnectedEvent(test_address, 1); + Mock::VerifyAndClearExpectations(&gatt_interface); // autoconnect - don't indicate disconnection EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0); GetDisconnectedEvent(test_address, 1); -- GitLab From f243c3dbd92c59387d03122b753e9bfbe37e7e93 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Fri, 1 Nov 2024 17:20:40 -0700 Subject: [PATCH 567/875] stack/a2dp: Cleanup the definition of a2dp codec IDs Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I23a892189767e1bec4b0f9d3e6ff1e89d7ce362d --- system/audio_hal_interface/a2dp_encoding.cc | 4 +- system/audio_hal_interface/a2dp_encoding.h | 4 +- .../audio_hal_interface/a2dp_encoding_host.cc | 2 +- .../aidl/a2dp/a2dp_encoding_aidl.cc | 2 +- .../aidl/a2dp/a2dp_encoding_aidl.h | 5 +- .../aidl/a2dp/a2dp_provider_info.cc | 10 +-- .../aidl/a2dp/a2dp_provider_info.h | 3 +- .../aidl/a2dp/a2dp_provider_info_unittest.cc | 16 ++-- system/btif/co/bta_av_co.cc | 2 +- system/gd/os/android/metrics.cc | 18 ++--- system/stack/a2dp/a2dp_codec_config.cc | 63 +++++++++++++++- system/stack/a2dp/a2dp_ext.cc | 6 +- system/stack/a2dp/a2dp_vendor.cc | 17 ----- system/stack/a2dp/a2dp_vendor_aptx.cc | 2 +- system/stack/a2dp/a2dp_vendor_aptx_hd.cc | 2 +- .../stack/a2dp/a2dp_vendor_aptx_hd_linux.cc | 2 +- system/stack/a2dp/a2dp_vendor_aptx_linux.cc | 2 +- system/stack/include/a2dp_aac.h | 2 +- system/stack/include/a2dp_codec_api.h | 6 +- system/stack/include/a2dp_constants.h | 74 ++++++++++++++----- system/stack/include/a2dp_sbc.h | 2 +- system/stack/include/a2dp_vendor_ldac.h | 2 +- system/stack/include/a2dp_vendor_opus.h | 2 +- .../mock_audio_hal_interface_a2dp_encoding.cc | 2 +- .../mock_audio_hal_interface_a2dp_encoding.h | 14 ++-- .../test/mock/mock_stack_a2dp_codec_config.cc | 5 +- 26 files changed, 175 insertions(+), 94 deletions(-) diff --git a/system/audio_hal_interface/a2dp_encoding.cc b/system/audio_hal_interface/a2dp_encoding.cc index 1bebeac1ed0..f2fd26eb82c 100644 --- a/system/audio_hal_interface/a2dp_encoding.cc +++ b/system/audio_hal_interface/a2dp_encoding.cc @@ -185,8 +185,8 @@ bool supports_codec(btav_a2dp_codec_index_t codec_index) { } // Return the A2DP capabilities for the selected codec. -bool codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_config) { +bool codec_info(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, + uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) { return (HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::AIDL) ? aidl::a2dp::provider::codec_info(codec_index, codec_id, codec_info, codec_config) : false; diff --git a/system/audio_hal_interface/a2dp_encoding.h b/system/audio_hal_interface/a2dp_encoding.h index d1de4138b20..84e31a82c6b 100644 --- a/system/audio_hal_interface/a2dp_encoding.h +++ b/system/audio_hal_interface/a2dp_encoding.h @@ -124,8 +124,8 @@ bool supports_codec(btav_a2dp_codec_index_t codec_index); // Return the A2DP capabilities for the selected codec. // `codec_info` returns the OTA codec capabilities, `codec_config` // returns the supported capabilities in a generic format. -bool codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_config); +bool codec_info(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, + uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config); struct a2dp_configuration { int remote_seid; diff --git a/system/audio_hal_interface/a2dp_encoding_host.cc b/system/audio_hal_interface/a2dp_encoding_host.cc index 92f4361b781..9bd81495355 100644 --- a/system/audio_hal_interface/a2dp_encoding_host.cc +++ b/system/audio_hal_interface/a2dp_encoding_host.cc @@ -328,7 +328,7 @@ std::optional codec_index_str(btav_a2dp_codec_index_t /*codec_index bool supports_codec(btav_a2dp_codec_index_t /*codec_index*/) { return false; } // Return the A2DP capabilities for the selected codec. -bool codec_info(btav_a2dp_codec_index_t /*codec_index*/, uint64_t* /*codec_id*/, +bool codec_info(btav_a2dp_codec_index_t /*codec_index*/, bluetooth::a2dp::CodecId* /*codec_id*/, uint8_t* /*codec_info*/, btav_a2dp_codec_config_t* /*codec_config*/) { return false; } diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc index e71171113a7..f99fa9ba284 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc @@ -665,7 +665,7 @@ bool provider::supports_codec(btav_a2dp_codec_index_t codec_index) { /*** * Return the A2DP capabilities for the selected codec. ***/ -bool provider::codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, +bool provider::codec_info(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) { return provider_info ? provider_info->CodecCapabilities(codec_index, codec_id, codec_info, codec_config) diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h index f470d5e06a5..0d51f789c0e 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.h @@ -18,6 +18,7 @@ #include +#include "a2dp_constants.h" #include "a2dp_encoding.h" #include "a2dp_sbc_constants.h" #include "common/message_loop_thread.h" @@ -119,8 +120,8 @@ bool supports_codec(btav_a2dp_codec_index_t codec_index); /*** * Return the A2DP capabilities for the selected codec. ***/ -bool codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_config); +bool codec_info(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, + uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config); /*** * Query the codec selection fromt the audio HAL. diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc index 074929290bf..ccd0bf04fe0 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.cc @@ -350,8 +350,8 @@ bool ProviderInfo::BuildCodecCapabilities(CodecId const& codec_id, return false; } -bool ProviderInfo::CodecCapabilities(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, - uint8_t* codec_info, +bool ProviderInfo::CodecCapabilities(btav_a2dp_codec_index_t codec_index, + bluetooth::a2dp::CodecId* codec_id, uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) const { auto it = assigned_codec_indexes.find(codec_index); if (it == assigned_codec_indexes.end()) { @@ -365,13 +365,13 @@ bool ProviderInfo::CodecCapabilities(btav_a2dp_codec_index_t codec_index, uint64 switch (codec->id.getTag()) { case CodecId::a2dp: { auto id = codec->id.get(); - *codec_id = static_cast(id); + *codec_id = static_cast(id); break; } case CodecId::vendor: { auto id = codec->id.get(); - *codec_id = 0xff | (static_cast(id.id) << 8) | - (static_cast(id.codecId) << 24); + *codec_id = static_cast( + bluetooth::a2dp::VendorCodecId(id.id, id.codecId)); break; } default: diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.h b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.h index beabc4b4edd..d2175c360d4 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.h +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info.h @@ -19,6 +19,7 @@ #include #include +#include "a2dp_constants.h" #include "audio_aidl_interfaces.h" #include "include/hardware/bt_av.h" @@ -89,7 +90,7 @@ public: * Return the A2DP capabilities for the selected codec. * Returns true if the codec is supported, false otherwise. ***/ - bool CodecCapabilities(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, + bool CodecCapabilities(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) const; const std::vector source_codecs; diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info_unittest.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info_unittest.cc index f1c4b0cbd1b..b3731e56275 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info_unittest.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_provider_info_unittest.cc @@ -563,11 +563,11 @@ TEST_F(ProviderInfoTest, TestCodecCapabilitiesSbc) { uint8_t result_codec_info[20]; btav_a2dp_codec_config_t result_codec_config; - uint64_t result_codec_id; + bluetooth::a2dp::CodecId result_codec_id; ASSERT_TRUE(provider_info->CodecCapabilities(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, &result_codec_id, result_codec_info, &result_codec_config)); - ASSERT_EQ(result_codec_id, A2DP_CODEC_ID_SBC); + ASSERT_EQ(result_codec_id, bluetooth::a2dp::CodecId::SBC); ASSERT_EQ(std::memcmp(result_codec_info, test_sbc_codec_info.data(), test_sbc_codec_info.size()), 0); ASSERT_TRUE(result_codec_config.channel_mode == @@ -584,11 +584,11 @@ TEST_F(ProviderInfoTest, TestCodecCapabilitiesAac) { uint8_t result_codec_info[20]; btav_a2dp_codec_config_t result_codec_config; - uint64_t result_codec_id; + bluetooth::a2dp::CodecId result_codec_id; ASSERT_TRUE(provider_info->CodecCapabilities(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, &result_codec_id, result_codec_info, &result_codec_config)); - ASSERT_EQ(result_codec_id, A2DP_CODEC_ID_AAC); + ASSERT_EQ(result_codec_id, bluetooth::a2dp::CodecId::AAC); ASSERT_EQ(std::memcmp(result_codec_info, test_aac_codec_info.data(), test_aac_codec_info.size()), 0); ASSERT_TRUE(result_codec_config.channel_mode == @@ -605,11 +605,11 @@ TEST_F(ProviderInfoTest, TestCodecCapabilitiesOpus) { uint8_t result_codec_info[20]; btav_a2dp_codec_config_t result_codec_config; - uint64_t result_codec_id; + bluetooth::a2dp::CodecId result_codec_id; ASSERT_TRUE(provider_info->CodecCapabilities(BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS, &result_codec_id, result_codec_info, &result_codec_config)); - ASSERT_EQ(result_codec_id, A2DP_CODEC_ID_OPUS); + ASSERT_EQ(result_codec_id, bluetooth::a2dp::CodecId::OPUS); ASSERT_EQ( std::memcmp(result_codec_info, test_opus_codec_info.data(), test_opus_codec_info.size()), 0); @@ -627,12 +627,12 @@ TEST_F(ProviderInfoTest, TestCodecCapabilitiesFoobar) { uint8_t result_codec_info[20]; btav_a2dp_codec_config_t result_codec_config; - uint64_t result_codec_id; + bluetooth::a2dp::CodecId result_codec_id; ASSERT_TRUE(provider_info->CodecCapabilities(BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN, &result_codec_id, result_codec_info, &result_codec_config)); - ASSERT_EQ(result_codec_id, static_cast(0x11223344ff)); + ASSERT_EQ(result_codec_id, static_cast(0x11223344ff)); ASSERT_EQ(std::memcmp(result_codec_info, test_foobar_codec_info.data(), test_foobar_codec_info.size()), 0); diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index de0f9066046..8011f3badcd 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -99,7 +99,7 @@ void BtaAvCo::Init(const std::vector& codec_priorities for (auto* codec_config : peer_cache_->peers_[0].GetCodecs()->orderedSourceCodecs()) { auto& codec_info = supported_codecs->emplace_back(); codec_info.codec_type = codec_config->codecIndex(); - codec_info.codec_id = codec_config->codecId(); + codec_info.codec_id = static_cast(codec_config->codecId()); codec_info.codec_name = codec_config->name(); } } diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc index 0a2dbd92b6d..69563654c62 100644 --- a/system/gd/os/android/metrics.cc +++ b/system/gd/os/android/metrics.cc @@ -168,32 +168,32 @@ void LogMetricA2dpSessionMetricsEvent(const hci::Address& /* address */, int64_t 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) { - char const* metric_id = nullptr; - uint64_t codec_id = -1; + char const* metric_id; + a2dp::CodecId codec_id; switch (codec_index) { case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC: metric_id = "bluetooth.value_sbc_codec_usage_over_a2dp"; - codec_id = A2DP_CODEC_ID_SBC; + codec_id = a2dp::CodecId::SBC; break; case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC: metric_id = "bluetooth.value_aac_codec_usage_over_a2dp"; - codec_id = A2DP_CODEC_ID_AAC; + codec_id = a2dp::CodecId::AAC; break; case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX: metric_id = "bluetooth.value_aptx_codec_usage_over_a2dp"; - codec_id = A2DP_CODEC_ID_APTX; + codec_id = a2dp::CodecId::APTX; break; case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: metric_id = "bluetooth.value_aptx_hd_codec_usage_over_a2dp"; - codec_id = A2DP_CODEC_ID_APTX_HD; + codec_id = a2dp::CodecId::APTX_HD; break; case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: metric_id = "bluetooth.value_ldac_codec_usage_over_a2dp"; - codec_id = A2DP_CODEC_ID_LDAC; + codec_id = a2dp::CodecId::LDAC; break; case BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS: metric_id = "bluetooth.value_opus_codec_usage_over_a2dp"; - codec_id = A2DP_CODEC_ID_OPUS; + codec_id = a2dp::CodecId::OPUS; break; default: return; @@ -204,7 +204,7 @@ void LogMetricA2dpSessionMetricsEvent(const hci::Address& /* address */, int64_t int ret = stats_write(A2DP_SESSION_REPORTED, 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_id, is_a2dp_offload); + buffer_underruns_count, static_cast(codec_id), is_a2dp_offload); if (ret < 0) { log::warn("failed to log a2dp_session_reported"); diff --git a/system/stack/a2dp/a2dp_codec_config.cc b/system/stack/a2dp/a2dp_codec_config.cc index 2a59138d7ea..4a39e0c93b0 100644 --- a/system/stack/a2dp/a2dp_codec_config.cc +++ b/system/stack/a2dp/a2dp_codec_config.cc @@ -24,6 +24,7 @@ #include "a2dp_aac.h" #include "a2dp_codec_api.h" +#include "a2dp_constants.h" #include "a2dp_ext.h" #include "a2dp_sbc.h" #include "a2dp_vendor.h" @@ -45,13 +46,50 @@ /* The Media Type offset within the codec info byte array */ #define A2DP_MEDIA_TYPE_OFFSET 1 +namespace bluetooth::a2dp { + +std::optional ParseCodecId(uint8_t const media_codec_capabilities[]) { + uint8_t length_of_service_capability = media_codec_capabilities[0]; + // The Media Codec Capabilities contain the Media Codec Type and + // Media Type on 16-bits. + if (length_of_service_capability < 2) { + return {}; + } + tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(media_codec_capabilities); + switch (codec_type) { + case A2DP_MEDIA_CT_SBC: + return CodecId::SBC; + case A2DP_MEDIA_CT_AAC: + return CodecId::AAC; + case A2DP_MEDIA_CT_NON_A2DP: { + // The Vendor Codec Specific Information Elements contain + // a 32-bit Vendor ID and 16-bit Vendor Specific Codec ID. + if (length_of_service_capability < 8) { + return {}; + } + uint32_t vendor_id = A2DP_VendorCodecGetVendorId(media_codec_capabilities); + uint16_t codec_id = A2DP_VendorCodecGetCodecId(media_codec_capabilities); + // The lower 16 bits of the 32-bit Vendor ID shall contain a valid, + // nonreserved 16-bit Company ID as defined in Bluetooth Assigned Numbers. + // The upper 16 bits of the 32-bit Vendor ID shall be set to zero. + if (vendor_id > UINT16_MAX) { + return {}; + } + return static_cast(VendorCodecId(static_cast(vendor_id), codec_id)); + } + default: + return {}; + } +} + +} // namespace bluetooth::a2dp + +using namespace bluetooth; + // Initializes the codec config. // |codec_config| is the codec config to initialize. // |codec_index| and |codec_priority| are the codec type and priority to use // for the initialization. - -using namespace bluetooth; - static void init_btav_a2dp_codec_config(btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index, btav_a2dp_codec_priority_t codec_priority) { @@ -60,7 +98,7 @@ static void init_btav_a2dp_codec_config(btav_a2dp_codec_config_t* codec_config, codec_config->codec_priority = codec_priority; } -A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, tA2DP_CODEC_ID codec_id, +A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, a2dp::CodecId codec_id, const std::string& name, btav_a2dp_codec_priority_t codec_priority) : codec_index_(codec_index), codec_id_(codec_id), @@ -1572,3 +1610,20 @@ int A2DP_GetEecoderEffectiveFrameSize(const uint8_t* p_codec_info) { const tA2DP_ENCODER_INTERFACE* a2dp_encoder_interface = A2DP_GetEncoderInterface(p_codec_info); return a2dp_encoder_interface ? a2dp_encoder_interface->get_effective_frame_size() : 0; } + +uint32_t A2DP_VendorCodecGetVendorId(const uint8_t* p_codec_info) { + const uint8_t* p = &p_codec_info[A2DP_VENDOR_CODEC_VENDOR_ID_START_IDX]; + + uint32_t vendor_id = (p[0] & 0x000000ff) | ((p[1] << 8) & 0x0000ff00) | + ((p[2] << 16) & 0x00ff0000) | ((p[3] << 24) & 0xff000000); + + return vendor_id; +} + +uint16_t A2DP_VendorCodecGetCodecId(const uint8_t* p_codec_info) { + const uint8_t* p = &p_codec_info[A2DP_VENDOR_CODEC_CODEC_ID_START_IDX]; + + uint16_t codec_id = (p[0] & 0x00ff) | ((p[1] << 8) & 0xff00); + + return codec_id; +} diff --git a/system/stack/a2dp/a2dp_ext.cc b/system/stack/a2dp/a2dp_ext.cc index 865361d6892..fa2ca6f91c5 100644 --- a/system/stack/a2dp/a2dp_ext.cc +++ b/system/stack/a2dp/a2dp_ext.cc @@ -25,11 +25,11 @@ using namespace bluetooth; -static tA2DP_CODEC_ID codec_id(btav_a2dp_codec_index_t codec_index) { - uint64_t id = 0; +static a2dp::CodecId codec_id(btav_a2dp_codec_index_t codec_index) { + bluetooth::a2dp::CodecId id; auto result = ::bluetooth::audio::a2dp::provider::codec_info(codec_index, &id, nullptr, nullptr); log::assert_that(result, "provider::codec_info unexpectdly failed"); - return static_cast(id); + return id; } A2dpCodecConfigExt::A2dpCodecConfigExt(btav_a2dp_codec_index_t codec_index, bool is_source) diff --git a/system/stack/a2dp/a2dp_vendor.cc b/system/stack/a2dp/a2dp_vendor.cc index 2057266d477..b178c3c9003 100644 --- a/system/stack/a2dp/a2dp_vendor.cc +++ b/system/stack/a2dp/a2dp_vendor.cc @@ -132,23 +132,6 @@ tA2DP_STATUS A2DP_IsVendorSinkCodecSupported(const uint8_t* p_codec_info) { return A2DP_NOT_SUPPORTED_CODEC_TYPE; } -uint32_t A2DP_VendorCodecGetVendorId(const uint8_t* p_codec_info) { - const uint8_t* p = &p_codec_info[A2DP_VENDOR_CODEC_VENDOR_ID_START_IDX]; - - uint32_t vendor_id = (p[0] & 0x000000ff) | ((p[1] << 8) & 0x0000ff00) | - ((p[2] << 16) & 0x00ff0000) | ((p[3] << 24) & 0xff000000); - - return vendor_id; -} - -uint16_t A2DP_VendorCodecGetCodecId(const uint8_t* p_codec_info) { - const uint8_t* p = &p_codec_info[A2DP_VENDOR_CODEC_CODEC_ID_START_IDX]; - - uint16_t codec_id = (p[0] & 0x00ff) | ((p[1] << 8) & 0xff00); - - return codec_id; -} - bool A2DP_VendorUsesRtpHeader(bool content_protection_enabled, const uint8_t* p_codec_info) { uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); diff --git a/system/stack/a2dp/a2dp_vendor_aptx.cc b/system/stack/a2dp/a2dp_vendor_aptx.cc index ebb5b50e486..461e0441462 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx.cc @@ -363,7 +363,7 @@ bool A2DP_VendorInitCodecConfigAptx(AvdtpSepConfig* p_cfg) { } A2dpCodecConfigAptx::A2dpCodecConfigAptx(btav_a2dp_codec_priority_t codec_priority) - : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, A2DP_CODEC_ID_APTX, + : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, bluetooth::a2dp::CodecId::APTX, A2DP_VendorCodecIndexStrAptx(), codec_priority) { // Compute the local capability if (a2dp_aptx_source_caps.sampleRate & A2DP_APTX_SAMPLERATE_44100) { diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd.cc index cc599366383..e7dfd57f727 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_hd.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_hd.cc @@ -380,7 +380,7 @@ bool A2DP_VendorInitCodecConfigAptxHd(AvdtpSepConfig* p_cfg) { } A2dpCodecConfigAptxHd::A2dpCodecConfigAptxHd(btav_a2dp_codec_priority_t codec_priority) - : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, A2DP_CODEC_ID_APTX_HD, + : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, bluetooth::a2dp::CodecId::APTX_HD, A2DP_VendorCodecIndexStrAptxHd(), codec_priority) { // Compute the local capability if (a2dp_aptx_hd_source_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) { diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd_linux.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd_linux.cc index a82ea55e412..fd4e0edc638 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_hd_linux.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_hd_linux.cc @@ -91,7 +91,7 @@ const char* A2DP_VendorCodecIndexStrAptxHd(void) { return "AptxHd"; } bool A2DP_VendorInitCodecConfigAptxHd(AvdtpSepConfig* p_cfg) { return false; } A2dpCodecConfigAptxHd::A2dpCodecConfigAptxHd(btav_a2dp_codec_priority_t codec_priority) - : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, A2DP_CODEC_ID_APTX_HD, + : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, bluetooth::a2dp::CodecId::APTX_HD, A2DP_VendorCodecIndexStrAptxHd(), codec_priority) {} A2dpCodecConfigAptxHd::~A2dpCodecConfigAptxHd() {} diff --git a/system/stack/a2dp/a2dp_vendor_aptx_linux.cc b/system/stack/a2dp/a2dp_vendor_aptx_linux.cc index 801b5a4ce7d..c4b63ac323e 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_linux.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_linux.cc @@ -87,7 +87,7 @@ const char* A2DP_VendorCodecIndexStrAptx(void) { return "Aptx"; } bool A2DP_VendorInitCodecConfigAptx(AvdtpSepConfig* p_cfg) { return false; } A2dpCodecConfigAptx::A2dpCodecConfigAptx(btav_a2dp_codec_priority_t codec_priority) - : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, A2DP_CODEC_ID_APTX, + : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, bluetooth::a2dp::CodecId::APTX, A2DP_VendorCodecIndexStrAptx(), codec_priority) {} A2dpCodecConfigAptx::~A2dpCodecConfigAptx() {} diff --git a/system/stack/include/a2dp_aac.h b/system/stack/include/a2dp_aac.h index 357400b6ab8..6b3feb1be39 100644 --- a/system/stack/include/a2dp_aac.h +++ b/system/stack/include/a2dp_aac.h @@ -33,7 +33,7 @@ class A2dpCodecConfigAacBase : public A2dpCodecConfig { protected: A2dpCodecConfigAacBase(btav_a2dp_codec_index_t codec_index, const std::string& name, btav_a2dp_codec_priority_t codec_priority, bool is_source) - : A2dpCodecConfig(codec_index, A2DP_CODEC_ID_AAC, name, codec_priority), + : A2dpCodecConfig(codec_index, bluetooth::a2dp::CodecId::AAC, name, codec_priority), is_source_(is_source) {} tA2DP_STATUS setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability, uint8_t* p_result_codec_config) override; diff --git a/system/stack/include/a2dp_codec_api.h b/system/stack/include/a2dp_codec_api.h index a9a263bbcb0..3c4f3f7c768 100644 --- a/system/stack/include/a2dp_codec_api.h +++ b/system/stack/include/a2dp_codec_api.h @@ -77,7 +77,7 @@ public: // set to 0, if octet 0 is not 0xFF. // - Bits 24-39: Vendor-defined codec ID, // set to 0, if octet 0 is not 0xFF. - tA2DP_CODEC_ID codecId() const { return codec_id_; } + bluetooth::a2dp::CodecId codecId() const { return codec_id_; } // Gets the codec name. const std::string& name() const { return name_; } @@ -200,7 +200,7 @@ protected: // The default codec priority is |codec_priority|. If the value is // |BTAV_A2DP_CODEC_PRIORITY_DEFAULT|, the codec priority is computed // internally. - A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, tA2DP_CODEC_ID codec_id, + A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId codec_id, const std::string& name, btav_a2dp_codec_priority_t codec_priority); // Initializes the codec entry. @@ -243,7 +243,7 @@ protected: std::recursive_mutex codec_mutex_; const btav_a2dp_codec_index_t codec_index_; // The unique codec index - const tA2DP_CODEC_ID codec_id_; // The standardized codec id + const bluetooth::a2dp::CodecId codec_id_; // The standardized codec id const std::string name_; // The codec name btav_a2dp_codec_priority_t codec_priority_; // Codec priority: must be unique btav_a2dp_codec_priority_t default_codec_priority_; diff --git a/system/stack/include/a2dp_constants.h b/system/stack/include/a2dp_constants.h index 3bb957a5e78..55a9b9abd38 100644 --- a/system/stack/include/a2dp_constants.h +++ b/system/stack/include/a2dp_constants.h @@ -20,6 +20,7 @@ #include #include +#include /* Profile supported features */ #define A2DP_SUPF_PLAYER 0x0001 @@ -43,25 +44,64 @@ enum tA2DP_CODEC_TYPE : uint8_t { A2DP_MEDIA_CT_NON_A2DP = 0xff, }; -// Standardized codec identifiers. -// The codec identifier is 40 bits, -// - Bits 0-7: Audio Codec ID, as defined by Assigned Numbers § 6.5.1 Audio Codec ID -// 0x00: SBC -// 0x02: AAC -// 0xFF: Vendor -// - Bits 8-23: Company ID, -// set to 0, if octet 0 is not 0xFF. -// - Bits 24-39: Vendor-defined codec ID, -// set to 0, if octet 0 is not 0xFF. -enum tA2DP_CODEC_ID : uint64_t { - A2DP_CODEC_ID_SBC = 0x0000000000, - A2DP_CODEC_ID_AAC = 0x0000000002, - A2DP_CODEC_ID_APTX = 0x0001004fff, - A2DP_CODEC_ID_APTX_HD = 0x002400d7ff, - A2DP_CODEC_ID_LDAC = 0x00aa012dff, - A2DP_CODEC_ID_OPUS = 0x000100e0ff, +namespace bluetooth::a2dp { + +/// Generate the `CodecId` tag value for a vendor codec identified +/// by the input `company_id` and `codec_id`. +constexpr static uint64_t VendorCodecId(uint16_t company_id, uint16_t codec_id) { + return 0xff | (static_cast(company_id) << 8) | (static_cast(codec_id) << 24); +} + +static constexpr uint16_t kAptxCompanyId = 0x004F; +static constexpr uint16_t kAptxHdCompanyId = 0x00D7; +static constexpr uint16_t kLdacCompanyId = 0x012D; +static constexpr uint16_t kOpusCompanyId = 0x00E0; + +static constexpr uint16_t kAptxCodecId = 0x0001; +static constexpr uint16_t kAptxHdCodecId = 0x0024; +static constexpr uint16_t kLdacCodecId = 0x00AA; +static constexpr uint16_t kOpusCodecId = 0x0001; + +/// Standardized codec identifiers. +/// +/// The codec identifier is 40 bits, +/// - Bits 0-7: Media Codec Type, as defined by Assigned Numbers § 6.5.1 Audio Codec ID +/// 0x00: SBC +/// 0x02: MPEG-AAC +/// 0xFF: Vendor +/// - Bits 8-23: Company ID, +/// set to 0, if octet 0 is not 0xFF. The Company ID is contained +/// within the codec Vendor ID, and specified by +/// Assigned Numbers § 7 Company identifiers. +/// - Bits 24-39: Vendor-defined codec ID, +/// set to 0, if octet 0 is not 0xFF. +/// +/// Values are defined here for codecs that are supported by default. +/// Offloaded codecs may be referenced using this identifier and in this case the +/// identifier is constructed from the Media Codec Capabilities information. +enum class CodecId : uint64_t { + SBC = 0x00, + AAC = 0x02, + APTX = VendorCodecId(kAptxCompanyId, kAptxCodecId), + APTX_HD = VendorCodecId(kAptxHdCompanyId, kAptxHdCodecId), + LDAC = VendorCodecId(kLdacCompanyId, kLdacCodecId), + OPUS = VendorCodecId(kOpusCompanyId, kOpusCodecId), }; +/// Parse the standardized codec identifier from the Media Codec Capabilities. +/// `media_codec_capabilities` must point to a non-null buffer that contains +/// well formed Media Codec Capabilities. +/// +/// Returns an error in one of three cases: +/// - unsupported Media Codec Type +/// - incorrectly formatted Media Codec Capabilities (e.g. truncated +/// Codec Specific Information Elements for non-A2DP codecs) +/// - incorrectly formatted Vendor ID (The upper 16 bits of the 32- +/// bit Vendor ID shall be set to zero) +std::optional ParseCodecId(uint8_t const media_codec_capabilities[]); + +} // namespace bluetooth::a2dp + // Error codes returned in AVDTP reject signalling messages. // The codes are specified from multiple sources as documented in the enum. enum tA2DP_STATUS : uint8_t { diff --git a/system/stack/include/a2dp_sbc.h b/system/stack/include/a2dp_sbc.h index ccb43b9cecc..0f21f3302e5 100644 --- a/system/stack/include/a2dp_sbc.h +++ b/system/stack/include/a2dp_sbc.h @@ -34,7 +34,7 @@ class A2dpCodecConfigSbcBase : public A2dpCodecConfig { protected: A2dpCodecConfigSbcBase(btav_a2dp_codec_index_t codec_index, const std::string& name, btav_a2dp_codec_priority_t codec_priority, bool is_source) - : A2dpCodecConfig(codec_index, A2DP_CODEC_ID_SBC, name, codec_priority), + : A2dpCodecConfig(codec_index, bluetooth::a2dp::CodecId::SBC, name, codec_priority), is_source_(is_source) {} tA2DP_STATUS setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability, uint8_t* p_result_codec_config) override; diff --git a/system/stack/include/a2dp_vendor_ldac.h b/system/stack/include/a2dp_vendor_ldac.h index 510aa6e0db8..ec755c3b726 100644 --- a/system/stack/include/a2dp_vendor_ldac.h +++ b/system/stack/include/a2dp_vendor_ldac.h @@ -34,7 +34,7 @@ class A2dpCodecConfigLdacBase : public A2dpCodecConfig { protected: A2dpCodecConfigLdacBase(btav_a2dp_codec_index_t codec_index, const std::string& name, btav_a2dp_codec_priority_t codec_priority, bool is_source) - : A2dpCodecConfig(codec_index, A2DP_CODEC_ID_LDAC, name, codec_priority), + : A2dpCodecConfig(codec_index, bluetooth::a2dp::CodecId::LDAC, name, codec_priority), is_source_(is_source) {} tA2DP_STATUS setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability, uint8_t* p_result_codec_config) override; diff --git a/system/stack/include/a2dp_vendor_opus.h b/system/stack/include/a2dp_vendor_opus.h index 5b6e23b739a..4defa77b08d 100644 --- a/system/stack/include/a2dp_vendor_opus.h +++ b/system/stack/include/a2dp_vendor_opus.h @@ -29,7 +29,7 @@ class A2dpCodecConfigOpusBase : public A2dpCodecConfig { protected: A2dpCodecConfigOpusBase(btav_a2dp_codec_index_t codec_index, const std::string& name, btav_a2dp_codec_priority_t codec_priority, bool is_source) - : A2dpCodecConfig(codec_index, A2DP_CODEC_ID_OPUS, name, codec_priority), + : A2dpCodecConfig(codec_index, bluetooth::a2dp::CodecId::OPUS, name, codec_priority), is_source_(is_source) {} tA2DP_STATUS setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability, uint8_t* p_result_codec_config) override; diff --git a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc index a4e795a97dd..a4a263c20b8 100644 --- a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc +++ b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.cc @@ -111,7 +111,7 @@ std::optional provider::codec_index_str(btav_a2dp_codec_index_t cod inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::codec_index_str(codec_index); } -bool provider::codec_info(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, +bool provider::codec_info(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) { inc_func_call_count(__func__); return test::mock::audio_hal_interface_a2dp_encoding::codec_info(codec_index, codec_id, diff --git a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h index e35853b2b1e..f78c4ff550a 100644 --- a/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h +++ b/system/test/mock/mock_audio_hal_interface_a2dp_encoding.h @@ -86,17 +86,17 @@ struct codec_index_str { extern struct codec_index_str codec_index_str; // Name: codec_info -// Params: btav_a2dp_codec_index_t codec_index, uint64_t *codec_id, uint8_t* +// Params: btav_a2dp_codec_index_t codec_index, CodecId *codec_id, uint8_t* // codec_info, btav_a2dp_codec_config_t* codec_config Return: bool struct codec_info { static bool return_value; - std::function - body{[](btav_a2dp_codec_index_t /* codec_index */, uint64_t* /* codec_id */, - uint8_t* /* codec_info */, + std::function + body{[](btav_a2dp_codec_index_t /* codec_index */, + bluetooth::a2dp::CodecId* /* codec_id */, uint8_t* /* codec_info */, btav_a2dp_codec_config_t* /* codec_config */) { return return_value; }}; - bool operator()(btav_a2dp_codec_index_t codec_index, uint64_t* codec_id, uint8_t* codec_info, - btav_a2dp_codec_config_t* codec_config) { + bool operator()(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, + uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) { return body(codec_index, codec_id, codec_info, codec_config); } }; diff --git a/system/test/mock/mock_stack_a2dp_codec_config.cc b/system/test/mock/mock_stack_a2dp_codec_config.cc index a25fd48075d..2e4bc3f517c 100644 --- a/system/test/mock/mock_stack_a2dp_codec_config.cc +++ b/system/test/mock/mock_stack_a2dp_codec_config.cc @@ -43,8 +43,9 @@ A2dpCodecConfig* A2dpCodecs::findSourceCodecConfig(btav_a2dp_codec_index_t /* co inc_func_call_count(__func__); return nullptr; } -A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, tA2DP_CODEC_ID codec_id, - const std::string& name, btav_a2dp_codec_priority_t codec_priority) +A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, + bluetooth::a2dp::CodecId codec_id, const std::string& name, + btav_a2dp_codec_priority_t codec_priority) : codec_index_(codec_index), codec_id_(codec_id), name_(name), -- GitLab From 694885b2cc1f16773862b805e6387e140c44fd20 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 5 Nov 2024 19:10:01 +0000 Subject: [PATCH 568/875] stack/a2dp: Implement unit test for bluetooth::a2dp::ParseCodecId Bug: 331817295 Test: atest --host net_test_stack_a2dp_codecs_native Test: m com.android.btservices Flag: EXEMPT, test change Change-Id: Ifd4112367c55d8afeb229ef26423473b7db598ed --- system/stack/Android.bp | 1 + .../a2dp/media_codec_capabilities_test.cc | 161 ++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 system/stack/test/a2dp/media_codec_capabilities_test.cc diff --git a/system/stack/Android.bp b/system/stack/Android.bp index cb987debfc1..ad7045db9ed 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -1387,6 +1387,7 @@ cc_test { "test/a2dp/a2dp_sbc_unittest.cc", "test/a2dp/a2dp_vendor_ldac_unittest.cc", "test/a2dp/a2dp_vendor_regression_tests.cc", + "test/a2dp/media_codec_capabilities_test.cc", "test/a2dp/mock_bta_av_codec.cc", "test/a2dp/test_util.cc", "test/a2dp/wav_reader.cc", diff --git a/system/stack/test/a2dp/media_codec_capabilities_test.cc b/system/stack/test/a2dp/media_codec_capabilities_test.cc new file mode 100644 index 00000000000..e266912ab93 --- /dev/null +++ b/system/stack/test/a2dp/media_codec_capabilities_test.cc @@ -0,0 +1,161 @@ +/* + * 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. + */ + +#include +#include + +#include +#include + +#include "hardware/bt_av.h" +#include "stack/include/a2dp_codec_api.h" +#include "stack/include/a2dp_constants.h" +#include "stack/include/a2dp_vendor_aptx_constants.h" +#include "stack/include/a2dp_vendor_aptx_hd_constants.h" +#include "stack/include/a2dp_vendor_ldac_constants.h" +#include "stack/include/a2dp_vendor_opus_constants.h" +#include "stack/include/avdt_api.h" + +namespace { +static constexpr uint8_t kCodecCapabilitiesWithTruncatedMediaCodecType[] = {0x0}; +static constexpr uint8_t kCodecCapabilitiesWithTruncatedVendorCodecId[] = {0x5, 0x0, 0xff, + 0x1, 0x2, 0x3}; +static constexpr uint8_t kCodecCapabilitiesWithInvalidMediaCodecType[] = {0x2, 0x0, 0xaa}; +static constexpr uint8_t kCodecCapabilitiesWithInvalidVendorCodecId[] = {0x8, 0x0, 0xff, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6}; + +static constexpr uint8_t kSbcCodecCapabilities[] = { + 6, // Length (A2DP_SBC_INFO_LEN) + 0, // Media Type: AVDT_MEDIA_TYPE_AUDIO + 0, // Media Codec Type: A2DP_MEDIA_CT_SBC + 0x20 | 0x01, // Sample Frequency: A2DP_SBC_IE_SAMP_FREQ_44 | + // Channel Mode: A2DP_SBC_IE_CH_MD_JOINT + 0x10 | 0x04 | 0x01, // Block Length: A2DP_SBC_IE_BLOCKS_16 | + // Subbands: A2DP_SBC_IE_SUBBAND_8 | + // Allocation Method: A2DP_SBC_IE_ALLOC_MD_L + 2, // MinimumBitpool Value: A2DP_SBC_IE_MIN_BITPOOL + 53, // Maximum Bitpool Value: A2DP_SBC_MAX_BITPOOL + 7, // Fake + 8, // Fake + 9 // Fake +}; + +static constexpr uint8_t kAacCodecCapabilities[] = { + 8, // Length (A2DP_AAC_INFO_LEN) + 0, // Media Type: AVDT_MEDIA_TYPE_AUDIO + 2, // Media Codec Type: A2DP_MEDIA_CT_AAC + 0x80, // Object Type: A2DP_AAC_OBJECT_TYPE_MPEG2_LC + 0x01, // Sampling Frequency: A2DP_AAC_SAMPLING_FREQ_44100 + 0x04, // Channels: A2DP_AAC_CHANNEL_MODE_STEREO + 0x00 | 0x4, // Variable Bit Rate: + // A2DP_AAC_VARIABLE_BIT_RATE_DISABLED + // Bit Rate: 320000 = 0x4e200 + 0xe2, // Bit Rate: 320000 = 0x4e200 + 0x00, // Bit Rate: 320000 = 0x4e200 + 7, // Unused + 8, // Unused + 9 // Unused +}; + +static constexpr uint8_t kAptxCodecCapabilities[] = { + A2DP_APTX_CODEC_LEN, + AVDT_MEDIA_TYPE_AUDIO, + A2DP_MEDIA_CT_NON_A2DP, + 0x4F, // A2DP_APTX_VENDOR_ID + 0x00, // A2DP_APTX_VENDOR_ID + 0x00, // A2DP_APTX_VENDOR_ID + 0x00, // A2DP_APTX_VENDOR_ID + 0x01, // A2DP_APTX_CODEC_ID + 0x00, // A2DP_APTX_CODEC_ID, + A2DP_APTX_SAMPLERATE_44100 | A2DP_APTX_CHANNELS_STEREO, +}; + +static constexpr uint8_t kAptxHdCodecCapabilities[] = { + A2DP_APTX_HD_CODEC_LEN, + AVDT_MEDIA_TYPE_AUDIO, + A2DP_MEDIA_CT_NON_A2DP, + 0xD7, // A2DP_APTX_HD_VENDOR_ID + 0x00, // A2DP_APTX_HD_VENDOR_ID + 0x00, // A2DP_APTX_HD_VENDOR_ID + 0x00, // A2DP_APTX_HD_VENDOR_ID + 0x24, // A2DP_APTX_HD_CODEC_ID + 0x00, // A2DP_APTX_HD_CODEC_ID, + A2DP_APTX_HD_SAMPLERATE_44100 | A2DP_APTX_HD_CHANNELS_STEREO, + A2DP_APTX_HD_ACL_SPRINT_RESERVED0, + A2DP_APTX_HD_ACL_SPRINT_RESERVED1, + A2DP_APTX_HD_ACL_SPRINT_RESERVED2, + A2DP_APTX_HD_ACL_SPRINT_RESERVED3, +}; + +static constexpr uint8_t kLdacCodecCapabilities[] = { + A2DP_LDAC_CODEC_LEN, + AVDT_MEDIA_TYPE_AUDIO, + A2DP_MEDIA_CT_NON_A2DP, + 0x2D, // A2DP_LDAC_VENDOR_ID + 0x01, // A2DP_LDAC_VENDOR_ID + 0x00, // A2DP_LDAC_VENDOR_ID + 0x00, // A2DP_LDAC_VENDOR_ID + 0xAA, // A2DP_LDAC_CODEC_ID + 0x00, // A2DP_LDAC_CODEC_ID, + A2DP_LDAC_SAMPLING_FREQ_44100, + A2DP_LDAC_CHANNEL_MODE_STEREO, +}; + +static constexpr uint8_t kOpusCodecCapabilities[] = { + A2DP_OPUS_CODEC_LEN, // Length + AVDT_MEDIA_TYPE_AUDIO << 4, // Media Type + A2DP_MEDIA_CT_NON_A2DP, // Media Codec Type Vendor + (A2DP_OPUS_VENDOR_ID & 0x000000FF), + (A2DP_OPUS_VENDOR_ID & 0x0000FF00) >> 8, + (A2DP_OPUS_VENDOR_ID & 0x00FF0000) >> 16, + (A2DP_OPUS_VENDOR_ID & 0xFF000000) >> 24, + (A2DP_OPUS_CODEC_ID & 0x00FF), + (A2DP_OPUS_CODEC_ID & 0xFF00) >> 8, + A2DP_OPUS_CHANNEL_MODE_STEREO | A2DP_OPUS_20MS_FRAMESIZE | A2DP_OPUS_SAMPLING_FREQ_48000, +}; +} // namespace + +namespace bluetooth::a2dp { + +class MediaCodecCapabilitiesTest : public ::testing::Test {}; + +// Test the correctness of the method `bluetooth::a2dp::ParseCodecId`. +TEST_F(MediaCodecCapabilitiesTest, ParseCodecId) { + ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithTruncatedMediaCodecType), std::nullopt); + ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithTruncatedVendorCodecId), std::nullopt); + ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithInvalidMediaCodecType), std::nullopt); + ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithInvalidVendorCodecId), std::nullopt); + + ASSERT_EQ(ParseCodecId(kSbcCodecCapabilities), CodecId::SBC); + ASSERT_EQ(ParseCodecId(kAacCodecCapabilities), CodecId::AAC); + ASSERT_EQ(ParseCodecId(kAptxCodecCapabilities), CodecId::APTX); + ASSERT_EQ(ParseCodecId(kAptxHdCodecCapabilities), CodecId::APTX_HD); + ASSERT_EQ(ParseCodecId(kLdacCodecCapabilities), CodecId::LDAC); + ASSERT_EQ(ParseCodecId(kOpusCodecCapabilities), CodecId::OPUS); +} + +// Test provided to validate the Media Codec Capabilities, the legacy APIs `A2DP_xxx` +// are considered the source of truth here. +TEST_F(MediaCodecCapabilitiesTest, A2DP_SourceCodecIndex) { + ASSERT_EQ(A2DP_SourceCodecIndex(kSbcCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_SBC); + ASSERT_EQ(A2DP_SourceCodecIndex(kAacCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_AAC); + ASSERT_EQ(A2DP_SourceCodecIndex(kAptxCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_APTX); + ASSERT_EQ(A2DP_SourceCodecIndex(kAptxHdCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD); + ASSERT_EQ(A2DP_SourceCodecIndex(kLdacCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC); + ASSERT_EQ(A2DP_SourceCodecIndex(kOpusCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS); +} + +} // namespace bluetooth::a2dp -- GitLab From 0dc741f8e299eba896cbf9f5ced8139e182d820b Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Wed, 21 Aug 2024 18:07:29 +0000 Subject: [PATCH 569/875] Framework implementation for HCI Vendor Specific Handling Bug: 360924438 Test: mma -j32 Flag: com.android.bluetooth.flags.hci_vendor_specific_extension Change-Id: I02baab09782a0e8fc88d36c7d9bc4c4fa518fb8c --- Android.bp | 1 + android/app/aidl/Android.bp | 1 + .../aidl/android/bluetooth/IBluetooth.aidl | 8 + .../IBluetoothHciVendorSpecificCallback.aidl | 26 ++ android/app/jni/com_android_bluetooth.h | 2 + ...d_bluetooth_BluetoothHciVendorSpecific.cpp | 219 ++++++++++++++ ...oid_bluetooth_btservice_AdapterService.cpp | 6 + .../bluetooth/btservice/AdapterService.java | 91 ++++++ .../BluetoothHciVendorSpecificDispatcher.java | 129 ++++++++ ...toothHciVendorSpecificNativeInterface.java | 63 ++++ framework/api/system-current.txt | 9 + .../android/bluetooth/BluetoothAdapter.java | 283 ++++++++++++++++++ system/btif/Android.bp | 1 + system/btif/BUILD.gn | 1 + system/btif/include/btif_hci_vs.h | 32 ++ system/btif/src/btif_hci_vs.cc | 61 ++++ system/include/hardware/bt_hci_vs.h | 48 +++ 17 files changed, 981 insertions(+) create mode 100644 android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl create mode 100644 android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp create mode 100644 android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java create mode 100644 android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java create mode 100644 system/btif/include/btif_hci_vs.h create mode 100644 system/btif/src/btif_hci_vs.cc create mode 100644 system/include/hardware/bt_hci_vs.h diff --git a/Android.bp b/Android.bp index 476d0187362..fde5137bba7 100644 --- a/Android.bp +++ b/Android.bp @@ -154,6 +154,7 @@ java_defaults { "-Xep:OperatorPrecedence:ERROR", "-Xep:ReferenceEquality:ERROR", "-Xep:ReturnAtTheEndOfVoidFunction:ERROR", + "-Xep:ReturnFromVoid:ERROR", "-Xep:StaticAssignmentInConstructor:ERROR", "-Xep:StaticGuardedByInstance:ERROR", "-Xep:StringCaseLocaleUsage:ERROR", diff --git a/android/app/aidl/Android.bp b/android/app/aidl/Android.bp index 37678c29175..03f2d109ced 100644 --- a/android/app/aidl/Android.bp +++ b/android/app/aidl/Android.bp @@ -27,6 +27,7 @@ filegroup { "android/bluetooth/IBluetoothGattServerCallback.aidl", "android/bluetooth/IBluetoothHapClient.aidl", "android/bluetooth/IBluetoothHapClientCallback.aidl", + "android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl", "android/bluetooth/IBluetoothHeadset.aidl", "android/bluetooth/IBluetoothHeadsetClient.aidl", "android/bluetooth/IBluetoothHearingAid.aidl", diff --git a/android/app/aidl/android/bluetooth/IBluetooth.aidl b/android/app/aidl/android/bluetooth/IBluetooth.aidl index 28cb07db6e3..83cbe469ae2 100644 --- a/android/app/aidl/android/bluetooth/IBluetooth.aidl +++ b/android/app/aidl/android/bluetooth/IBluetooth.aidl @@ -19,6 +19,7 @@ package android.bluetooth; import android.app.PendingIntent; import android.bluetooth.IBluetoothActivityEnergyInfoListener; import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IBluetoothHciVendorSpecificCallback; import android.bluetooth.IBluetoothPreferredAudioProfilesCallback; import android.bluetooth.IBluetoothQualityReportReadyCallback; import android.bluetooth.IBluetoothCallback; @@ -293,6 +294,13 @@ interface IBluetooth @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") int unregisterBluetoothQualityReportReadyCallback(in IBluetoothQualityReportReadyCallback callback, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)") + void registerHciVendorSpecificCallback(in IBluetoothHciVendorSpecificCallback callback, in int[] eventCodes); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)") + void unregisterHciVendorSpecificCallback(in IBluetoothHciVendorSpecificCallback callback); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)") + void sendHciVendorSpecificCommand(in int ocf, in byte[] parameters, in IBluetoothHciVendorSpecificCallback callback); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") int getOffloadedTransportDiscoveryDataScanSupported(in AttributionSource attributionSource); diff --git a/android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl new file mode 100644 index 00000000000..2aac21b158c --- /dev/null +++ b/android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl @@ -0,0 +1,26 @@ +/* + * 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. + */ +package android.bluetooth; + +/** + * Callback definitions for HCI Vendor Specific Callback. + * @hide + */ +oneway interface IBluetoothHciVendorSpecificCallback { + void onCommandStatus(int ocf, in int status); + void onCommandComplete(int ocf, in byte[] returnParameters); + void onEvent(int code, in byte[] data); +} diff --git a/android/app/jni/com_android_bluetooth.h b/android/app/jni/com_android_bluetooth.h index c473b50ac69..d83e6a9f74a 100644 --- a/android/app/jni/com_android_bluetooth.h +++ b/android/app/jni/com_android_bluetooth.h @@ -162,6 +162,8 @@ int register_com_android_bluetooth_csip_set_coordinator(JNIEnv* env); int register_com_android_bluetooth_btservice_BluetoothQualityReport(JNIEnv* env); +int register_com_android_bluetooth_btservice_BluetoothHciVendorSpecific(JNIEnv* env); + struct JNIJavaMethod { const char* name; const char* signature; diff --git a/android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp b/android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp new file mode 100644 index 00000000000..96c15300af5 --- /dev/null +++ b/android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp @@ -0,0 +1,219 @@ +/* + * 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. + */ + +#define LOG_TAG "BluetoothHciVendorSpecificJni" + +#include + +#include "btif/include/btif_hci_vs.h" +#include "com_android_bluetooth.h" +#include "hardware/bt_hci_vs.h" + +using bluetooth::hci_vs::BluetoothHciVendorSpecificInterface; +using bluetooth::hci_vs::Cookie; + +namespace android { + +static std::shared_timed_mutex interface_mutex; +static std::shared_timed_mutex callbacks_mutex; + +static jmethodID method_onCommandStatus; +static jmethodID method_onCommandComplete; +static jmethodID method_onEvent; +static jobject mCallbacksObj = nullptr; + +class BluetoothHciVendorSpecificCallbacksImpl + : public bluetooth::hci_vs::BluetoothHciVendorSpecificCallbacks { +public: + ~BluetoothHciVendorSpecificCallbacksImpl() = default; + + void onCommandStatus(uint16_t ocf, uint8_t status, Cookie cookie) override { + log::info(""); + std::shared_lock lock(callbacks_mutex); + + CallbackEnv callbackEnv(__func__); + if (!callbackEnv.valid() || mCallbacksObj == nullptr) { + return; + } + + auto j_cookie = toJByteArray(callbackEnv.get(), cookie); + if (!j_cookie.get()) { + log::error("Error while allocating byte array for cookie"); + return; + } + + callbackEnv->CallVoidMethod(mCallbacksObj, method_onCommandStatus, (jint)ocf, (jint)status, + j_cookie.get()); + } + + void onCommandComplete(uint16_t ocf, std::vector return_parameters, + Cookie cookie) override { + log::info(""); + std::shared_lock lock(callbacks_mutex); + + CallbackEnv callbackEnv(__func__); + if (!callbackEnv.valid() || mCallbacksObj == nullptr) { + return; + } + + auto j_return_parameters = toJByteArray(callbackEnv.get(), return_parameters); + auto j_cookie = toJByteArray(callbackEnv.get(), cookie); + if (!j_return_parameters.get() || !j_cookie.get()) { + log::error("Error while allocating byte array for return parameters or cookie"); + return; + } + + callbackEnv->CallVoidMethod(mCallbacksObj, method_onCommandComplete, (jint)ocf, + j_return_parameters.get(), j_cookie.get()); + } + + void onEvent(uint8_t code, std::vector data) override { + log::info(""); + std::shared_lock lock(callbacks_mutex); + + CallbackEnv callbackEnv(__func__); + if (!callbackEnv.valid() || mCallbacksObj == nullptr) { + return; + } + + auto j_data = toJByteArray(callbackEnv.get(), data); + if (!j_data.get()) { + log::error("Error while allocating byte array for event data"); + return; + } + + callbackEnv->CallVoidMethod(mCallbacksObj, method_onEvent, (jint)code, j_data.get()); + } + +private: + template + static ScopedLocalRef toJByteArray(JNIEnv* env, const T& src) { + ScopedLocalRef dst(env, env->NewByteArray(src.size())); + if (dst.get()) { + env->SetByteArrayRegion(dst.get(), 0, src.size(), reinterpret_cast(src.data())); + } + return dst; + } +}; + +static BluetoothHciVendorSpecificInterface* sBluetoothHciVendorSpecificInterface = nullptr; +static BluetoothHciVendorSpecificCallbacksImpl sBluetoothHciVendorSpecificCallbacks; + +static void initNative(JNIEnv* env, jobject object) { + std::unique_lock interface_lock(interface_mutex); + std::unique_lock callbacks_lock(callbacks_mutex); + + if (sBluetoothHciVendorSpecificInterface != nullptr) { + log::info("Cleaning up BluetoothHciVendorSpecific Interface before initializing..."); + sBluetoothHciVendorSpecificInterface = nullptr; + } + + if (mCallbacksObj != nullptr) { + log::info("Cleaning up BluetoothHciVendorSpecific callback object"); + env->DeleteGlobalRef(mCallbacksObj); + mCallbacksObj = nullptr; + } + + if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { + log::error("Failed to allocate Global Ref for BluetoothHciVendorSpecific Callbacks"); + return; + } + + sBluetoothHciVendorSpecificInterface = + bluetooth::hci_vs::getBluetoothHciVendorSpecificInterface(); + if (sBluetoothHciVendorSpecificInterface == nullptr) { + log::error("Failed to get BluetoothHciVendorSpecific Interface"); + return; + } + + sBluetoothHciVendorSpecificInterface->init(&sBluetoothHciVendorSpecificCallbacks); +} + +static void cleanupNative(JNIEnv* env, jobject /* object */) { + std::unique_lock interface_lock(interface_mutex); + std::unique_lock callbacks_lock(callbacks_mutex); + + if (sBluetoothHciVendorSpecificInterface != nullptr) { + sBluetoothHciVendorSpecificInterface = nullptr; + } + + if (mCallbacksObj != nullptr) { + env->DeleteGlobalRef(mCallbacksObj); + mCallbacksObj = nullptr; + } +} + +static void sendCommandNative(JNIEnv* env, jobject /* obj */, jint ocf, jbyteArray parametersArray, + jbyteArray uuidArray) { + std::unique_lock interface_lock(interface_mutex); + log::verbose(""); + if (!sBluetoothHciVendorSpecificInterface) { + return; + } + + jbyte* pParameters = env->GetByteArrayElements(parametersArray, NULL); + jbyte* pUuid = env->GetByteArrayElements(uuidArray, NULL); + if (pParameters && pUuid && env->GetArrayLength(uuidArray) == 16) { + std::vector parameters( + reinterpret_cast(pParameters), + reinterpret_cast(pParameters + env->GetArrayLength(parametersArray))); + + Cookie cookie; + std::memcpy(cookie.data(), reinterpret_cast(pUuid), 16); + + if (!sBluetoothHciVendorSpecificInterface) { + return; + } + sBluetoothHciVendorSpecificInterface->sendCommand(ocf, parameters, cookie); + + } else { + jniThrowIOException(env, EINVAL); + } + + if (pParameters) { + env->ReleaseByteArrayElements(parametersArray, pParameters, 0); + } + + if (pUuid) { + env->ReleaseByteArrayElements(uuidArray, pUuid, 0); + } +} + +int register_com_android_bluetooth_btservice_BluetoothHciVendorSpecific(JNIEnv* env) { + const JNINativeMethod methods[] = { + {"initNative", "()V", reinterpret_cast(initNative)}, + {"cleanupNative", "()V", reinterpret_cast(cleanupNative)}, + {"sendCommandNative", "(I[B[B)V", reinterpret_cast(sendCommandNative)}, + }; + const int result = REGISTER_NATIVE_METHODS( + env, "com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface", + methods); + if (result != 0) { + return result; + } + + const JNIJavaMethod javaMethods[] = { + {"onCommandStatus", "(II[B)V", &method_onCommandStatus}, + {"onCommandComplete", "(I[B[B)V", &method_onCommandComplete}, + {"onEvent", "(I[B)V", &method_onEvent}, + }; + GET_JAVA_METHODS(env, "com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface", + javaMethods); + + return 0; +} + +} // namespace android diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index 8e2f4e201df..da4b61e1466 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -2509,6 +2509,12 @@ jint JNI_OnLoad(JavaVM* jvm, void* /* reserved */) { return JNI_ERR; } + status = android::register_com_android_bluetooth_btservice_BluetoothHciVendorSpecific(e); + if (status < 0) { + log::error("jni bluetooth hci vendor-specific registration failure: {}", status); + return JNI_ERR; + } + return JNI_VERSION_1_6; } diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index d1feef50d5c..695ad6e138d 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -73,6 +73,7 @@ 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; @@ -188,6 +189,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -273,6 +275,13 @@ public class AdapterService extends Service { private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener(); + private final BluetoothHciVendorSpecificDispatcher mBluetoothHciVendorSpecificDispatcher = + new BluetoothHciVendorSpecificDispatcher(); + private final BluetoothHciVendorSpecificNativeInterface + mBluetoothHciVendorSpecificNativeInterface = + new BluetoothHciVendorSpecificNativeInterface( + mBluetoothHciVendorSpecificDispatcher); + private final Looper mLooper; private final AdapterServiceHandler mHandler; @@ -685,6 +694,10 @@ public class AdapterService extends Service { "BluetoothQualityReportNativeInterface cannot be null when BQR starts"); mBluetoothQualityReportNativeInterface.init(); + if (Flags.hciVendorSpecificExtension()) { + mBluetoothHciVendorSpecificNativeInterface.init(); + } + mSdpManager = new SdpManager(this, mLooper); mDatabaseManager.start(MetadataDatabase.createDatabase(this)); @@ -4134,6 +4147,84 @@ public class AdapterService extends Service { 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 eventCodesSet = + Arrays.stream(eventCodes).boxed().collect(Collectors.toSet()); + if (eventCodesSet.stream() + .anyMatch((n) -> (n < 0) || (n >= 0x50 && 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 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(); diff --git a/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java new file mode 100644 index 00000000000..fe40294d207 --- /dev/null +++ b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java @@ -0,0 +1,129 @@ +/* + * 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. + */ + +package com.android.bluetooth.btservice; + +import android.bluetooth.IBluetoothHciVendorSpecificCallback; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.ArrayMap; +import android.util.Log; + +import com.android.bluetooth.Utils; +import com.android.internal.annotations.GuardedBy; + +import java.nio.ByteBuffer; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +class BluetoothHciVendorSpecificDispatcher { + private static final String TAG = "BluetoothHciVendorSpecificDispatcher"; + + private final class Registration implements IBinder.DeathRecipient { + final IBluetoothHciVendorSpecificCallback mCallback; + final Set mEventCodes; + final UUID mUuid; + + Registration(IBluetoothHciVendorSpecificCallback callback, Set eventCodes) { + mCallback = callback; + mEventCodes = eventCodes; + mUuid = UUID.randomUUID(); + } + + public void binderDied() { + synchronized (mRegistrations) { + mRegistrations.remove(mCallback.asBinder()); + } + } + } + + @GuardedBy("mRegistrations") + private final ArrayMap mRegistrations = new ArrayMap<>(); + + void unregister(IBluetoothHciVendorSpecificCallback callback) { + IBinder binder = callback.asBinder(); + synchronized (mRegistrations) { + Registration registration = mRegistrations.remove(binder); + if (registration == null) { + throw new IllegalStateException("callback was never registered"); + } + + binder.unlinkToDeath(registration, 0); + } + } + + void register(IBluetoothHciVendorSpecificCallback callback, Set eventCodes) { + IBinder binder = callback.asBinder(); + synchronized (mRegistrations) { + if (mRegistrations.containsKey(binder)) { + throw new IllegalStateException("callback already registered"); + } + + try { + Registration registration = new Registration(callback, eventCodes); + binder.linkToDeath(registration, 0); + mRegistrations.put(binder, registration); + } catch (RemoteException e) { + Log.e(TAG, "link to death", e); + } + } + } + + Optional getRegisteredCookie(IBluetoothHciVendorSpecificCallback callback) { + IBinder binder = callback.asBinder(); + synchronized (mRegistrations) { + if (!mRegistrations.containsKey(binder)) return Optional.empty(); + + Registration registration = mRegistrations.get(binder); + ByteBuffer cookieBb = ByteBuffer.allocate(16); + cookieBb.putLong(registration.mUuid.getMostSignificantBits()); + cookieBb.putLong(registration.mUuid.getLeastSignificantBits()); + return Optional.of(cookieBb.array()); + } + } + + void dispatchCommandStatusOrComplete( + byte[] cookie, + Utils.RemoteExceptionIgnoringConsumer action) { + ByteBuffer cookieBb = ByteBuffer.wrap(cookie); + UUID uuid = new UUID(cookieBb.getLong(), cookieBb.getLong()); + synchronized (mRegistrations) { + try { + Registration registration = + mRegistrations.values().stream() + .filter((r) -> r.mUuid.equals(uuid)) + .findAny() + .get(); + action.accept(registration.mCallback); + } catch (NoSuchElementException e) { + Log.e(TAG, "Command status or complete owner not registered"); + return; + } + } + } + + void broadcastEvent( + int eventCode, + Utils.RemoteExceptionIgnoringConsumer action) { + synchronized (mRegistrations) { + mRegistrations.values().stream() + .filter((r) -> r.mEventCodes.contains(eventCode)) + .forEach((r) -> action.accept(r.mCallback)); + } + } +} diff --git a/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java new file mode 100644 index 00000000000..7acf26f360f --- /dev/null +++ b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java @@ -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. + */ + +package com.android.bluetooth.btservice; + +class BluetoothHciVendorSpecificNativeInterface { + private static final String TAG = "BluetoothHciVendorSpecificNativeInterface"; + private final BluetoothHciVendorSpecificDispatcher mDispatcher; + + public BluetoothHciVendorSpecificNativeInterface( + BluetoothHciVendorSpecificDispatcher dispatcher) { + mDispatcher = dispatcher; + } + + void init() { + initNative(); + } + + void cleanup() { + cleanupNative(); + } + + void sendCommand(int ocf, byte[] parameters, byte[] cookie) { + sendCommandNative(ocf, parameters, cookie); + } + + // Callbacks from the native stack + + private void onCommandStatus(int ocf, int status, byte[] cookie) { + mDispatcher.dispatchCommandStatusOrComplete( + cookie, (cb) -> cb.onCommandStatus(ocf, status)); + } + + private void onCommandComplete(int ocf, byte[] returnParameters, byte[] cookie) { + mDispatcher.dispatchCommandStatusOrComplete( + cookie, (cb) -> cb.onCommandComplete(ocf, returnParameters)); + } + + private void onEvent(int code, byte[] data) { + mDispatcher.broadcastEvent(code, (cb) -> cb.onEvent(code, data)); + } + + // Native methods that call into the JNI interface + + private native void initNative(); + + private native void cleanupNative(); + + private native void sendCommandNative(int ocf, byte[] parameters, byte[] cookie); +} diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index cd02d1805e1..49344548736 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -83,12 +83,14 @@ package android.bluetooth { method @NonNull public static String nameForState(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int notifyActiveDeviceChangeApplied(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean registerBluetoothConnectionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.BluetoothConnectionCallback); + method @FlaggedApi("com.android.bluetooth.flags.hci_vendor_specific_extension") @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void registerBluetoothHciVendorSpecificCallback(@NonNull java.util.Set, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.BluetoothHciVendorSpecificCallback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int registerBluetoothQualityReportReadyCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.BluetoothQualityReportReadyCallback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int registerPreferredAudioProfilesChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.PreferredAudioProfilesChangedCallback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void requestControllerActivityEnergyInfo(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback); method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothSocket retrieveConnectedRfcommSocket(@NonNull java.util.UUID); + method @FlaggedApi("com.android.bluetooth.flags.hci_vendor_specific_extension") @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void sendBluetoothHciVendorSpecificCommand(@IntRange(from=0, to=1023) int, @NonNull byte[]); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setAutoOnEnabled(boolean); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int setBluetoothHciSnoopLoggingMode(int); @@ -98,6 +100,7 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int startRfcommServer(@NonNull String, @NonNull java.util.UUID, @NonNull android.app.PendingIntent); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int stopRfcommServer(@NonNull java.util.UUID); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean unregisterBluetoothConnectionCallback(@NonNull android.bluetooth.BluetoothAdapter.BluetoothConnectionCallback); + method @FlaggedApi("com.android.bluetooth.flags.hci_vendor_specific_extension") @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void unregisterBluetoothHciVendorSpecificCallback(@NonNull android.bluetooth.BluetoothAdapter.BluetoothHciVendorSpecificCallback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int unregisterBluetoothQualityReportReadyCallback(@NonNull android.bluetooth.BluetoothAdapter.BluetoothQualityReportReadyCallback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int unregisterPreferredAudioProfilesChangedCallback(@NonNull android.bluetooth.BluetoothAdapter.PreferredAudioProfilesChangedCallback); field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_AUTO_ON_STATE_CHANGED = "android.bluetooth.action.AUTO_ON_STATE_CHANGED"; @@ -126,6 +129,12 @@ package android.bluetooth { method public void onDeviceDisconnected(@NonNull android.bluetooth.BluetoothDevice, int); } + @FlaggedApi("com.android.bluetooth.flags.hci_vendor_specific_extension") public static interface BluetoothAdapter.BluetoothHciVendorSpecificCallback { + method public void onCommandComplete(@IntRange(from=0, to=1023) int, @NonNull byte[]); + method public void onCommandStatus(@IntRange(from=0, to=1023) int, @IntRange(from=0, to=255) int); + method public void onEvent(@IntRange(from=0, to=254) int, @NonNull byte[]); + } + public static interface BluetoothAdapter.BluetoothQualityReportReadyCallback { method public void onBluetoothQualityReportReady(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothQualityReport, int); } diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index ebbe97566d9..2be58683c5b 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -31,7 +31,9 @@ import static java.util.Objects.requireNonNull; import android.annotation.BroadcastBehavior; import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresNoPermission; @@ -3901,6 +3903,14 @@ public final class BluetoothAdapter { mAudioProfilesCallbackWrapper.registerToNewService(mService); mQualityCallbackWrapper.registerToNewService(mService); mBluetoothConnectionCallbackWrapper.registerToNewService(mService); + synchronized (mHciVendorSpecificCallbackRegistration) { + try { + mHciVendorSpecificCallbackRegistration.registerToService( + mService, mHciVendorSpecificCallbackStub); + } catch (Exception e) { + Log.e(TAG, "Failed to register HCI vendor-specific callback", e); + } + } } finally { mServiceLock.readLock().unlock(); } @@ -5575,4 +5585,277 @@ public final class BluetoothAdapter { } return BluetoothStatusCodes.ERROR_UNKNOWN; } + + /** + * Callbacks for receiving response of HCI Vendor-Specific Commands and Vendor-Specific Events + * that arise from the controller. + * + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_HCI_VENDOR_SPECIFIC_EXTENSION) + public interface BluetoothHciVendorSpecificCallback { + /** + * Invoked when an `HCI_Command_Status`, in response to a Vendor Command is received. + * + * @param ocf "Opcode command field" of the HCI Opcode, as defined in the Bluetooth Core + * Specification Vol 4, Part E, Section 5.4.1. + * @param status as defined by the Bluetooth Core Specification. + */ + void onCommandStatus( + @IntRange(from = 0x000, to = 0x3ff) int ocf, + @IntRange(from = 0x00, to = 0xff) int status); + + /** + * Invoked when an `HCI_Command_Complete`, in response to a Vendor Command is received. + * + * @param ocf "Opcode command field" of the HCI Opcode, as defined in the Bluetooth Core + * Specification Vol 4, Part E, Section 5.4.1. + * @param returnParameters Data returned by the command (from 0 to 252 Bytes). + */ + void onCommandComplete( + @IntRange(from = 0x000, to = 0x3ff) int ocf, @NonNull byte[] returnParameters); + + /** + * Invoked when an event is received. + * + * @param code The vendor-specific event Code. The first octet of the event parameters + * of a vendor-specific event (Bluetooth Core Specification Vol 4, Part E, 5.4.3). + * @param data from 0 to 254 Bytes. + */ + void onEvent(@IntRange(from = 0x00, to = 0xfe) int code, @NonNull byte[] data); + } + + private static final class HciVendorSpecificCallbackRegistration { + private BluetoothHciVendorSpecificCallback mCallback; + private Executor mExecutor; + private Set mEventCodeSet; + + void set( + BluetoothHciVendorSpecificCallback callback, + Set eventCodeSet, + Executor executor) { + mCallback = callback; + mEventCodeSet = eventCodeSet; + mExecutor = executor; + } + + void reset() { + mCallback = null; + mEventCodeSet = null; + mExecutor = null; + } + + boolean isSet() { + return mCallback != null; + } + + boolean isSet(BluetoothHciVendorSpecificCallback callback) { + return isSet() && (callback == mCallback); + } + + @RequiresPermission(BLUETOOTH_PRIVILEGED) + void registerToService(IBluetooth service, IBluetoothHciVendorSpecificCallback stub) { + if (service == null || !isSet()) { + return; + } + + int[] eventCodes = mEventCodeSet.stream().mapToInt(i -> i).toArray(); + try { + service.registerHciVendorSpecificCallback(stub, eventCodes); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } + + @RequiresPermission(BLUETOOTH_PRIVILEGED) + void unregisterFromService(IBluetooth service, IBluetoothHciVendorSpecificCallback stub) { + if (service == null) { + return; + } + try { + service.unregisterHciVendorSpecificCallback(stub); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } + + void execute(Consumer consumer) { + BluetoothHciVendorSpecificCallback callback = mCallback; + if (callback == null) { + return; + } + executeFromBinder(mExecutor, () -> consumer.accept(callback)); + } + } + + private final HciVendorSpecificCallbackRegistration mHciVendorSpecificCallbackRegistration = + new HciVendorSpecificCallbackRegistration(); + + private final IBluetoothHciVendorSpecificCallback mHciVendorSpecificCallbackStub = + new IBluetoothHciVendorSpecificCallback.Stub() { + + @Override + @RequiresNoPermission + public void onCommandStatus(int ocf, int status) { + synchronized (mHciVendorSpecificCallbackRegistration) { + if (Flags.hciVendorSpecificExtension()) { + mHciVendorSpecificCallbackRegistration.execute( + (cb) -> cb.onCommandStatus(ocf, status)); + } + } + } + + @Override + @RequiresNoPermission + public void onCommandComplete(int ocf, byte[] returnParameters) { + synchronized (mHciVendorSpecificCallbackRegistration) { + if (Flags.hciVendorSpecificExtension()) { + mHciVendorSpecificCallbackRegistration.execute( + (cb) -> cb.onCommandComplete(ocf, returnParameters)); + } + } + } + + @Override + @RequiresNoPermission + public void onEvent(int code, byte[] data) { + synchronized (mHciVendorSpecificCallbackRegistration) { + if (Flags.hciVendorSpecificExtension()) { + mHciVendorSpecificCallbackRegistration.execute( + (cb) -> cb.onEvent(code, data)); + } + } + } + }; + + /** + * Register an {@link BluetoothHciVendorCallback} to listen for HCI vendor responses and events + * + * @param eventCodeSet Set of vendor-specific event codes to listen for updates. Each + * vendor-specific event code must be in the range 0x00 to 0x4f or 0x60 to 0xff. + * The inclusive range 0x50-0x5f is reserved by the system. + * @param executor an {@link Executor} to execute given callback + * @param callback user implementation of the {@link BluetoothHciVendorCallback} + * @throws IllegalArgumentException if the callback is already registered, or event codes not in + * a valid range + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_HCI_VENDOR_SPECIFIC_EXTENSION) + @RequiresPermission(BLUETOOTH_PRIVILEGED) + @SuppressLint("AndroidFrameworkRequiresPermission") // Consumer wrongly report permission + public void registerBluetoothHciVendorSpecificCallback( + @NonNull Set eventCodeSet, + @NonNull @CallbackExecutor Executor executor, + @NonNull BluetoothHciVendorSpecificCallback callback) { + if (DBG) Log.d(TAG, "registerBluetoothHciVendorSpecificCallback()"); + + requireNonNull(eventCodeSet); + requireNonNull(executor); + requireNonNull(callback); + if (eventCodeSet.stream() + .anyMatch((n) -> (n < 0) || (n >= 0x50 && n < 0x60) || (n > 0xff))) { + throw new IllegalArgumentException("Event code not in valid range"); + } + + mServiceLock.readLock().lock(); + try { + synchronized (mHciVendorSpecificCallbackRegistration) { + if (mHciVendorSpecificCallbackRegistration.isSet()) { + throw new IllegalArgumentException("Only one registration allowed"); + } + mHciVendorSpecificCallbackRegistration.set(callback, eventCodeSet, executor); + try { + mHciVendorSpecificCallbackRegistration.registerToService( + mService, mHciVendorSpecificCallbackStub); + } catch (Exception e) { + mHciVendorSpecificCallbackRegistration.reset(); + throw e; + } + } + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Unregister the specified {@link BluetoothHciVendorCallback} + * + * @param callback user implementation of the {@link BluetoothHciVendorCallback} + * @throws IllegalArgumentException if the callback has not been registered + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_HCI_VENDOR_SPECIFIC_EXTENSION) + @RequiresPermission(BLUETOOTH_PRIVILEGED) + @SuppressLint("AndroidFrameworkRequiresPermission") // Consumer wrongly report permission + public void unregisterBluetoothHciVendorSpecificCallback( + @NonNull BluetoothHciVendorSpecificCallback callback) { + if (DBG) Log.d(TAG, "unregisterBluetoothHciVendorSpecificCallback()"); + + requireNonNull(callback); + + mServiceLock.readLock().lock(); + try { + synchronized (mHciVendorSpecificCallbackRegistration) { + if (!mHciVendorSpecificCallbackRegistration.isSet(callback)) { + throw new IllegalArgumentException("Callback not registered"); + } + mHciVendorSpecificCallbackRegistration.unregisterFromService( + mService, mHciVendorSpecificCallbackStub); + mHciVendorSpecificCallbackRegistration.reset(); + } + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Send an HCI Vendor-Specific Command + * + * @param ocf "Opcode command field" of the HCI Opcode, as defined in the Bluetooth Core + * Specification Vol 4, Part E, Section 5.4.1. Each vendor-specific ocf must be in the range + * 0x000-0x14f or 0x160-0x3ff. The inclusive range 0x150-0x15f is reserved by the system. + * @param parameters shall be less or equal to 255 bytes. + * @throws IllegalArgumentException if the ocf is not in a valid range + * @throws IllegalStateException when a callback has not been registered + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_HCI_VENDOR_SPECIFIC_EXTENSION) + @RequiresPermission(BLUETOOTH_PRIVILEGED) + public void sendBluetoothHciVendorSpecificCommand( + @IntRange(from = 0x000, to = 0x3ff) int ocf, @NonNull byte[] parameters) { + if (DBG) Log.d(TAG, "sendBluetoothHciVendorSpecificCommand()"); + + // 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("Opcode command value not in valid range"); + } + + requireNonNull(parameters); + if (parameters.length > 255) { + throw new IllegalArgumentException("Parameters size is too big"); + } + + mServiceLock.readLock().lock(); + try { + if (!mHciVendorSpecificCallbackRegistration.isSet()) { + throw new IllegalStateException("No Callback registered"); + } + + if (mService != null) { + mService.sendHciVendorSpecificCommand( + ocf, parameters, mHciVendorSpecificCallbackStub); + } + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } finally { + mServiceLock.readLock().unlock(); + } + } } diff --git a/system/btif/Android.bp b/system/btif/Android.bp index e6bdf90de5d..fd27f850baf 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -198,6 +198,7 @@ cc_library_static { "src/btif_gatt_client.cc", "src/btif_gatt_server.cc", "src/btif_gatt_util.cc", + "src/btif_hci_vs.cc", "src/btif_iot_config.cc", "src/btif_keystore.cc", "src/btif_metrics_logging.cc", diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn index 68ca336a3d0..167ac3bcfbf 100644 --- a/system/btif/BUILD.gn +++ b/system/btif/BUILD.gn @@ -59,6 +59,7 @@ static_library("btif") { "src/btif_le_audio_broadcaster.cc", "src/btif_has_client.cc", "src/btif_hearing_aid.cc", + "src/btif_hci_vs.cc", "src/btif_hf.cc", "src/btif_hf_client.cc", "src/btif_hh.cc", diff --git a/system/btif/include/btif_hci_vs.h b/system/btif/include/btif_hci_vs.h new file mode 100644 index 00000000000..0e227ed8e78 --- /dev/null +++ b/system/btif/include/btif_hci_vs.h @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#ifndef BTIF_HCI_VS_H_ +#define BTIF_HCI_VS_H_ + +#include + +#include "include/hardware/bt_hci_vs.h" + +namespace bluetooth { +namespace hci_vs { + +BluetoothHciVendorSpecificInterface* getBluetoothHciVendorSpecificInterface(); + +} // namespace hci_vs +} // namespace bluetooth + +#endif // BTIF_HCI_VS_H_ diff --git a/system/btif/src/btif_hci_vs.cc b/system/btif/src/btif_hci_vs.cc new file mode 100644 index 00000000000..5d591eaf5bb --- /dev/null +++ b/system/btif/src/btif_hci_vs.cc @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#include "btif_hci_vs.h" + +#include + +#include "btif_common.h" +#include "hci/hci_interface.h" +#include "main/shim/entry.h" +#include "packet/raw_builder.h" +#include "stack/include/main_thread.h" + +namespace bluetooth { +namespace hci_vs { + +std::unique_ptr hciVendorSpecificInterface; + +class BluetoothHciVendorSpecificInterfaceImpl + : public bluetooth::hci_vs::BluetoothHciVendorSpecificInterface { + ~BluetoothHciVendorSpecificInterfaceImpl() override = default; + + void init(BluetoothHciVendorSpecificCallbacks* callbacks) override { + log::info("BluetoothHciVendorSpecificInterfaceImpl"); + this->callbacks = callbacks; + } + + void sendCommand(uint16_t ocf, std::vector parameters, Cookie cookie) override { + // TODO: Send HCI Command + (void)ocf; + (void)parameters; + (void)cookie; + } + +private: + BluetoothHciVendorSpecificCallbacks* callbacks = nullptr; +}; + +BluetoothHciVendorSpecificInterface* getBluetoothHciVendorSpecificInterface() { + if (!hciVendorSpecificInterface) { + hciVendorSpecificInterface.reset(new BluetoothHciVendorSpecificInterfaceImpl()); + } + + return hciVendorSpecificInterface.get(); +} + +} // namespace hci_vs +} // namespace bluetooth diff --git a/system/include/hardware/bt_hci_vs.h b/system/include/hardware/bt_hci_vs.h new file mode 100644 index 00000000000..729f5a5334d --- /dev/null +++ b/system/include/hardware/bt_hci_vs.h @@ -0,0 +1,48 @@ +/* + * 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 + +#include + +namespace bluetooth { +namespace hci_vs { + +typedef std::array Cookie; + +class BluetoothHciVendorSpecificCallbacks { +public: + virtual ~BluetoothHciVendorSpecificCallbacks() = default; + + virtual void onCommandStatus(uint16_t ocf, uint8_t status, Cookie cookie) = 0; + virtual void onCommandComplete(uint16_t ocf, std::vector return_parameters, + Cookie cookie) = 0; + virtual void onEvent(uint8_t code, std::vector data) = 0; +}; + +class BluetoothHciVendorSpecificInterface { +public: + virtual ~BluetoothHciVendorSpecificInterface() = default; + + virtual void init(BluetoothHciVendorSpecificCallbacks* callbacks) = 0; + + virtual void sendCommand(uint16_t ocf, std::vector parameters, Cookie cookie) = 0; +}; + +} // namespace hci_vs +} // namespace bluetooth -- GitLab From 444208a0f51aa667591aae0121eecc895334a769 Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Wed, 4 Sep 2024 22:43:34 +0000 Subject: [PATCH 570/875] GD/HCI: Allow return of Command Status or Complete, without preconditionning Bug: 360924438 Test: mma -j32 Flag: com.android.bluetooth.flags.hci_vendor_specific_extension NO_IFTTT=Fuzzer actually not working, and test nothing Change-Id: I0fe231b594883aa9fdcd3807f3316f4832c4f96f --- .../classic_acl_connection_test.cc | 7 +++ .../hci/acl_manager/le_acl_connection_test.cc | 7 +++ system/gd/hci/command_interface.h | 6 +++ system/gd/hci/controller_test.cc | 6 +++ system/gd/hci/fuzz/fuzz_hci_layer.h | 5 +++ system/gd/hci/fuzz/hci_layer_fuzz_client.h | 6 ++- .../hci/fuzz/status_vs_complete_commands.cc | 5 +++ .../gd/hci/fuzz/status_vs_complete_commands.h | 2 +- system/gd/hci/hci_interface.h | 11 +++++ system/gd/hci/hci_layer.cc | 45 +++++++++++++++---- system/gd/hci/hci_layer.h | 4 ++ system/gd/hci/hci_layer_fake.cc | 7 +++ system/gd/hci/hci_layer_fake.h | 4 ++ system/gd/hci/hci_layer_mock.h | 4 ++ .../gd/hci/le_periodic_sync_manager_test.cc | 6 +++ 15 files changed, 115 insertions(+), 10 deletions(-) diff --git a/system/gd/hci/acl_manager/classic_acl_connection_test.cc b/system/gd/hci/acl_manager/classic_acl_connection_test.cc index 97ee9fc4afc..85a206df27e 100644 --- a/system/gd/hci/acl_manager/classic_acl_connection_test.cc +++ b/system/gd/hci/acl_manager/classic_acl_connection_test.cc @@ -142,6 +142,13 @@ private: } } + void EnqueueCommand( + std::unique_ptr /* command */, + common::ContextualOnceCallback< + void(hci::CommandStatusOrCompleteView)> /* on_status_or_complete */) override { + FAIL(); + } + public: virtual ~TestAclConnectionInterface() = default; diff --git a/system/gd/hci/acl_manager/le_acl_connection_test.cc b/system/gd/hci/acl_manager/le_acl_connection_test.cc index e8b9d0637a1..5153fa4d3b1 100644 --- a/system/gd/hci/acl_manager/le_acl_connection_test.cc +++ b/system/gd/hci/acl_manager/le_acl_connection_test.cc @@ -89,6 +89,13 @@ private: } } + void EnqueueCommand( + std::unique_ptr /* command */, + common::ContextualOnceCallback< + void(hci::CommandStatusOrCompleteView)> /* on_status_or_complete */) override { + FAIL(); + } + public: virtual ~TestLeAclConnectionInterface() = default; diff --git a/system/gd/hci/command_interface.h b/system/gd/hci/command_interface.h index 21edd42a760..a6781ef7c58 100644 --- a/system/gd/hci/command_interface.h +++ b/system/gd/hci/command_interface.h @@ -24,6 +24,8 @@ namespace bluetooth { namespace hci { +typedef std::variant CommandStatusOrCompleteView; + template class CommandInterface { public: @@ -40,6 +42,10 @@ public: virtual void EnqueueCommand( std::unique_ptr command, common::ContextualOnceCallback on_status) = 0; + + virtual void EnqueueCommand(std::unique_ptr command, + common::ContextualOnceCallback + on_status_or_complete) = 0; }; } // namespace hci } // namespace bluetooth diff --git a/system/gd/hci/controller_test.cc b/system/gd/hci/controller_test.cc index 3ea8416469b..06624692005 100644 --- a/system/gd/hci/controller_test.cc +++ b/system/gd/hci/controller_test.cc @@ -78,6 +78,12 @@ public: FAIL() << "Controller properties should not generate Command Status"; } + void EnqueueCommand(std::unique_ptr /* command */, + common::ContextualOnceCallback /* on_status_or_complete */) override { + FAIL() << "Controller properties should not generate Command Status"; + } + void HandleCommand(std::unique_ptr command_builder, common::ContextualOnceCallback on_complete) { auto bytes = std::make_shared>(); diff --git a/system/gd/hci/fuzz/fuzz_hci_layer.h b/system/gd/hci/fuzz/fuzz_hci_layer.h index 10492cdda96..d4a69c114e3 100644 --- a/system/gd/hci/fuzz/fuzz_hci_layer.h +++ b/system/gd/hci/fuzz/fuzz_hci_layer.h @@ -42,6 +42,11 @@ public: void EnqueueCommand( std::unique_ptr /* command */, common::ContextualOnceCallback /* on_status */) override {} + + void EnqueueCommand( + std::unique_ptr /* command */, + common::ContextualOnceCallback< + void(hci::CommandStatusOrCompleteView)> /* on_status_or_complete */) override {} }; class FuzzHciLayer : public HciLayer { diff --git a/system/gd/hci/fuzz/hci_layer_fuzz_client.h b/system/gd/hci/fuzz/hci_layer_fuzz_client.h index 3ec1ef34e82..3f9942c48aa 100644 --- a/system/gd/hci/fuzz/hci_layer_fuzz_client.h +++ b/system/gd/hci/fuzz/hci_layer_fuzz_client.h @@ -65,7 +65,11 @@ private: return; } - if (uses_command_status(commandPacket.GetOpCode())) { + if (uses_command_status_or_complete(commandPacket.GetOpCode())) { + interface->EnqueueCommand( + TBUILDER::FromView(commandPacket), + GetHandler()->BindOnce([](CommandStatusOrCompleteView /* status */) {})); + } else if (uses_command_status(commandPacket.GetOpCode())) { interface->EnqueueCommand(TBUILDER::FromView(commandPacket), GetHandler()->BindOnce([](CommandStatusView /* status */) {})); } else { diff --git a/system/gd/hci/fuzz/status_vs_complete_commands.cc b/system/gd/hci/fuzz/status_vs_complete_commands.cc index 1bed8ff07ab..c4cc72ca73f 100644 --- a/system/gd/hci/fuzz/status_vs_complete_commands.cc +++ b/system/gd/hci/fuzz/status_vs_complete_commands.cc @@ -45,6 +45,11 @@ bool uses_command_status(OpCode code) { return commands_that_use_status.find(code) != commands_that_use_status.end(); } +bool uses_command_status_or_complete(OpCode code) { + bool is_vendor_specific = (static_cast(code) >> 10) == 0x3f; + return is_vendor_specific; +} + } // namespace fuzz } // namespace hci } // namespace bluetooth diff --git a/system/gd/hci/fuzz/status_vs_complete_commands.h b/system/gd/hci/fuzz/status_vs_complete_commands.h index c50ce5e53ee..57cb9c1174d 100644 --- a/system/gd/hci/fuzz/status_vs_complete_commands.h +++ b/system/gd/hci/fuzz/status_vs_complete_commands.h @@ -23,7 +23,7 @@ namespace hci { namespace fuzz { bool uses_command_status(hci::OpCode code); - +bool uses_command_status_or_complete(hci::OpCode code); } } // namespace hci } // namespace bluetooth diff --git a/system/gd/hci/hci_interface.h b/system/gd/hci/hci_interface.h index 057039fc9f3..32e7031e162 100644 --- a/system/gd/hci/hci_interface.h +++ b/system/gd/hci/hci_interface.h @@ -50,6 +50,10 @@ public: common::ContextualOnceCallback on_status) override = 0; + void EnqueueCommand(std::unique_ptr command, + common::ContextualOnceCallback + on_status_or_complete) override = 0; + virtual common::BidiQueueEnd* GetAclQueueEnd() = 0; virtual common::BidiQueueEnd* GetScoQueueEnd() = 0; @@ -138,6 +142,13 @@ protected: common::ContextualOnceCallback on_status) override { hci_->EnqueueCommand(std::move(command), std::move(on_status)); } + + void EnqueueCommand(std::unique_ptr command, + common::ContextualOnceCallback + on_status_or_complete) override { + hci_->EnqueueCommand(std::move(command), std::move(on_status_or_complete)); + } + HciInterface* hci_; common::OnceCallback cleanup_; }; diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc index f9847101c03..520d71a1f81 100644 --- a/system/gd/hci/hci_layer.cc +++ b/system/gd/hci/hci_layer.cc @@ -47,6 +47,7 @@ using bluetooth::common::ContextualCallback; using bluetooth::common::ContextualOnceCallback; using bluetooth::hci::CommandBuilder; using bluetooth::hci::CommandCompleteView; +using bluetooth::hci::CommandStatusOrCompleteView; using bluetooth::hci::CommandStatusView; using bluetooth::hci::EventView; using bluetooth::hci::LeMetaEventView; @@ -87,24 +88,34 @@ static void abort_after_time_out(OpCode op_code) { class CommandQueueEntry { public: + enum class WaitingFor { STATUS, COMPLETE, STATUS_OR_COMPLETE }; + CommandQueueEntry(unique_ptr command_packet, ContextualOnceCallback on_complete_function) : command(std::move(command_packet)), - waiting_for_status_(false), + waiting_for_(WaitingFor::COMPLETE), on_complete(std::move(on_complete_function)) {} CommandQueueEntry(unique_ptr command_packet, ContextualOnceCallback on_status_function) : command(std::move(command_packet)), - waiting_for_status_(true), + waiting_for_(WaitingFor::STATUS), on_status(std::move(on_status_function)) {} + CommandQueueEntry( + unique_ptr command_packet, + ContextualOnceCallback on_status_or_complete_function) + : command(std::move(command_packet)), + waiting_for_(WaitingFor::STATUS_OR_COMPLETE), + on_status_or_complete(std::move(on_status_or_complete_function)) {} + unique_ptr command; unique_ptr command_view; - bool waiting_for_status_; + WaitingFor waiting_for_; ContextualOnceCallback on_status; ContextualOnceCallback on_complete; + ContextualOnceCallback on_status_or_complete; template ContextualOnceCallback* GetCallback() { @@ -120,6 +131,12 @@ public: ContextualOnceCallback* GetCallback() { return &on_complete; } + + template <> + ContextualOnceCallback* + GetCallback() { + return &on_status_or_complete; + } }; struct HciLayer::impl { @@ -181,8 +198,8 @@ struct HciLayer::impl { OpCode op_code = response_view.GetCommandOpCode(); ErrorCode status = response_view.GetStatus(); if (status != ErrorCode::SUCCESS) { - log::error("Received UNEXPECTED command status:{} opcode:{}", ErrorCodeText(status), - OpCodeText(op_code)); + log::warn("Received UNEXPECTED command status:{} opcode:{}", ErrorCodeText(status), + OpCodeText(op_code)); } handle_command_response(event, "status"); } @@ -215,8 +232,10 @@ struct HciLayer::impl { OpCodeText(waiting_command_), OpCodeText(op_code)); bool is_vendor_specific = static_cast(op_code) & (0x3f << 10); + using WaitingFor = CommandQueueEntry::WaitingFor; + WaitingFor waiting_for = command_queue_.front().waiting_for_; CommandStatusView status_view = CommandStatusView::Create(event); - if (is_vendor_specific && (is_status && !command_queue_.front().waiting_for_status_) && + if (is_vendor_specific && (is_status && waiting_for == WaitingFor::COMPLETE) && (status_view.IsValid() && status_view.GetStatus() == ErrorCode::UNKNOWN_HCI_COMMAND)) { // If this is a command status of a vendor specific command, and command complete is expected, // we can't treat this as hard failure since we have no way of probing this lack of support at @@ -235,11 +254,14 @@ struct HciLayer::impl { log::assert_that(command_complete_view.IsValid(), "assert failed: command_complete_view.IsValid()"); (*command_queue_.front().GetCallback())(command_complete_view); - } else { - log::assert_that(command_queue_.front().waiting_for_status_ == is_status, + } else if (waiting_for != WaitingFor::STATUS_OR_COMPLETE) { + log::assert_that((waiting_for == WaitingFor::STATUS) == is_status, "{} was not expecting {} event", OpCodeText(op_code), logging_id); (*command_queue_.front().GetCallback())(std::move(response_view)); + } else { + (*command_queue_.front().GetCallback())( + std::move(response_view)); } #ifdef TARGET_FLOSS @@ -600,6 +622,13 @@ void HciLayer::EnqueueCommand(unique_ptr command, std::move(on_status)); } +void HciLayer::EnqueueCommand( + unique_ptr command, + ContextualOnceCallback on_status_or_complete) { + CallOn(impl_, &impl::enqueue_command, std::move(command), + std::move(on_status_or_complete)); +} + void HciLayer::RegisterEventHandler(EventCode event, ContextualCallback handler) { CallOn(impl_, &impl::register_event, event, handler); } diff --git a/system/gd/hci/hci_layer.h b/system/gd/hci/hci_layer.h index fc9b79e1961..c330dc3cd21 100644 --- a/system/gd/hci/hci_layer.h +++ b/system/gd/hci/hci_layer.h @@ -58,6 +58,10 @@ public: void EnqueueCommand(std::unique_ptr command, common::ContextualOnceCallback on_status) override; + void EnqueueCommand(std::unique_ptr command, + common::ContextualOnceCallback + on_status_or_complete) override; + virtual common::BidiQueueEnd* GetAclQueueEnd(); virtual common::BidiQueueEnd* GetScoQueueEnd(); diff --git a/system/gd/hci/hci_layer_fake.cc b/system/gd/hci/hci_layer_fake.cc index ca13230d318..b09bb5feebd 100644 --- a/system/gd/hci/hci_layer_fake.cc +++ b/system/gd/hci/hci_layer_fake.cc @@ -102,6 +102,13 @@ void HciLayerFake::EnqueueCommand( } } +void HciLayerFake::EnqueueCommand( + std::unique_ptr /* command */, + common::ContextualOnceCallback< + void(CommandStatusOrCompleteView)> /* on_status_or_complete */) { + FAIL(); +} + CommandView HciLayerFake::GetCommand() { EXPECT_EQ(command_future_.wait_for(std::chrono::milliseconds(1000)), std::future_status::ready); diff --git a/system/gd/hci/hci_layer_fake.h b/system/gd/hci/hci_layer_fake.h index a15bc0ec542..4743c0c0ffc 100644 --- a/system/gd/hci/hci_layer_fake.h +++ b/system/gd/hci/hci_layer_fake.h @@ -40,6 +40,10 @@ public: std::unique_ptr command, common::ContextualOnceCallback on_complete) override; + void EnqueueCommand(std::unique_ptr command, + common::ContextualOnceCallback + on_status_or_complete) override; + CommandView GetCommand(); CommandView GetCommand(OpCode op_code); diff --git a/system/gd/hci/hci_layer_mock.h b/system/gd/hci/hci_layer_mock.h index 7cb4e73460c..ef63887dc5e 100644 --- a/system/gd/hci/hci_layer_mock.h +++ b/system/gd/hci/hci_layer_mock.h @@ -40,6 +40,10 @@ public: (std::unique_ptr, common::ContextualOnceCallback), (override)); + MOCK_METHOD(void, EnqueueCommand, + (std::unique_ptr, + common::ContextualOnceCallback), + (override)); MOCK_METHOD((common::BidiQueueEnd*), GetAclQueueEnd, (), (override)); MOCK_METHOD((common::BidiQueueEnd*), GetScoQueueEnd, (), (override)); MOCK_METHOD((common::BidiQueueEnd*), GetIsoQueueEnd, (), (override)); diff --git a/system/gd/hci/le_periodic_sync_manager_test.cc b/system/gd/hci/le_periodic_sync_manager_test.cc index 94d7efef10b..447948bd206 100644 --- a/system/gd/hci/le_periodic_sync_manager_test.cc +++ b/system/gd/hci/le_periodic_sync_manager_test.cc @@ -71,6 +71,12 @@ public: } } + void EnqueueCommand(std::unique_ptr /* command */, + common::ContextualOnceCallback /* on_status_or_complete */) override { + FAIL(); + } + void SetCommandFuture() { ASSERT_EQ(command_promise_, nullptr) << "Promises, Promises, ... Only one at a time."; command_promise_ = std::make_unique>(); -- GitLab From 8b0522f37fd0d73cd3c9e0b033b4f24991ce16ad Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Tue, 10 Sep 2024 23:19:43 +0000 Subject: [PATCH 571/875] GD/HCI: Add fallback handler for vendor specific event Bug: 360924438 Test: mma -j32 Flag: com.android.bluetooth.flags.hci_vendor_specific_extension Change-Id: I095107e7d2d070799399a69a7d21bd83d6b1ab2e --- system/btif/src/btif_hci_vs.cc | 63 ++++++++++++++++++++++++++++++---- system/gd/hci/hci_interface.h | 5 +++ system/gd/hci/hci_layer.cc | 24 +++++++++++-- system/gd/hci/hci_layer.h | 5 +++ system/gd/hci/hci_layer_mock.h | 3 ++ 5 files changed, 91 insertions(+), 9 deletions(-) diff --git a/system/btif/src/btif_hci_vs.cc b/system/btif/src/btif_hci_vs.cc index 5d591eaf5bb..2c1eb034fe3 100644 --- a/system/btif/src/btif_hci_vs.cc +++ b/system/btif/src/btif_hci_vs.cc @@ -27,26 +27,77 @@ namespace bluetooth { namespace hci_vs { +using hci::CommandCompleteView; +using hci::CommandStatusOrCompleteView; +using hci::CommandStatusView; +using hci::OpCode; +using hci::VendorSpecificEventView; + std::unique_ptr hciVendorSpecificInterface; +static void CommandStatusOrCompleteCallback(BluetoothHciVendorSpecificCallbacks* callbacks, + Cookie cookie, + CommandStatusOrCompleteView status_or_complete) { + if (std::holds_alternative(status_or_complete)) { + auto view = std::get(status_or_complete); + auto ocf = static_cast(view.GetCommandOpCode()) & 0x3ff; + auto status = static_cast(view.GetStatus()); + callbacks->commandStatusDelivery(ocf, status, cookie); + + } else if (std::holds_alternative(status_or_complete)) { + auto view = std::get(status_or_complete); + auto ocf = static_cast(view.GetCommandOpCode()) & 0x3ff; + std::vector return_parameters(view.GetPayload().begin(), view.GetPayload().end()); + callbacks->commandCompleteDelivery(ocf, return_parameters, cookie); + } +} + +static void EventCallback(BluetoothHciVendorSpecificCallbacks* callbacks, + VendorSpecificEventView view) { + const uint8_t aosp_reserved_codes_range[] = {0x50, 0x60}; + auto code = static_cast(view.GetSubeventCode()); + if (code >= aosp_reserved_codes_range[0] && code < aosp_reserved_codes_range[1]) { + return; + } + + std::vector data(view.GetPayload().begin(), view.GetPayload().end()); + callbacks->eventDelivery(code, data); +} + class BluetoothHciVendorSpecificInterfaceImpl : public bluetooth::hci_vs::BluetoothHciVendorSpecificInterface { ~BluetoothHciVendorSpecificInterfaceImpl() override = default; void init(BluetoothHciVendorSpecificCallbacks* callbacks) override { log::info("BluetoothHciVendorSpecificInterfaceImpl"); - this->callbacks = callbacks; + log::assert_that(callbacks != nullptr, "callbacks cannot be null"); + callbacks_ = callbacks; + + shim::GetHciLayer()->RegisterDefaultVendorSpecificEventHandler( + get_main()->Bind(EventCallback, callbacks_)); } void sendCommand(uint16_t ocf, std::vector parameters, Cookie cookie) override { - // TODO: Send HCI Command - (void)ocf; - (void)parameters; - (void)cookie; + if (callbacks_ == nullptr) { + log::error("not initialized"); + return; + } + + if (ocf & ~0x3ff) { + log::error("invalid vendor-specific op-code"); + return; + } + + const uint16_t ogf_vendor_specific = 0x3f; + auto op_code = static_cast((ogf_vendor_specific << 10) | ocf); + + shim::GetHciLayer()->EnqueueCommand( + hci::CommandBuilder::Create(op_code, std::make_unique(parameters)), + get_main()->BindOnce(CommandStatusOrCompleteCallback, callbacks_, std::move(cookie))); } private: - BluetoothHciVendorSpecificCallbacks* callbacks = nullptr; + BluetoothHciVendorSpecificCallbacks* callbacks_ = nullptr; }; BluetoothHciVendorSpecificInterface* getBluetoothHciVendorSpecificInterface() { diff --git a/system/gd/hci/hci_interface.h b/system/gd/hci/hci_interface.h index 32e7031e162..46c5f400bdc 100644 --- a/system/gd/hci/hci_interface.h +++ b/system/gd/hci/hci_interface.h @@ -65,6 +65,11 @@ public: virtual void UnregisterEventHandler(EventCode event_code) = 0; + virtual void RegisterDefaultVendorSpecificEventHandler( + common::ContextualCallback handler) = 0; + + virtual void UnregisterDefaultVendorSpecificEventHandler() = 0; + virtual void RegisterLeEventHandler( SubeventCode subevent_code, common::ContextualCallback event_handler) = 0; diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc index 520d71a1f81..87061483d91 100644 --- a/system/gd/hci/hci_layer.cc +++ b/system/gd/hci/hci_layer.cc @@ -400,6 +400,12 @@ struct HciLayer::impl { vs_event_handlers_.erase(vs_event_handlers_.find(event)); } + void register_vs_event_default(ContextualCallback handler) { + vs_event_default_handler_ = std::move(handler); + } + + void unregister_vs_event_default() { vs_event_default_handler_.reset(); } + static void abort_after_root_inflammation(uint8_t vse_error) { log::fatal("Root inflammation with reason 0x{:02x}", vse_error); } @@ -524,11 +530,13 @@ struct HciLayer::impl { VendorSpecificEventView vs_event_view = VendorSpecificEventView::Create(event); log::assert_that(vs_event_view.IsValid(), "assert failed: vs_event_view.IsValid()"); VseSubeventCode subevent_code = vs_event_view.GetSubeventCode(); - if (vs_event_handlers_.find(subevent_code) == vs_event_handlers_.end()) { + if (vs_event_handlers_.find(subevent_code) != vs_event_handlers_.end()) { + vs_event_handlers_[subevent_code](vs_event_view); + } else if (vs_event_default_handler_.has_value()) { + (*vs_event_default_handler_)(vs_event_view); + } else { log::warn("Unhandled vendor specific event of type {}", VseSubeventCodeText(subevent_code)); - return; } - vs_event_handlers_[subevent_code](vs_event_view); } hal::HciHal* hal_; @@ -540,6 +548,7 @@ struct HciLayer::impl { std::map> event_handlers_; std::map> le_event_handlers_; std::map> vs_event_handlers_; + std::optional> vs_event_default_handler_; OpCode waiting_command_{OpCode::NONE}; uint8_t command_credits_{1}; // Send reset first @@ -655,6 +664,15 @@ void HciLayer::UnregisterVendorSpecificEventHandler(VseSubeventCode event) { CallOn(impl_, &impl::unregister_vs_event, event); } +void HciLayer::RegisterDefaultVendorSpecificEventHandler( + ContextualCallback handler) { + CallOn(impl_, &impl::register_vs_event_default, handler); +} + +void HciLayer::UnregisterDefaultVendorSpecificEventHandler() { + CallOn(impl_, &impl::unregister_vs_event_default); +} + void HciLayer::on_disconnection_complete(EventView event_view) { auto disconnection_view = DisconnectionCompleteView::Create(event_view); if (!disconnection_view.IsValid()) { diff --git a/system/gd/hci/hci_layer.h b/system/gd/hci/hci_layer.h index c330dc3cd21..d30884a6255 100644 --- a/system/gd/hci/hci_layer.h +++ b/system/gd/hci/hci_layer.h @@ -84,6 +84,11 @@ public: virtual void UnregisterVendorSpecificEventHandler(VseSubeventCode event); + virtual void RegisterDefaultVendorSpecificEventHandler( + common::ContextualCallback handler); + + virtual void UnregisterDefaultVendorSpecificEventHandler(); + virtual void RegisterForDisconnects( common::ContextualCallback on_disconnect); diff --git a/system/gd/hci/hci_layer_mock.h b/system/gd/hci/hci_layer_mock.h index ef63887dc5e..f2072032511 100644 --- a/system/gd/hci/hci_layer_mock.h +++ b/system/gd/hci/hci_layer_mock.h @@ -57,6 +57,9 @@ public: (VseSubeventCode, common::ContextualCallback), (override)); MOCK_METHOD((void), UnregisterVendorSpecificEventHandler, (VseSubeventCode), (override)); + MOCK_METHOD((void), RegisterDefaultVendorSpecificEventHandler, + (common::ContextualCallback), (override)); + MOCK_METHOD((void), UnregisterDefaultVendorSpecificEventHandler, (), (override)); MOCK_METHOD((SecurityInterface*), GetSecurityInterface, (common::ContextualCallback event_handler), (override)); -- GitLab From b50dc7c9979c534dc9d704b3acb9697d700d436a Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Wed, 11 Sep 2024 18:03:58 +0000 Subject: [PATCH 572/875] HCI Vendor specific hook to GD/HAL Bug: 360924438 Test: mma -j32 Flag: com.android.bluetooth.flags.hci_vendor_specific_extension Change-Id: I58f1d36df797d33810ea90c58648eac03af8b966 --- system/btif/src/btif_hci_vs.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/system/btif/src/btif_hci_vs.cc b/system/btif/src/btif_hci_vs.cc index 2c1eb034fe3..35b8b9cdfb2 100644 --- a/system/btif/src/btif_hci_vs.cc +++ b/system/btif/src/btif_hci_vs.cc @@ -42,13 +42,15 @@ static void CommandStatusOrCompleteCallback(BluetoothHciVendorSpecificCallbacks* auto view = std::get(status_or_complete); auto ocf = static_cast(view.GetCommandOpCode()) & 0x3ff; auto status = static_cast(view.GetStatus()); - callbacks->commandStatusDelivery(ocf, status, cookie); + do_in_jni_thread(base::BindOnce(&BluetoothHciVendorSpecificCallbacks::onCommandStatus, + base::Unretained(callbacks), ocf, status, cookie)); } else if (std::holds_alternative(status_or_complete)) { auto view = std::get(status_or_complete); auto ocf = static_cast(view.GetCommandOpCode()) & 0x3ff; std::vector return_parameters(view.GetPayload().begin(), view.GetPayload().end()); - callbacks->commandCompleteDelivery(ocf, return_parameters, cookie); + do_in_jni_thread(base::BindOnce(&BluetoothHciVendorSpecificCallbacks::onCommandComplete, + base::Unretained(callbacks), ocf, return_parameters, cookie)); } } @@ -61,7 +63,8 @@ static void EventCallback(BluetoothHciVendorSpecificCallbacks* callbacks, } std::vector data(view.GetPayload().begin(), view.GetPayload().end()); - callbacks->eventDelivery(code, data); + do_in_jni_thread(base::BindOnce(&BluetoothHciVendorSpecificCallbacks::onEvent, + base::Unretained(callbacks), code, data)); } class BluetoothHciVendorSpecificInterfaceImpl @@ -92,7 +95,8 @@ class BluetoothHciVendorSpecificInterfaceImpl auto op_code = static_cast((ogf_vendor_specific << 10) | ocf); shim::GetHciLayer()->EnqueueCommand( - hci::CommandBuilder::Create(op_code, std::make_unique(parameters)), + hci::CommandBuilder::Create( + op_code, std::make_unique(std::move(parameters))), get_main()->BindOnce(CommandStatusOrCompleteCallback, callbacks_, std::move(cookie))); } -- GitLab From f661e2e519e2d49629e32614100d895bc8ed3819 Mon Sep 17 00:00:00 2001 From: William Escande Date: Mon, 7 Oct 2024 15:14:50 -0700 Subject: [PATCH 573/875] BluetoothAdapter: cleanup no-op cleanup found after restoring BluetoothAdapterTest Bug: 371656429 Test: atest CtsBluetoothTestCases Flag: TEST_ONLY Change-Id: I611f330a4ada51d529ff332fc2397922931391d1 --- framework/java/android/bluetooth/BluetoothAdapter.java | 2 +- .../com/android/server/bluetooth/BluetoothManagerService.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index ebbe97566d9..76f1904e0ad 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -5532,7 +5532,7 @@ public final class BluetoothAdapter { try { mManagerService.setAutoOnEnabled(status); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); } } diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 35e0a61311f..8688e5913b8 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -2402,8 +2402,7 @@ class BluetoothManagerService { snoopMode = BluetoothProperties.snoop_log_mode_values.FULL; break; default: - Log.e(TAG, "setBtHciSnoopLogMode: Not a valid mode:" + mode); - return BluetoothStatusCodes.ERROR_BAD_PARAMETERS; + throw new IllegalArgumentException("Invalid HCI snoop log mode param value"); } try { BluetoothProperties.snoop_log_mode(snoopMode); -- GitLab From 4510904b187e297d5cec4f94c7834b9e09905f12 Mon Sep 17 00:00:00 2001 From: Palash Ahuja Date: Tue, 5 Nov 2024 14:22:09 -0800 Subject: [PATCH 574/875] BluetoothMetrics: Add BONDED state transition for pairing Bug: 375437118 Test: m statsd_testdrive && statsd_testdrive -terse 916 Flag: EXEMPT, metrics changes only Change-Id: I593f47c10fc3d893b3ea26f12f0902b65854b2b1 --- system/btif/src/btif_dm.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 118aa5eba60..dd0e86ceb2e 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -569,6 +569,10 @@ static void bond_state_changed(bt_status_t status, const RawAddress& bd_addr, bluetooth::os::LogMetricBluetoothEvent(ToGdAddress(bd_addr), android::bluetooth::EventType::BOND, android::bluetooth::State::STATE_NONE); + } else if (state == BT_BOND_STATE_BONDED) { + bluetooth::os::LogMetricBluetoothEvent(ToGdAddress(bd_addr), + android::bluetooth::EventType::BOND, + android::bluetooth::State::STATE_BONDED); } } -- GitLab From ab0c3a5153cb719fedfbbc1d90feaefbb6a85d68 Mon Sep 17 00:00:00 2001 From: Palash Ahuja Date: Tue, 5 Nov 2024 14:28:08 -0800 Subject: [PATCH 575/875] BluetoothMetrics: Adding the transport level breakdown for pairing Test: m statsd_testdrive && statsd_testdrive -terse 916 Bug: 375437118 Flag: EXEMPT, metrics change only Change-Id: I20e793f29595f6ec26d0917171a5570074d8de59 --- system/btif/src/btif_dm.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index dd0e86ceb2e..c7577b2a05e 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -812,6 +812,10 @@ static void btif_dm_cb_create_bond(const RawAddress bd_addr, tBT_TRANSPORT trans /* Track originator of bond creation */ pairing_cb.is_local_initiated = true; + bluetooth::os::LogMetricBluetoothEvent( + ToGdAddress(bd_addr), android::bluetooth::EventType::TRANSPORT, + transport == BT_TRANSPORT_LE ? android::bluetooth::State::LE + : android::bluetooth::State::CLASSIC); BTA_DmBond(bd_addr, addr_type, transport, device_type); } -- GitLab From 9f917bc946a9b32c6da6932f3e59e33115a0f3d2 Mon Sep 17 00:00:00 2001 From: Palash Ahuja Date: Tue, 5 Nov 2024 15:42:42 -0800 Subject: [PATCH 576/875] BluetoothMetrics: Mapping all the error codes to State enum variants Bug: 375437118 Test: m statsd_testdrive && statsd_testdrive -terse 916 Flag: EXEMPT, metrics logging Change-Id: I3e2a6c330c52a0a12c4ff8d24145b43156271f65 --- system/gd/metrics/bluetooth_event.cc | 96 ++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/system/gd/metrics/bluetooth_event.cc b/system/gd/metrics/bluetooth_event.cc index 86ac065eac3..292fe3cf928 100644 --- a/system/gd/metrics/bluetooth_event.cc +++ b/system/gd/metrics/bluetooth_event.cc @@ -60,6 +60,102 @@ State MapErrorCodeToState(ErrorCode reason) { return State::PAIRING_NOT_ALLOWED; case ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES: return State::RESOURCES_EXCEEDED; + case ErrorCode::HARDWARE_FAILURE: + return State::HARDWARE_FAILURE; + case ErrorCode::MEMORY_CAPACITY_EXCEEDED: + return State::MEMORY_CAPACITY_EXCEEDED; + case ErrorCode::CONNECTION_LIMIT_EXCEEDED: + return State::CONNECTION_LIMIT_EXCEEDED; + case ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED: + return State::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED; + case ErrorCode::CONNECTION_REJECTED_SECURITY_REASONS: + return State::CONNECTION_REJECTED_SECURITY_REASONS; + case ErrorCode::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR: + return State::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR; + case ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE: + return State::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; + case ErrorCode::INVALID_HCI_COMMAND_PARAMETERS: + return State::INVALID_HCI_COMMAND_PARAMETERS; + case ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST: + return State::CONNECTION_TERMINATED_BY_LOCAL_HOST; + case ErrorCode::UNSUPPORTED_REMOTE_OR_LMP_FEATURE: + return State::UNSUPPORTED_REMOTE_OR_LMP_FEATURE; + case ErrorCode::SCO_OFFSET_REJECTED: + return State::SCO_OFFSET_REJECTED; + case ErrorCode::SCO_INTERVAL_REJECTED: + return State::SCO_INTERVAL_REJECTED; + case ErrorCode::SCO_AIR_MODE_REJECTED: + return State::SCO_AIR_MODE_REJECTED; + case ErrorCode::INVALID_LMP_OR_LL_PARAMETERS: + return State::INVALID_LMP_OR_LL_PARAMETERS; + case ErrorCode::UNSPECIFIED_ERROR: + return State::UNSPECIFIED_ERROR; + case ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER: + return State::UNSUPPORTED_LMP_OR_LL_PARAMETER; + case ErrorCode::ROLE_CHANGE_NOT_ALLOWED: + return State::ROLE_CHANGE_NOT_ALLOWED; + case ErrorCode::LINK_LAYER_COLLISION: + return State::LINK_LAYER_COLLISION; + case ErrorCode::LMP_PDU_NOT_ALLOWED: + return State::LMP_PDU_NOT_ALLOWED; + case ErrorCode::ENCRYPTION_MODE_NOT_ACCEPTABLE: + return State::ENCRYPTION_MODE_NOT_ACCEPTABLE; + case ErrorCode::LINK_KEY_CANNOT_BE_CHANGED: + return State::LINK_KEY_CANNOT_BE_CHANGED; + case ErrorCode::REQUESTED_QOS_NOT_SUPPORTED: + return State::REQUESTED_QOS_NOT_SUPPORTED; + case ErrorCode::INSTANT_PASSED: + return State::INSTANT_PASSED; + case ErrorCode::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED: + return State::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED; + case ErrorCode::DIFFERENT_TRANSACTION_COLLISION: + return State::DIFFERENT_TRANSACTION_COLLISION; + case ErrorCode::QOS_UNACCEPTABLE_PARAMETERS: + return State::QOS_UNACCEPTABLE_PARAMETERS; + case ErrorCode::QOS_REJECTED: + return State::QOS_REJECTED; + case ErrorCode::CHANNEL_ASSESSMENT_NOT_SUPPORTED: + return State::CHANNEL_ASSESSMENT_NOT_SUPPORTED; + case ErrorCode::INSUFFICIENT_SECURITY: + return State::INSUFFICIENT_SECURITY; + case ErrorCode::PARAMETER_OUT_OF_MANDATORY_RANGE: + return State::PARAMETER_OUT_OF_MANDATORY_RANGE; + case ErrorCode::ROLE_SWITCH_PENDING: + return State::ROLE_SWITCH_PENDING; + case ErrorCode::RESERVED_SLOT_VIOLATION: + return State::RESERVED_SLOT_VIOLATION; + case ErrorCode::ROLE_SWITCH_FAILED: + return State::ROLE_SWITCH_FAILED; + case ErrorCode::EXTENDED_INQUIRY_RESPONSE_TOO_LARGE: + return State::EXTENDED_INQUIRY_RESPONSE_TOO_LARGE; + case ErrorCode::SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST: + return State::SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST; + case ErrorCode::HOST_BUSY_PAIRING: + return State::HOST_BUSY_PAIRING; + case ErrorCode::CONNECTION_REJECTED_NO_SUITABLE_CHANNEL_FOUND: + return State::CONNECTION_REJECTED_NO_SUITABLE_CHANNEL_FOUND; + case ErrorCode::CONTROLLER_BUSY: + return State::CONTROLLER_BUSY; + case ErrorCode::UNACCEPTABLE_CONNECTION_PARAMETERS: + return State::UNACCEPTABLE_CONNECTION_PARAMETERS; + case ErrorCode::ADVERTISING_TIMEOUT: + return State::ADVERTISING_TIMEOUT; + case ErrorCode::CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE: + return State::CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE; + case ErrorCode::CONNECTION_FAILED_ESTABLISHMENT: + return State::CONNECTION_FAILED_ESTABLISHMENT; + case ErrorCode::COARSE_CLOCK_ADJUSTMENT_REJECTED: + return State::COARSE_CLOCK_ADJUSTMENT_REJECTED; + case ErrorCode::TYPE0_SUBMAP_NOT_DEFINED: + return State::TYPE0_SUBMAP_NOT_DEFINED; + case ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER: + return State::UNKNOWN_ADVERTISING_IDENTIFIER; + case ErrorCode::LIMIT_REACHED: + return State::LIMIT_REACHED; + case ErrorCode::OPERATION_CANCELLED_BY_HOST: + return State::OPERATION_CANCELLED_BY_HOST; + case ErrorCode::PACKET_TOO_LONG: + return State::PACKET_TOO_LONG; default: return State::STATE_UNKNOWN; } -- GitLab From f20739b3d64e40070cd5c40874be39a1dbfdcd3e Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 5 Nov 2024 16:03:45 -0800 Subject: [PATCH 577/875] btif_av: Move callback declarations from hardware/bt_av.h to btif_av.h Bug: 331817295 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I7eb96c5ae448949b0f4ded2cae5e6a860511d784 --- system/btif/include/btif_av.h | 53 +++++++++++++++++++++++++++++++++ system/include/hardware/bt_av.h | 53 --------------------------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/system/btif/include/btif_av.h b/system/btif/include/btif_av.h index ca04f2c4f22..051e8e40b47 100644 --- a/system/btif/include/btif_av.h +++ b/system/btif/include/btif_av.h @@ -30,6 +30,59 @@ #include "include/hardware/bt_av.h" #include "types/raw_address.h" +/** Callback for connection state change. + * state will have one of the values from btav_connection_state_t + */ +typedef void (*btav_connection_state_callback)(const RawAddress& bd_addr, + btav_connection_state_t state, + const btav_error_t& error); + +/** Callback for audiopath state change. + * state will have one of the values from btav_audio_state_t + */ +typedef void (*btav_audio_state_callback)(const RawAddress& bd_addr, btav_audio_state_t state); + +/** Callback for audio configuration change. + * Used only for the A2DP Source interface. + */ +typedef void (*btav_audio_source_config_callback)( + const RawAddress& bd_addr, btav_a2dp_codec_config_t codec_config, + std::vector codecs_local_capabilities, + std::vector codecs_selectable_capabilities); + +/** Callback for audio configuration change. + * Used only for the A2DP Sink interface. + * sample_rate: sample rate in Hz + * channel_count: number of channels (1 for mono, 2 for stereo) + */ +typedef void (*btav_audio_sink_config_callback)(const RawAddress& bd_addr, uint32_t sample_rate, + uint8_t channel_count); + +/** Callback for querying whether the mandatory codec is more preferred. + * Used only for the A2DP Source interface. + * Return true if optional codecs are not preferred. + */ +typedef bool (*btav_mandatory_codec_preferred_callback)(const RawAddress& bd_addr); + +/** BT-AV A2DP Source callback structure. */ +typedef struct { + /** set to sizeof(btav_source_callbacks_t) */ + size_t size; + btav_connection_state_callback connection_state_cb; + btav_audio_state_callback audio_state_cb; + btav_audio_source_config_callback audio_config_cb; + btav_mandatory_codec_preferred_callback mandatory_codec_preferred_cb; +} btav_source_callbacks_t; + +/** BT-AV A2DP Sink callback structure. */ +typedef struct { + /** set to sizeof(btav_sink_callbacks_t) */ + size_t size; + btav_connection_state_callback connection_state_cb; + btav_audio_state_callback audio_state_cb; + btav_audio_sink_config_callback audio_config_cb; +} btav_sink_callbacks_t; + /* Interface methods for the A2DP source stack. */ bt_status_t btif_av_source_init(btav_source_callbacks_t* callbacks, int max_connected_audio_devices, diff --git a/system/include/hardware/bt_av.h b/system/include/hardware/bt_av.h index df4b18c5750..b83db16f64f 100644 --- a/system/include/hardware/bt_av.h +++ b/system/include/hardware/bt_av.h @@ -272,59 +272,6 @@ typedef struct { std::optional error_msg; } btav_error_t; -/** Callback for connection state change. - * state will have one of the values from btav_connection_state_t - */ -typedef void (*btav_connection_state_callback)(const RawAddress& bd_addr, - btav_connection_state_t state, - const btav_error_t& error); - -/** Callback for audiopath state change. - * state will have one of the values from btav_audio_state_t - */ -typedef void (*btav_audio_state_callback)(const RawAddress& bd_addr, btav_audio_state_t state); - -/** Callback for audio configuration change. - * Used only for the A2DP Source interface. - */ -typedef void (*btav_audio_source_config_callback)( - const RawAddress& bd_addr, btav_a2dp_codec_config_t codec_config, - std::vector codecs_local_capabilities, - std::vector codecs_selectable_capabilities); - -/** Callback for audio configuration change. - * Used only for the A2DP Sink interface. - * sample_rate: sample rate in Hz - * channel_count: number of channels (1 for mono, 2 for stereo) - */ -typedef void (*btav_audio_sink_config_callback)(const RawAddress& bd_addr, uint32_t sample_rate, - uint8_t channel_count); - -/** Callback for querying whether the mandatory codec is more preferred. - * Used only for the A2DP Source interface. - * Return true if optional codecs are not preferred. - */ -typedef bool (*btav_mandatory_codec_preferred_callback)(const RawAddress& bd_addr); - -/** BT-AV A2DP Source callback structure. */ -typedef struct { - /** set to sizeof(btav_source_callbacks_t) */ - size_t size; - btav_connection_state_callback connection_state_cb; - btav_audio_state_callback audio_state_cb; - btav_audio_source_config_callback audio_config_cb; - btav_mandatory_codec_preferred_callback mandatory_codec_preferred_cb; -} btav_source_callbacks_t; - -/** BT-AV A2DP Sink callback structure. */ -typedef struct { - /** set to sizeof(btav_sink_callbacks_t) */ - size_t size; - btav_connection_state_callback connection_state_cb; - btav_audio_state_callback audio_state_cb; - btav_audio_sink_config_callback audio_config_cb; -} btav_sink_callbacks_t; - /** * NOTE: * -- GitLab From 00555617ddbbc1a19089104c084d14f465c971ce Mon Sep 17 00:00:00 2001 From: Brian Delwiche Date: Sat, 2 Nov 2024 02:29:10 +0000 Subject: [PATCH 578/875] Fix more memory-unsafe logging In various locations around the stack, log statements use structures that may, in exceptional cases, have been freed by preceding calls. This can lead to use after free and potentially to security vulnerabilities. Use local variables instead, or store the length before the call if no local variable is already convenient. Bug: 375404242 Bug: 375398779 Bug: 375397720 Bug: 375397164 Bug: 375397370 Bug: 375396810 Bug: 375159652 Bug: 375160214 Bug: 375159480 Test: m libbluetooth Test: researcher POC Flag: EXEMPT trivial logic fix Ignore-AOSP-First: security Tag: #security Change-Id: Ia50e074de751661a0e617bfffa17871497b8d1ea --- system/stack/avct/avct_lcb_act.cc | 5 ++++- system/stack/bnep/bnep_main.cc | 4 +++- system/stack/bnep/bnep_utils.cc | 3 ++- system/stack/hid/hidd_conn.cc | 4 ++-- system/stack/rfcomm/rfc_ts_frames.cc | 3 ++- system/stack/rfcomm/rfc_utils.cc | 3 ++- system/stack/sdp/sdp_discovery.cc | 2 +- system/stack/sdp/sdp_server.cc | 4 ++-- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/system/stack/avct/avct_lcb_act.cc b/system/stack/avct/avct_lcb_act.cc index 986bce7d34b..32da9d865b5 100644 --- a/system/stack/avct/avct_lcb_act.cc +++ b/system/stack/avct/avct_lcb_act.cc @@ -727,10 +727,13 @@ void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) { p = (uint8_t*)(p_buf + 1) + p_buf->offset; AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ); UINT16_TO_BE_STREAM(p, pid); + + uint16_t len = p_buf->len; + if (stack::l2cap::get_interface().L2CA_DataWrite(p_lcb->ch_lcid, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} lcid:0x{:04x} len:{}", p_lcb->peer_addr, - p_lcb->ch_lcid, p_buf->len); + p_lcb->ch_lcid, len); } } } diff --git a/system/stack/bnep/bnep_main.cc b/system/stack/bnep/bnep_main.cc index e0e3c4540c3..adf3c8666e6 100644 --- a/system/stack/bnep/bnep_main.cc +++ b/system/stack/bnep/bnep_main.cc @@ -295,10 +295,12 @@ static void bnep_congestion_ind(uint16_t l2cap_cid, bool is_congested) { break; } + uint16_t len = p_buf->len; + if (stack::l2cap::get_interface().L2CA_DataWrite(l2cap_cid, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_bcb->rem_bda, l2cap_cid, - p_buf->len); + len); } } } diff --git a/system/stack/bnep/bnep_utils.cc b/system/stack/bnep/bnep_utils.cc index 252facf668f..4092d9afee3 100644 --- a/system/stack/bnep/bnep_utils.cc +++ b/system/stack/bnep/bnep_utils.cc @@ -411,10 +411,11 @@ void bnepu_check_send_packet(tBNEP_CONN* p_bcb, BT_HDR* p_buf) { fixed_queue_enqueue(p_bcb->xmit_q, p_buf); } } else { + uint16_t len = p_buf->len; if (stack::l2cap::get_interface().L2CA_DataWrite(p_bcb->l2cap_cid, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_bcb->rem_bda, - p_bcb->l2cap_cid, p_buf->len); + p_bcb->l2cap_cid, len); } } } diff --git a/system/stack/hid/hidd_conn.cc b/system/stack/hid/hidd_conn.cc index c64a7b91042..695e5d6c843 100644 --- a/system/stack/hid/hidd_conn.cc +++ b/system/stack/hid/hidd_conn.cc @@ -88,10 +88,10 @@ static void hidd_check_config_done() { // send outstanding data on intr if (hd_cb.pending_data) { + uint16_t len = hd_cb.pending_data->len; if (stack::l2cap::get_interface().L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data) != tL2CAP_DW_RESULT::SUCCESS) { - log::warn("Unable to write L2CAP data cid:{} len:{}", p_hcon->intr_cid, - hd_cb.pending_data->len); + log::warn("Unable to write L2CAP data cid:{} len:{}", p_hcon->intr_cid, len); } hd_cb.pending_data = NULL; } diff --git a/system/stack/rfcomm/rfc_ts_frames.cc b/system/stack/rfcomm/rfc_ts_frames.cc index ea57abf6dc2..e93cfed9b8a 100644 --- a/system/stack/rfcomm/rfc_ts_frames.cc +++ b/system/stack/rfcomm/rfc_ts_frames.cc @@ -201,10 +201,11 @@ void rfc_send_buf_uih(tRFC_MCB* p_mcb, uint8_t dlci, BT_HDR* p_buf) { if (dlci == RFCOMM_MX_DLCI) { rfc_check_send_cmd(p_mcb, p_buf); } else { + uint16_t len = p_buf->len; if (stack::l2cap::get_interface().L2CA_DataWrite(p_mcb->lcid, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_mcb->bd_addr, p_mcb->lcid, - p_buf->len); + len); } } } diff --git a/system/stack/rfcomm/rfc_utils.cc b/system/stack/rfcomm/rfc_utils.cc index 23420892cbf..0c5074db767 100644 --- a/system/stack/rfcomm/rfc_utils.cc +++ b/system/stack/rfcomm/rfc_utils.cc @@ -428,9 +428,10 @@ void rfc_check_send_cmd(tRFC_MCB* p_mcb, BT_HDR* p_buf) { if (p == NULL) { break; } + uint16_t len = p->len; if (stack::l2cap::get_interface().L2CA_DataWrite(p_mcb->lcid, p) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_mcb->bd_addr, p_mcb->lcid, - p->len); + len); } } } diff --git a/system/stack/sdp/sdp_discovery.cc b/system/stack/sdp/sdp_discovery.cc index 4fa484e14a4..6aba1993aff 100644 --- a/system/stack/sdp/sdp_discovery.cc +++ b/system/stack/sdp/sdp_discovery.cc @@ -877,7 +877,7 @@ static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, uint8_t* if (stack::l2cap::get_interface().L2CA_DataWrite(p_ccb->connection_id, p_msg) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_ccb->device_address, - p_ccb->connection_id, p_msg->len); + p_ccb->connection_id, p - p_start); } /* Start inactivity timer */ diff --git a/system/stack/sdp/sdp_server.cc b/system/stack/sdp/sdp_server.cc index abd70aedb16..0f379708e92 100644 --- a/system/stack/sdp/sdp_server.cc +++ b/system/stack/sdp/sdp_server.cc @@ -300,7 +300,7 @@ static void process_service_search(tCONN_CB* p_ccb, uint16_t trans_num, uint16_t if (stack::l2cap::get_interface().L2CA_DataWrite(p_ccb->connection_id, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_ccb->device_address, - p_ccb->connection_id, p_buf->len); + p_ccb->connection_id, p_rsp - p_rsp_start); } } @@ -564,7 +564,7 @@ static void process_service_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, uint16 if (stack::l2cap::get_interface().L2CA_DataWrite(p_ccb->connection_id, p_buf) != tL2CAP_DW_RESULT::SUCCESS) { log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_ccb->device_address, - p_ccb->connection_id, p_buf->len); + p_ccb->connection_id, p_rsp - p_rsp_start); } } -- GitLab From 9c1965c4ee067cf53698fee27fe4893d7637d474 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 5 Nov 2024 17:01:59 -0800 Subject: [PATCH 579/875] blueberry/tests: Remove sl4a_sl4a and gd_sl4a tests Bug: 333555245 Test: None Flag: EXEMPT, dead code removal Change-Id: I2dc2a537a5b9f2146039c22258edad7f95453d0d --- .../sl4a_sl4a/advertising/le_advertising.py | 62 -- .../tests/sl4a_sl4a/gatt/gatt_connect_test.py | 970 ------------------ .../gatt/gatt_connect_with_irk_test.py | 148 --- .../tests/sl4a_sl4a/gatt/gatt_notify_test.py | 98 -- .../sl4a_sl4a/l2cap/le_l2cap_coc_test.py | 169 --- .../sl4a_sl4a/lib/gatt_connected_base_test.py | 189 ---- system/blueberry/tests/sl4a_sl4a/lib/l2cap.py | 70 -- .../tests/sl4a_sl4a/lib/le_advertiser.py | 82 -- .../tests/sl4a_sl4a/lib/le_scanner.py | 173 ---- .../blueberry/tests/sl4a_sl4a/lib/oob_data.py | 52 - .../blueberry/tests/sl4a_sl4a/lib/security.py | 142 --- .../sl4a_sl4a/lib/sl4a_sl4a_base_test.py | 189 ---- .../tests/sl4a_sl4a/scanning/le_scanning.py | 96 -- .../sl4a_sl4a/security/irk_rotation_test.py | 173 ---- .../sl4a_sl4a/security/oob_pairing_test.py | 174 ---- .../sl4a_sl4a/sl4a_sl4a_device_config.yaml | 20 - .../tests/sl4a_sl4a/sl4a_sl4a_test_runner.py | 79 -- system/blueberry/utils/bt_gatt_utils.py | 22 - system/blueberry/utils/bt_test_utils.py | 73 -- system/blueberry/utils/mobly_sl4a_utils.py | 89 -- system/gd/cert/run | 18 - 21 files changed, 3088 deletions(-) delete mode 100644 system/blueberry/tests/sl4a_sl4a/advertising/le_advertising.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_with_irk_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/gatt/gatt_notify_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/l2cap/le_l2cap_coc_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/lib/gatt_connected_base_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/lib/l2cap.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/lib/le_advertiser.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/lib/le_scanner.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/lib/oob_data.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/lib/security.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/scanning/le_scanning.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/security/irk_rotation_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/security/oob_pairing_test.py delete mode 100644 system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_device_config.yaml delete mode 100644 system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py delete mode 100644 system/blueberry/utils/mobly_sl4a_utils.py diff --git a/system/blueberry/tests/sl4a_sl4a/advertising/le_advertising.py b/system/blueberry/tests/sl4a_sl4a/advertising/le_advertising.py deleted file mode 100644 index 90fd1e0e353..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/advertising/le_advertising.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import binascii -import io -import logging -import os -import queue - -from blueberry.tests.gd.cert.context import get_current_context - -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_address_types -from mobly import test_runner - - -class LeAdvertisingTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass): - - def setup_class(self): - super().setup_class() - - def setup_test(self): - super().setup_test() - - def teardown_test(self): - super().teardown_test() - - def test_advertise_name(self): - rpa_address = self.cert_advertiser_.advertise_public_extended_pdu() - self.dut_scanner_.scan_for_name(self.cert_advertiser_.get_local_advertising_name()) - self.dut_scanner_.stop_scanning() - self.cert_advertiser_.stop_advertising() - - def test_advertise_name_stress(self): - for i in range(0, 10): - self.test_advertise_name() - - def test_advertise_name_twice_no_stop(self): - rpa_address = self.cert_advertiser_.advertise_public_extended_pdu() - self.dut_scanner_.scan_for_name(self.cert_advertiser_.get_local_advertising_name()) - self.dut_scanner_.stop_scanning() - rpa_address = self.cert_advertiser_.advertise_public_extended_pdu() - self.dut_scanner_.scan_for_name(self.cert_advertiser_.get_local_advertising_name()) - self.dut_scanner_.stop_scanning() - self.cert_advertiser_.stop_advertising() - - -if __name__ == '__main__': - test_runner.main() diff --git a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py b/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py deleted file mode 100644 index 2fc1025e7d6..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py +++ /dev/null @@ -1,970 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2016 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. -""" -This test script exercises different GATT connection tests. - -Original location: - tools/test/connectivity/acts_tests/tests/google/ble/gatt/GattConnectTest.py -""" - -import logging -import time -from queue import Empty - -from blueberry.tests.gd.cert.test_decorators import test_tracker_info -from blueberry.tests.gd_sl4a.lib.bt_constants import scan_result -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test -from blueberry.utils.ble_scan_adv_constants import BleAdvertiseSettingsMode -from blueberry.utils.ble_scan_adv_constants import BleScanSettingsMatchNums -from blueberry.utils.ble_scan_adv_constants import BleScanSettingsModes -from blueberry.utils.bt_constants import BluetoothProfile -from blueberry.utils.bt_gatt_constants import GattCallbackError -from blueberry.utils.bt_gatt_constants import GattCallbackString -from blueberry.utils.bt_gatt_constants import GattCharacteristic -from blueberry.utils.bt_gatt_constants import GattConnectionState -from blueberry.utils.bt_gatt_constants import GattMtuSize -from blueberry.utils.bt_gatt_constants import GattPhyMask -from blueberry.utils.bt_gatt_constants import GattServiceType -from blueberry.utils.bt_gatt_constants import GattTransport -from blueberry.utils.bt_gatt_utils import GattTestUtilsError -from blueberry.utils.bt_gatt_utils import close_gatt_client -from blueberry.utils.bt_gatt_utils import disconnect_gatt_connection -from blueberry.utils.bt_gatt_utils import get_mac_address_of_generic_advertisement -from blueberry.utils.bt_gatt_utils import log_gatt_server_uuids -from blueberry.utils.bt_gatt_utils import orchestrate_gatt_connection -from blueberry.utils.bt_gatt_utils import setup_gatt_connection -from blueberry.utils.bt_gatt_utils import setup_multiple_services -from blueberry.utils.bt_gatt_utils import wait_for_gatt_disconnect_event -from blueberry.utils.bt_test_utils import clear_bonded_devices -from blueberry.tests.gd.cert.truth import assertThat -from mobly import asserts -from mobly import test_runner - -PHYSICAL_DISCONNECT_TIMEOUT = 5 - - -class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass): - adv_instances = [] - bluetooth_gatt_list = [] - gatt_server_list = [] - default_timeout = 10 - default_discovery_timeout = 3 - - ADDR_TYPE_PUBLIC = 0 - ADDR_TYPE_RPA = 1 - ADDR_TYPE_NRPA = 2 - - def setup_class(self): - super().setup_class() - self.central = self.dut - self.peripheral = self.cert - - def setup_test(self): - super().setup_test() - bluetooth_gatt_list = [] - self.gatt_server_list = [] - self.adv_instances = [] - # Ensure there is ample time for a physical disconnect in between - # testcases. - logging.info("Waiting for {} seconds for physical GATT disconnections".format(PHYSICAL_DISCONNECT_TIMEOUT)) - time.sleep(PHYSICAL_DISCONNECT_TIMEOUT) - - def teardown_test(self): - for bluetooth_gatt in self.bluetooth_gatt_list: - self.central.sl4a.gattClientClose(bluetooth_gatt) - for gatt_server in self.gatt_server_list: - self.peripheral.sl4a.gattServerClose(gatt_server) - for adv in self.adv_instances: - self.peripheral.sl4a.bleStopBleAdvertising(adv) - super().teardown_test() - return True - - def _orchestrate_gatt_disconnection(self, bluetooth_gatt, gatt_callback): - logging.info("Disconnecting from peripheral device.") - try: - disconnect_gatt_connection(self.central, bluetooth_gatt, gatt_callback) - logging.info("Disconnected GATT, closing GATT client.") - close_gatt_client(self.central, bluetooth_gatt) - logging.info("Closed GATT client, removing it from local tracker.") - if bluetooth_gatt in self.bluetooth_gatt_list: - self.bluetooth_gatt_list.remove(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - return False - return True - - def _find_service_added_event(self, gatt_server_cb, uuid): - expected_event = GattCallbackString.SERV_ADDED.format(gatt_server_cb) - try: - event = self.peripheral.ed.pop_event(expected_event, self.default_timeout) - except Empty: - logging.error(GattCallbackError.SERV_ADDED_ERR.format(expected_event)) - return False - if event['data']['serviceUuid'].lower() != uuid.lower(): - logging.error("Uuid mismatch. Found: {}, Expected {}.".format(event['data']['serviceUuid'], uuid)) - return False - return True - - def _verify_mtu_changed_on_client_and_server(self, expected_mtu, gatt_callback, gatt_server_callback): - expected_event = GattCallbackString.MTU_CHANGED.format(gatt_callback) - try: - mtu_event = self.central.ed.pop_event(expected_event, self.default_timeout) - mtu_size_found = mtu_event['data']['MTU'] - if mtu_size_found != expected_mtu: - logging.error("MTU size found: {}, expected: {}".format(mtu_size_found, expected_mtu)) - return False - except Empty: - logging.error(GattCallbackError.MTU_CHANGED_ERR.format(expected_event)) - return False - - expected_event = GattCallbackString.MTU_SERV_CHANGED.format(gatt_server_callback) - try: - mtu_event = self.peripheral.ed.pop_event(expected_event, self.default_timeout) - mtu_size_found = mtu_event['data']['MTU'] - if mtu_size_found != expected_mtu: - logging.error("MTU size found: {}, expected: {}".format(mtu_size_found, expected_mtu)) - return False - except Empty: - logging.error(GattCallbackError.MTU_SERV_CHANGED_ERR.format(expected_event)) - return False - return True - - @test_tracker_info(uuid='8a3530a3-c8bb-466b-9710-99e694c38618') - def test_gatt_connect(self): - """Test GATT connection over LE. - - Test establishing a gatt connection between a GATT server and GATT - client. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was established and then disconnected - successfully. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT - Priority: 0 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.adv_instances.append(adv_callback) - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='a839b505-03ac-4783-be7e-1d43129a1948') - def test_gatt_connect_stop_advertising(self): - """Test GATT connection over LE then stop advertising - - A test case that verifies the GATT connection doesn't - disconnect when LE advertisement is stopped. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. Stop the advertiser. - 7. Verify no connection state changed happened. - 8. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was established and not disconnected - when advertisement stops. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT - Priority: 0 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.peripheral.sl4a.bleStopBleAdvertising(adv_callback) - try: - event = self.central.ed.pop_event( - GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback, self.default_timeout)) - logging.error("Connection event found when not expected: {}".format(event)) - asserts.fail("Connection event found when not expected: {}".format(event)) - return - except Empty: - logging.info("No connection state change as expected") - try: - self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback) - except Exception as err: - logging.info("Failed to orchestrate disconnect: {}".format(err)) - asserts.fail("Failed to orchestrate disconnect: {}".format(err)) - return - - @test_tracker_info(uuid='b82f91a8-54bb-4779-a117-73dc7fdb28cc') - def test_gatt_connect_autoconnect(self): - """Test GATT connection over LE. - - Test re-establishing a gatt connection using autoconnect - set to True in order to test connection allowlist. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. Disconnect the GATT connection. - 7. Create a GATT connection with autoconnect set to True - 8. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was re-established and then disconnected - successfully. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT - Priority: 0 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.peripheral.log.info("Opened GATT server on CERT, scanning it from DUT") - self.gatt_server_list.append(gatt_server) - autoconnect = False - mac_address, adv_callback, scan_callback = (get_mac_address_of_generic_advertisement( - self.central, self.peripheral, self.ADDR_TYPE_PUBLIC)) - self.adv_instances.append(adv_callback) - self.central.log.info("Discovered BLE advertisement, connecting GATT with autoConnect={}".format(autoconnect)) - try: - bluetooth_gatt, gatt_callback = setup_gatt_connection(self.central, mac_address, autoconnect) - self.central.log.info("GATT connected, stopping BLE scanning") - self.central.sl4a.bleStopBleScan(scan_callback) - self.central.log.info("Stopped BLE scanning") - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.central.log.info("Disconnecting GATT") - try: - disconnect_gatt_connection(self.central, bluetooth_gatt, gatt_callback) - self.central.log.info("GATT disconnected, closing GATT client") - close_gatt_client(self.central, bluetooth_gatt) - self.central.log.info("GATT client closed, removing it from in-memory tracker") - if bluetooth_gatt in self.bluetooth_gatt_list: - self.bluetooth_gatt_list.remove(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to disconnect GATT, error: {}".format(err)) - return - autoconnect = True - self.central.log.info("Connecting GATT with autoConnect={}".format(autoconnect)) - bluetooth_gatt = self.central.sl4a.gattClientConnectGatt(gatt_callback, mac_address, autoconnect, - GattTransport.TRANSPORT_LE, False, - GattPhyMask.PHY_LE_1M_MASK) - self.central.log.info("Waiting for GATt to become connected") - self.bluetooth_gatt_list.append(bluetooth_gatt) - expected_event = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback) - try: - event = self.central.ed.pop_event(expected_event, self.default_timeout) - self.central.log.info("Received event={}".format(event)) - except Empty: - logging.error(GattCallbackError.GATT_CONN_CHANGE_ERR.format(expected_event)) - asserts.fail(GattCallbackError.GATT_CONN_CHANGE_ERR.format(expected_event)) - return - found_state = event['data']['State'] - expected_state = GattConnectionState.STATE_CONNECTED - assertThat(found_state).isEqualTo(expected_state) - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='e506fa50-7cd9-4bd8-938a-6b85dcfe6bc6') - def test_gatt_connect_opportunistic(self): - """Test opportunistic GATT connection over LE. - - Test establishing a gatt connection between a GATT server and GATT - client in opportunistic mode. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create GATT connection 1 between the scanner and advertiser normally - 6. Create GATT connection 2 between the scanner and advertiser using - opportunistic mode - 7. Disconnect GATT connection 1 - - Expected Result: - Verify GATT connection 2 automatically disconnects when GATT connection - 1 disconnect - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT - Priority: 0 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - mac_address, adv_callback, scan_callback = (get_mac_address_of_generic_advertisement( - self.central, self.peripheral)) - # Make GATT connection 1 - try: - bluetooth_gatt_1, gatt_callback_1 = setup_gatt_connection(self.central, - mac_address, - False, - transport=GattTransport.TRANSPORT_AUTO, - opportunistic=False) - self.central.sl4a.bleStopBleScan(scan_callback) - self.adv_instances.append(adv_callback) - self.bluetooth_gatt_list.append(bluetooth_gatt_1) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT 1, error: {}".format(err)) - return - # Make GATT connection 2 - try: - bluetooth_gatt_2, gatt_callback_2 = setup_gatt_connection(self.central, - mac_address, - False, - transport=GattTransport.TRANSPORT_AUTO, - opportunistic=True) - self.bluetooth_gatt_list.append(bluetooth_gatt_2) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT 2, error: {}".format(err)) - return - # Disconnect GATT connection 1 - try: - disconnect_gatt_connection(self.central, bluetooth_gatt_1, gatt_callback_1) - close_gatt_client(self.central, bluetooth_gatt_1) - if bluetooth_gatt_1 in self.bluetooth_gatt_list: - self.bluetooth_gatt_list.remove(bluetooth_gatt_1) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to disconnect GATT 1, error: {}".format(err)) - return - # Confirm that GATT connection 2 also disconnects - wait_for_gatt_disconnect_event(self.central, gatt_callback_2) - close_gatt_client(self.central, bluetooth_gatt_2) - if bluetooth_gatt_2 in self.bluetooth_gatt_list: - self.bluetooth_gatt_list.remove(bluetooth_gatt_2) - - @test_tracker_info(uuid='4416d483-dec3-46cb-8038-4d82620f873a') - def test_gatt_request_out_of_bounds_mtu(self): - """Test GATT connection over LE and exercise an out of bound MTU size. - - Test establishing a gatt connection between a GATT server and GATT - client. Request an MTU size that is the MIN value minus 1. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. From the scanner (client) request MTU size change to the - minimum value minus one. - 7. Find the MTU changed event on the client. - 8. Disconnect the GATT connection. - - Expected Result: - Verify that an MTU changed event was not discovered and that - it didn't cause an exception when requesting an out of bounds - MTU. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT, MTU - Priority: 0 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.adv_instances.append(adv_callback) - unexpected_mtu = GattMtuSize.MIN - 1 - self.central.sl4a.gattClientRequestMtu(bluetooth_gatt, unexpected_mtu) - assertThat(self._verify_mtu_changed_on_client_and_server(unexpected_mtu, gatt_callback, - gatt_server_cb)).isFalse() - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='31ffb9ca-cc75-43fb-9802-c19f1c5856b6') - def test_gatt_connect_trigger_on_read_rssi(self): - """Test GATT connection over LE read RSSI. - - Test establishing a gatt connection between a GATT server and GATT - client then read the RSSI. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. From the scanner, request to read the RSSI of the advertiser. - 7. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was established and then disconnected - successfully. Verify that the RSSI was ready correctly. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT, RSSI - Priority: 1 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.adv_instances.append(adv_callback) - expected_event = GattCallbackString.RD_REMOTE_RSSI.format(gatt_callback) - if self.central.sl4a.gattClientReadRSSI(bluetooth_gatt): - try: - self.central.ed.pop_event(expected_event, self.default_timeout) - except Empty: - logging.error(GattCallbackError.RD_REMOTE_RSSI_ERR.format(expected_event)) - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='dee9ef28-b872-428a-821b-cc62f27ba936') - def test_gatt_connect_trigger_on_services_discovered(self): - """Test GATT connection and discover services of peripheral. - - Test establishing a gatt connection between a GATT server and GATT - client the discover all services from the connected device. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. From the scanner (central device), discover services. - 7. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was established and then disconnected - successfully. Verify that the service were discovered. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT, Services - Priority: 1 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.adv_instances.append(adv_callback) - if self.central.sl4a.gattClientDiscoverServices(bluetooth_gatt): - expected_event = GattCallbackString.GATT_SERV_DISC.format(gatt_callback) - try: - event = self.central.ed.pop_event(expected_event, self.default_timeout) - except Empty: - logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - return - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='01883bdd-0cf8-48fb-bf15-467bbd4f065b') - def test_gatt_connect_trigger_on_services_discovered_iterate_attributes(self): - """Test GATT connection and iterate peripherals attributes. - - Test establishing a gatt connection between a GATT server and GATT - client and iterate over all the characteristics and descriptors of the - discovered services. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. From the scanner (central device), discover services. - 7. Iterate over all the characteristics and descriptors of the - discovered features. - 8. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was established and then disconnected - successfully. Verify that the services, characteristics, and descriptors - were discovered. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT, Services - Characteristics, Descriptors - Priority: 1 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.adv_instances.append(adv_callback) - if self.central.sl4a.gattClientDiscoverServices(bluetooth_gatt): - expected_event = GattCallbackString.GATT_SERV_DISC.format(gatt_callback) - try: - event = self.central.ed.pop_event(expected_event, self.default_timeout) - discovered_services_index = event['data']['ServicesIndex'] - except Empty: - logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - return - log_gatt_server_uuids(self.central, discovered_services_index) - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='d4277bee-da99-4f48-8a4d-f81b5389da18') - def test_gatt_connect_with_service_uuid_variations(self): - """Test GATT connection with multiple service uuids. - - Test establishing a gatt connection between a GATT server and GATT - client with multiple service uuid variations. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. From the scanner (central device), discover services. - 7. Verify that all the service uuid variations are found. - 8. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was established and then disconnected - successfully. Verify that the service uuid variations are found. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT, Services - Priority: 2 - """ - try: - gatt_server_cb, gatt_server = setup_multiple_services(self.peripheral) - self.gatt_server_list.append(gatt_server) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to setup GATT service, error: {}".format(err)) - return - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - self.adv_instances.append(adv_callback) - if self.central.sl4a.gattClientDiscoverServices(bluetooth_gatt): - expected_event = GattCallbackString.GATT_SERV_DISC.format(gatt_callback) - try: - event = self.central.ed.pop_event(expected_event, self.default_timeout) - except Empty: - logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - return - discovered_services_index = event['data']['ServicesIndex'] - log_gatt_server_uuids(self.central, discovered_services_index) - - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='7d3442c5-f71f-44ae-bd35-f2569f01b3b8') - def test_gatt_connect_in_quick_succession(self): - """Test GATT connections multiple times. - - Test establishing a gatt connection between a GATT server and GATT - client with multiple iterations. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 6. Disconnect the GATT connection. - 7. Repeat steps 5 and 6 twenty times. - - Expected Result: - Verify that a connection was established and then disconnected - successfully twenty times. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT, Stress - Priority: 1 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - mac_address, adv_callback, scan_callback = get_mac_address_of_generic_advertisement( - self.central, self.peripheral) - autoconnect = False - for i in range(100): - logging.info("Starting connection iteration {}".format(i + 1)) - try: - bluetooth_gatt, gatt_callback = setup_gatt_connection(self.central, mac_address, autoconnect) - self.central.sl4a.bleStopBleScan(scan_callback) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT at iteration {}, error: {}".format(i + 1, err)) - return - test_result = self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback) - if not test_result: - logging.info("Failed to disconnect from peripheral device.") - asserts.fail("Failed to disconnect from peripheral device.") - return - self.adv_instances.append(adv_callback) - - @test_tracker_info(uuid='148469d9-7ab0-4c08-b2e9-7e49e88da1fc') - def test_gatt_connect_on_path_attack(self): - """Test GATT connection with permission write encrypted with on-path attacker prevention - - Test establishing a gatt connection between a GATT server and GATT - client while the GATT server's characteristic includes the property - write value and the permission write encrypted on-path attacker prevention - value. This will prompt LE pairing and then the devices will create a bond. - - Steps: - 1. Create a GATT server and server callback on the peripheral device. - 2. Create a unique service and characteristic uuid on the peripheral. - 3. Create a characteristic on the peripheral with these properties: - GattCharacteristic.PROPERTY_WRITE, - GattCharacteristic.PERMISSION_WRITE_ENCRYPTED_MITM - 4. Create a GATT service on the peripheral. - 5. Add the characteristic to the GATT service. - 6. Create a GATT connection between your central and peripheral device. - 7. From the central device, discover the peripheral's services. - 8. Iterate the services found until you find the unique characteristic - created in step 3. - 9. Once found, write a random but valid value to the characteristic. - 10. Start pairing helpers on both devices immediately after attempting - to write to the characteristic. - 11. Within 10 seconds of writing the characteristic, there should be - a prompt to bond the device from the peripheral. The helpers will - handle the UI interaction automatically. (see - BluetoothConnectionFacade.java bluetoothStartPairingHelper). - 12. Verify that the two devices are bonded. - - Expected Result: - Verify that a connection was established and the devices are bonded. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Filtering, Scanning, GATT, Characteristic, OnPathAttacker - Priority: 1 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - service_uuid = "3846D7A0-69C8-11E4-BA00-0002A5D5C51B" - test_uuid = "aa7edd5a-4d1d-4f0e-883a-d145616a1630" - bonded = False - characteristic = self.peripheral.sl4a.gattServerCreateBluetoothGattCharacteristic( - test_uuid, GattCharacteristic.PROPERTY_WRITE, GattCharacteristic.PERMISSION_WRITE_ENCRYPTED_MITM) - gatt_service = self.peripheral.sl4a.gattServerCreateService(service_uuid, GattServiceType.SERVICE_TYPE_PRIMARY) - self.peripheral.sl4a.gattServerAddCharacteristicToService(gatt_service, characteristic) - self.peripheral.sl4a.gattServerAddService(gatt_server, gatt_service) - assertThat(self._find_service_added_event(gatt_server_cb, service_uuid)).isTrue() - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - self.adv_instances.append(adv_callback) - if self.central.sl4a.gattClientDiscoverServices(bluetooth_gatt): - expected_event = GattCallbackString.GATT_SERV_DISC.format(gatt_callback) - try: - event = self.central.ed.pop_event(expected_event, self.default_timeout) - except Empty: - logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event)) - return - discovered_services_index = event['data']['ServicesIndex'] - else: - logging.info("Failed to discover services.") - asserts.fail("Failed to discover services.") - return - test_value = [1, 2, 3, 4, 5, 6, 7] - services_count = self.central.sl4a.gattClientGetDiscoveredServicesCount(discovered_services_index) - for i in range(services_count): - characteristic_uuids = (self.central.sl4a.gattClientGetDiscoveredCharacteristicUuids( - discovered_services_index, i)) - for characteristic_uuid in characteristic_uuids: - if characteristic_uuid == test_uuid: - self.central.sl4a.bluetoothStartPairingHelper() - self.peripheral.sl4a.bluetoothStartPairingHelper() - self.central.sl4a.gattClientCharacteristicSetValue(bluetooth_gatt, discovered_services_index, i, - characteristic_uuid, test_value) - self.central.sl4a.gattClientWriteCharacteristic(bluetooth_gatt, discovered_services_index, i, - characteristic_uuid) - start_time = time.time() + self.default_timeout - target_name = self.peripheral.sl4a.bluetoothGetLocalName() - while time.time() < start_time and bonded == False: - bonded_devices = \ - self.central.sl4a.bluetoothGetBondedDevices() - for device in bonded_devices: - if ('name' in device.keys() and device['name'] == target_name): - bonded = True - break - bonded = False - target_name = self.central.sl4a.bluetoothGetLocalName() - while time.time() < start_time and bonded == False: - bonded_devices = \ - self.peripheral.sl4a.bluetoothGetBondedDevices() - for device in bonded_devices: - if ('name' in device.keys() and device['name'] == target_name): - bonded = True - break - - # Dual mode devices will establish connection over the classic transport, - # in order to establish bond over both transports, and do SDP. Starting - # disconnection before all this is finished is not safe, might lead to - # race conditions, i.e. bond over classic tranport shows up after LE - # bond is already removed. - time.sleep(4) - - for ad in [self.central, self.peripheral]: - assertThat(clear_bonded_devices(ad)).isTrue() - - # Necessary sleep time for entries to update unbonded state - time.sleep(2) - - for ad in [self.central, self.peripheral]: - bonded_devices = ad.sl4a.bluetoothGetBondedDevices() - if len(bonded_devices) > 0: - logging.error("Failed to unbond devices: {}".format(bonded_devices)) - asserts.fail("Failed to unbond devices: {}".format(bonded_devices)) - return - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='cc3fc361-7bf1-4ee2-9e46-4a27c88ce6a8') - def test_gatt_connect_get_connected_devices(self): - """Test GATT connections show up in getConnectedDevices - - Test establishing a gatt connection between a GATT server and GATT - client. Verify that active connections show up using - BluetoothManager.getConnectedDevices API. - - Steps: - 1. Start a generic advertisement. - 2. Start a generic scanner. - 3. Find the advertisement and extract the mac address. - 4. Stop the first scanner. - 5. Create a GATT connection between the scanner and advertiser. - 7. Verify the GATT Client has an open connection to the GATT Server. - 8. Verify the GATT Server has an open connection to the GATT Client. - 9. Disconnect the GATT connection. - - Expected Result: - Verify that a connection was established, connected devices are found - on both the central and peripheral devices, and then disconnected - successfully. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Scanning, GATT - Priority: 2 - """ - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - self.gatt_server_list.append(gatt_server) - try: - bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral)) - self.bluetooth_gatt_list.append(bluetooth_gatt) - except GattTestUtilsError as err: - logging.error(err) - asserts.fail("Failed to connect to GATT, error: {}".format(err)) - return - conn_cen_devices = self.central.sl4a.bluetoothGetConnectedLeDevices(BluetoothProfile.GATT) - conn_per_devices = self.peripheral.sl4a.bluetoothGetConnectedLeDevices(BluetoothProfile.GATT_SERVER) - target_name = self.peripheral.sl4a.bluetoothGetLocalName() - error_message = ("Connected device {} not found in list of connected " - "devices {}") - if not any(d['name'] == target_name for d in conn_cen_devices): - logging.error(error_message.format(target_name, conn_cen_devices)) - asserts.fail(error_message.format(target_name, conn_cen_devices)) - return - # For the GATT server only check the size of the list since - # it may or may not include the device name. - target_name = self.central.sl4a.bluetoothGetLocalName() - if not conn_per_devices: - logging.error(error_message.format(target_name, conn_per_devices)) - asserts.fail(error_message.format(target_name, conn_per_devices)) - return - self.adv_instances.append(adv_callback) - assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue() - - @test_tracker_info(uuid='a0a37ca6-9fa8-4d35-9fdb-0e25b4b8a363') - def test_gatt_connect_second_adv_after_canceling_first_adv(self): - """Test GATT connection to peripherals second advertising address. - - Test the ability of cancelling GATT connections and trying to reconnect - to the same device via a different address. - - Steps: - 1. A starts advertising - 2. B starts scanning and finds A's mac address - 3. Stop advertisement from step 1. Start a new advertisement on A and - find the new new mac address, B knows of both old and new address. - 4. B1 sends connect request to old address of A - 5. B1 cancel connect attempt after 10 seconds - 6. B1 sends connect request to new address of A - 7. Verify B1 establish connection to A in less than 10 seconds - - Expected Result: - Verify that a connection was established only on the second - advertisement's mac address. - - Returns: - Pass if True - Fail if False - - TAGS: LE, Advertising, Scanning, GATT - Priority: 3 - """ - autoconnect = False - transport = GattTransport.TRANSPORT_AUTO - opportunistic = False - # Setup a basic Gatt server on the peripheral - gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback() - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb) - - # Set advertisement settings to include local name in advertisement - # and set the advertising mode to low_latency. - self.peripheral.sl4a.bleSetAdvertiseSettingsIsConnectable(True) - self.peripheral.sl4a.bleSetAdvertiseDataIncludeDeviceName(True) - self.peripheral.sl4a.bleSetAdvertiseSettingsAdvertiseMode(BleAdvertiseSettingsMode.LOW_LATENCY) - - # Setup necessary advertisement objects. - advertise_data = self.peripheral.sl4a.bleBuildAdvertiseData() - advertise_settings = self.peripheral.sl4a.bleBuildAdvertiseSettings() - advertise_callback = self.peripheral.sl4a.bleGenBleAdvertiseCallback() - - # Step 1: Start advertisement - self.peripheral.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings) - - # Setup scan settings for low_latency scanning and to include the local name - # of the advertisement started in step 1. - filter_list = self.central.sl4a.bleGenFilterList() - self.central.sl4a.bleSetScanSettingsNumOfMatches(BleScanSettingsMatchNums.ONE) - self.central.sl4a.bleSetScanFilterDeviceName(self.peripheral.sl4a.bluetoothGetLocalName()) - self.central.sl4a.bleBuildScanFilter(filter_list) - self.central.sl4a.bleSetScanSettingsScanMode(BleScanSettingsModes.LOW_LATENCY) - - # Setup necessary scan objects. - scan_settings = self.central.sl4a.bleBuildScanSetting() - scan_callback = self.central.sl4a.bleGenScanCallback() - - # Step 2: Start scanning on central Android device and find peripheral - # address. - self.central.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback) - expected_event_name = scan_result.format(scan_callback) - try: - mac_address_pre_restart = self.central.ed.pop_event( - expected_event_name, self.default_timeout)['data']['Result']['deviceInfo']['address'] - logging.info("Peripheral advertisement found with mac address: {}".format(mac_address_pre_restart)) - except Empty: - logging.info("Peripheral advertisement not found") - asserts.fail("Peripheral advertisement not found") - return - finally: - self.peripheral.sl4a.bleStopBleAdvertising(advertise_callback) - - # Step 3: Restart peripheral advertising such that a new mac address is - # created. - self.peripheral.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings) - - mac_address_post_restart = mac_address_pre_restart - - while True: - try: - mac_address_post_restart = self.central.ed.pop_event( - expected_event_name, self.default_timeout)['data']['Result']['deviceInfo']['address'] - logging.info("Peripheral advertisement found with mac address: {}".format(mac_address_post_restart)) - except Empty: - logging.info("Peripheral advertisement not found") - asserts.fail("Peripheral advertisement not found") - return - - if mac_address_pre_restart != mac_address_post_restart: - break - - -if __name__ == '__main__': - test_runner.main() diff --git a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_with_irk_test.py b/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_with_irk_test.py deleted file mode 100644 index eb96468da7f..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_with_irk_test.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python3 -# -# 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. - -import io -import logging -import os -import queue - -from blueberry.facade import common_pb2 as common -from blueberry.tests.gd.cert.context import get_current_context -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.gd_sl4a.lib.ble_lib import generate_ble_advertise_objects -from blueberry.tests.gd_sl4a.lib.ble_lib import generate_ble_scan_objects -from blueberry.tests.gd_sl4a.lib.bt_constants import adv_succ -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_address_types -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_advertise_settings_modes -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_scan_settings_modes -from blueberry.tests.gd_sl4a.lib.bt_constants import scan_result -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test -from blueberry.utils.bt_gatt_constants import GattCallbackString -from blueberry.utils.bt_gatt_constants import GattTransport -from mobly import test_runner -from mobly.controllers.android_device_lib.adb import AdbError - - -class GattConnectWithIrkTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass): - - def setup_class(self): - super().setup_class() - self.default_timeout = 10 # seconds - - def setup_test(self): - super().setup_test() - - def teardown_test(self): - super().teardown_test() - - def _wait_for_event(self, expected_event_name, device): - try: - event_info = device.ed.pop_event(expected_event_name, self.default_timeout) - logging.info(event_info) - except queue.Empty as error: - logging.error("Failed to find event: %s", expected_event_name) - return False - return True - - def _wait_for_scan_result_event(self, expected_event_name, device): - try: - event_info = device.ed.pop_event(expected_event_name, self.default_timeout) - except queue.Empty as error: - logging.error("Could not find scan result event: %s", expected_event_name) - return None - return event_info['data']['Result']['deviceInfo']['address'] - - def _get_cert_public_address_and_irk_from_bt_config(self): - # Pull IRK from SL4A cert side to pass in from SL4A DUT side when scanning - bt_config_file_path = os.path.join(get_current_context().get_full_output_path(), - "DUT_%s_bt_config.conf" % self.cert.serial) - try: - self.cert.adb.pull(["/data/misc/bluedroid/bt_config.conf", bt_config_file_path]) - except AdbError as error: - logging.error("Failed to pull SL4A cert BT config") - return False - logging.debug("Reading SL4A cert BT config") - with io.open(bt_config_file_path) as f: - for line in f.readlines(): - stripped_line = line.strip() - if (stripped_line.startswith("Address")): - address_fields = stripped_line.split(' ') - # API currently requires public address to be capitalized - address = address_fields[2].upper() - logging.debug("Found cert address: %s" % address) - continue - if (stripped_line.startswith("LE_LOCAL_KEY_IRK")): - irk_fields = stripped_line.split(' ') - irk = irk_fields[2] - logging.debug("Found cert IRK: %s" % irk) - continue - - return address, irk - - def test_scan_connect_unbonded_device_public_address_with_irk(self): - # Set up SL4A cert side to advertise - logging.info("Starting advertising") - self.cert.sl4a.bleSetAdvertiseSettingsIsConnectable(True) - self.cert.sl4a.bleSetAdvertiseDataIncludeDeviceName(True) - self.cert.sl4a.bleSetAdvertiseSettingsAdvertiseMode(ble_advertise_settings_modes['low_latency']) - self.cert.sl4a.bleSetAdvertiseSettingsOwnAddressType(common.RANDOM_DEVICE_ADDRESS) - advertise_callback, advertise_data, advertise_settings = generate_ble_advertise_objects(self.cert.sl4a) - self.cert.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings) - - # Wait for SL4A cert to start advertising - assertThat(self._wait_for_event(adv_succ.format(advertise_callback), self.cert)).isTrue() - logging.info("Advertising started") - - # Pull IRK from SL4A cert side to pass in from SL4A DUT side when scanning - cert_public_address, irk = self._get_cert_public_address_and_irk_from_bt_config() - - # Set up SL4A DUT side to scan - addr_type = ble_address_types["public"] - logging.info("Start scanning for PUBLIC_ADDRESS %s with address type %d and IRK %s" % - (cert_public_address, addr_type, irk)) - self.dut.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) - self.dut.sl4a.bleSetScanSettingsLegacy(False) - filter_list, scan_settings, scan_callback = generate_ble_scan_objects(self.dut.sl4a) - expected_event_name = scan_result.format(scan_callback) - - # Start scanning on SL4A DUT - self.dut.sl4a.bleSetScanFilterDeviceAddressTypeAndIrkHexString(cert_public_address, int(addr_type), irk) - self.dut.sl4a.bleBuildScanFilter(filter_list) - self.dut.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback) - logging.info("Started scanning") - - # Verify that scan result is received on SL4A DUT - mac_address = self._wait_for_scan_result_event(expected_event_name, self.dut) - assertThat(mac_address).isNotNone() - logging.info("Filter advertisement with address {}".format(mac_address)) - - # Try to connect GATT - gatt_callback = self.dut.sl4a.gattCreateGattCallback() - bluetooth_gatt = self.dut.sl4a.gattClientConnectGatt(gatt_callback, mac_address, False, - GattTransport.TRANSPORT_LE, False, None) - assertThat(bluetooth_gatt).isNotNone() - - # Verify that GATT connect event occurs on SL4A DUT - expected_event_name = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback) - assertThat(self._wait_for_event(expected_event_name, self.dut)).isTrue() - - # Test over - self.cert.sl4a.bleStopBleAdvertising(advertise_callback) - self.dut.sl4a.bleStopBleScan(scan_callback) - - -if __name__ == '__main__': - test_runner.main() diff --git a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_notify_test.py b/system/blueberry/tests/sl4a_sl4a/gatt/gatt_notify_test.py deleted file mode 100644 index 5e02675185e..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_notify_test.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2016 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. -""" -This test script exercises GATT notify/indicate procedures. - -Original location: - tools/test/connectivity/acts_tests/tests/google/ble/gatt/GattNotifyTest.py -""" - -from blueberry.tests.gd.cert.test_decorators import test_tracker_info - -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.sl4a_sl4a.lib import gatt_connected_base_test -from blueberry.utils.bt_gatt_constants import GattCharDesc -from blueberry.utils.bt_gatt_constants import GattDescriptor -from blueberry.utils.bt_gatt_constants import GattEvent -from mobly import test_runner - - -class GattNotifyTest(gatt_connected_base_test.GattConnectedBaseTest): - - @test_tracker_info(uuid='e0ba60af-c1f2-4516-a5d5-89e2def0c757') - def test_notify_char(self): - """Test notify characteristic value. - - Test GATT notify characteristic value. - - Steps: - 1. Central: write CCC - register for notifications. - 2. Peripheral: receive CCC modification. - 3. Peripheral: send characteristic notification. - 4. Central: receive notification, verify it's conent matches what was - sent - - Expected Result: - Verify that notification registration and delivery works. - - Returns: - Pass if True - Fail if False - - TAGS: LE, GATT, Characteristic - Priority: 0 - """ - # write CCC descriptor to enable notifications - self.central.sl4a.gattClientDescriptorSetValue( - self.bluetooth_gatt, self.discovered_services_index, self.test_service_index, self.NOTIFIABLE_CHAR_UUID, - GattCharDesc.GATT_CLIENT_CHARAC_CFG_UUID, GattDescriptor.ENABLE_NOTIFICATION_VALUE) - - self.central.sl4a.gattClientWriteDescriptor(self.bluetooth_gatt, self.discovered_services_index, - self.test_service_index, self.NOTIFIABLE_CHAR_UUID, - GattCharDesc.GATT_CLIENT_CHARAC_CFG_UUID) - - # enable notifications in app - self.central.sl4a.gattClientSetCharacteristicNotification(self.bluetooth_gatt, self.discovered_services_index, - self.test_service_index, self.NOTIFIABLE_CHAR_UUID, - True) - - event = self._server_wait(GattEvent.DESC_WRITE_REQ) - - request_id = event['data']['requestId'] - bt_device_id = 0 - status = 0 - # confirm notification registration was successful - self.peripheral.sl4a.gattServerSendResponse(self.gatt_server, bt_device_id, request_id, status, 0, []) - # wait for client to get response - event = self._client_wait(GattEvent.DESC_WRITE) - - # set notified value - notified_value = [1, 5, 9, 7, 5, 3, 6, 4, 8, 2] - self.peripheral.sl4a.gattServerCharacteristicSetValue(self.notifiable_char_index, notified_value) - - # send notification - self.peripheral.sl4a.gattServerNotifyCharacteristicChanged(self.gatt_server, bt_device_id, - self.notifiable_char_index, False) - - # wait for client to receive the notification - event = self._client_wait(GattEvent.CHAR_CHANGE) - assertThat(event["data"]["CharacteristicValue"]).isEqualTo(notified_value) - - return True - - -if __name__ == '__main__': - test_runner.main() diff --git a/system/blueberry/tests/sl4a_sl4a/l2cap/le_l2cap_coc_test.py b/system/blueberry/tests/sl4a_sl4a/l2cap/le_l2cap_coc_test.py deleted file mode 100644 index ee949016a20..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/l2cap/le_l2cap_coc_test.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import binascii -import io -import logging -import os -import queue -import time - -from blueberry.tests.gd.cert.context import get_current_context -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_address_types -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test -from blueberry.tests.sl4a_sl4a.lib.security import Security - - -class LeL2capCoCTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass): - - def __get_cert_public_address_and_irk_from_bt_config(self): - # Pull IRK from SL4A cert side to pass in from SL4A DUT side when scanning - bt_config_file_path = os.path.join(get_current_context().get_full_output_path(), - "DUT_%s_bt_config.conf" % self.cert.serial) - try: - self.cert.adb.pull(["/data/misc/bluedroid/bt_config.conf", bt_config_file_path]) - except AdbError as error: - logging.error("Failed to pull SL4A cert BT config") - return False - logging.debug("Reading SL4A cert BT config") - with io.open(bt_config_file_path) as f: - for line in f.readlines(): - stripped_line = line.strip() - if (stripped_line.startswith("Address")): - address_fields = stripped_line.split(' ') - # API currently requires public address to be capitalized - address = address_fields[2].upper() - logging.debug("Found cert address: %s" % address) - continue - if (stripped_line.startswith("LE_LOCAL_KEY_IRK")): - irk_fields = stripped_line.split(' ') - irk = irk_fields[2] - logging.debug("Found cert IRK: %s" % irk) - continue - - return address, irk - - def setup_class(self): - super().setup_class() - - def setup_test(self): - assertThat(super().setup_test()).isTrue() - - def teardown_test(self): - self.dut_scanner_.stop_scanning() - self.cert_advertiser_.stop_advertising() - self.dut_security_.remove_all_bonded_devices() - self.cert_security_.remove_all_bonded_devices() - super().teardown_test() - - # Scans for the cert device by name. We expect to get back a RPA. - def __scan_for_cert_by_name(self): - cert_public_address, irk = self.__get_cert_public_address_and_irk_from_bt_config() - self.cert_advertiser_.advertise_public_extended_pdu() - advertising_name = self.cert_advertiser_.get_local_advertising_name() - - # Scan with name and verify we get back a scan result with the RPA - scan_result_addr = self.dut_scanner_.scan_for_name(advertising_name) - assertThat(scan_result_addr).isNotNone() - assertThat(scan_result_addr).isNotEqualTo(cert_public_address) - - return scan_result_addr - - def __scan_for_irk(self): - cert_public_address, irk = self.__get_cert_public_address_and_irk_from_bt_config() - rpa_address = self.cert_advertiser_.advertise_public_extended_pdu() - id_addr = self.dut_scanner_.scan_for_address_with_irk(cert_public_address, ble_address_types["public"], irk) - self.dut_scanner_.stop_scanning() - return id_addr - - def __create_le_bond_oob_single_sided(self, - wait_for_oob_data=True, - wait_for_device_bonded=True, - addr=None, - addr_type=ble_address_types["random"]): - oob_data = self.cert_security_.generate_oob_data(Security.TRANSPORT_LE, wait_for_oob_data) - if wait_for_oob_data: - assertThat(oob_data[0]).isEqualTo(0) - assertThat(oob_data[1]).isNotNone() - self.dut_security_.create_bond_out_of_band(oob_data[1], addr, addr_type, wait_for_device_bonded) - return oob_data[1].to_sl4a_address() - - def __create_le_bond_oob_double_sided(self, - wait_for_oob_data=True, - wait_for_device_bonded=True, - addr=None, - addr_type=ble_address_types["random"]): - # Genearte OOB data on DUT, but we don't use it - self.dut_security_.generate_oob_data(Security.TRANSPORT_LE, wait_for_oob_data) - self.__create_le_bond_oob_single_sided(wait_for_oob_data, wait_for_device_bonded, addr, addr_type) - - def __test_le_l2cap_insecure_coc(self): - logging.info("Testing insecure L2CAP CoC") - cert_rpa = self.__scan_for_cert_by_name() - - # Listen on an insecure l2cap coc on the cert - psm = self.cert_l2cap_.listen_using_l2cap_le_coc(False) - self.dut_l2cap_.create_l2cap_le_coc(cert_rpa, psm, False) - - # Cleanup - self.dut_scanner_.stop_scanning() - self.dut_l2cap_.close_l2cap_le_coc_client() - self.cert_advertiser_.stop_advertising() - self.cert_l2cap_.close_l2cap_le_coc_server() - - def __test_le_l2cap_secure_coc(self): - logging.info("Testing secure L2CAP CoC") - cert_rpa = self.__create_le_bond_oob_single_sided() - - # Listen on an secure l2cap coc on the cert - psm = self.cert_l2cap_.listen_using_l2cap_le_coc(True) - self.dut_l2cap_.create_l2cap_le_coc(cert_rpa, psm, True) - - # Cleanup - self.dut_scanner_.stop_scanning() - self.dut_l2cap_.close_l2cap_le_coc_client() - self.cert_advertiser_.stop_advertising() - self.cert_l2cap_.close_l2cap_le_coc_server() - self.dut_security_.remove_all_bonded_devices() - self.cert_security_.remove_all_bonded_devices() - - def __test_le_l2cap_secure_coc_after_irk_scan(self): - logging.info("Testing secure L2CAP CoC after IRK scan") - cert_config_addr, irk = self.__get_cert_public_address_and_irk_from_bt_config() - cert_id_addr = self.__scan_for_irk() - - assertThat(cert_id_addr).isEqualTo(cert_config_addr) - self.__create_le_bond_oob_single_sided(True, True, cert_id_addr, ble_address_types["public"]) - self.cert_advertiser_.stop_advertising() - self.__test_le_l2cap_secure_coc() - - def __test_secure_le_l2cap_coc_stress(self): - for i in range(0, 10): - self.__test_le_l2cap_secure_coc() - - def __test_insecure_le_l2cap_coc_stress(self): - for i in range(0, 10): - self.__test_le_l2cap_insecure_coc() - - def __test_le_l2cap_coc_stress(self): - #for i in range (0, 10): - self.__test_le_l2cap_insecure_coc() - self.__test_le_l2cap_secure_coc() - - def __test_secure_le_l2cap_coc_after_irk_scan_stress(self): - for i in range(0, 10): - self.__test_le_l2cap_secure_coc_after_irk_scan() diff --git a/system/blueberry/tests/sl4a_sl4a/lib/gatt_connected_base_test.py b/system/blueberry/tests/sl4a_sl4a/lib/gatt_connected_base_test.py deleted file mode 100644 index 9a4e6064987..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/lib/gatt_connected_base_test.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2016 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. -""" -This is base class for tests that exercises different GATT procedures between two connected devices. -Setup/Teardown methods take care of establishing connection, and doing GATT DB initialization/discovery. - -Original file: - tools/test/connectivity/acts_tests/acts_contrib/test_utils/bt/GattConnectedBaseTest.py -""" - -import logging -from queue import Empty - -from blueberry.tests.gd_sl4a.lib.bt_constants import bt_default_timeout -from blueberry.tests.sl4a_sl4a.lib.sl4a_sl4a_base_test import Sl4aSl4aBaseTestClass -from blueberry.utils.bt_gatt_constants import GattCallbackError -from blueberry.utils.bt_gatt_constants import GattCallbackString -from blueberry.utils.bt_gatt_constants import GattCharDesc -from blueberry.utils.bt_gatt_constants import GattCharacteristic -from blueberry.utils.bt_gatt_constants import GattDescriptor -from blueberry.utils.bt_gatt_constants import GattEvent -from blueberry.utils.bt_gatt_constants import GattMtuSize -from blueberry.utils.bt_gatt_constants import GattServiceType -from blueberry.utils.bt_gatt_utils import GattTestUtilsError -from blueberry.utils.bt_gatt_utils import disconnect_gatt_connection -from blueberry.utils.bt_gatt_utils import orchestrate_gatt_connection -from blueberry.utils.bt_gatt_utils import setup_gatt_characteristics -from blueberry.utils.bt_gatt_utils import setup_gatt_descriptors - - -class GattConnectedBaseTest(Sl4aSl4aBaseTestClass): - - TEST_SERVICE_UUID = "3846D7A0-69C8-11E4-BA00-0002A5D5C51B" - READABLE_CHAR_UUID = "21c0a0bf-ad51-4a2d-8124-b74003e4e8c8" - READABLE_DESC_UUID = "aa7edd5a-4d1d-4f0e-883a-d145616a1630" - WRITABLE_CHAR_UUID = "aa7edd5a-4d1d-4f0e-883a-d145616a1630" - WRITABLE_DESC_UUID = "76d5ed92-ca81-4edb-bb6b-9f019665fb32" - NOTIFIABLE_CHAR_UUID = "b2c83efa-34ca-11e6-ac61-9e71128cae77" - - def setup_class(self): - super().setup_class() - self.central = self.dut - self.peripheral = self.cert - - def setup_test(self): - super(GattConnectedBaseTest, self).setup_test() - - self.gatt_server_callback, self.gatt_server = \ - self._setup_multiple_services() - if not self.gatt_server_callback or not self.gatt_server: - raise AssertionError('Service setup failed') - - self.bluetooth_gatt, self.gatt_callback, self.adv_callback = (orchestrate_gatt_connection( - self.central, self.peripheral)) - self.peripheral.sl4a.bleStopBleAdvertising(self.adv_callback) - - self.mtu = GattMtuSize.MIN - - if self.central.sl4a.gattClientDiscoverServices(self.bluetooth_gatt): - event = self._client_wait(GattEvent.GATT_SERV_DISC) - self.discovered_services_index = event['data']['ServicesIndex'] - services_count = self.central.sl4a.gattClientGetDiscoveredServicesCount(self.discovered_services_index) - self.test_service_index = None - for i in range(services_count): - disc_service_uuid = (self.central.sl4a.gattClientGetDiscoveredServiceUuid( - self.discovered_services_index, i).upper()) - if disc_service_uuid == self.TEST_SERVICE_UUID: - self.test_service_index = i - break - - if not self.test_service_index: - print("Service not found") - return False - - connected_device_list = self.peripheral.sl4a.gattServerGetConnectedDevices(self.gatt_server) - if len(connected_device_list) == 0: - logging.info("No devices connected from peripheral.") - return False - - return True - - def teardown_test(self): - self.peripheral.sl4a.gattServerClearServices(self.gatt_server) - self.peripheral.sl4a.gattServerClose(self.gatt_server) - - del self.gatt_server_callback - del self.gatt_server - - self._orchestrate_gatt_disconnection(self.bluetooth_gatt, self.gatt_callback) - - return super(GattConnectedBaseTest, self).teardown_test() - - def _server_wait(self, gatt_event): - return self._timed_pop(gatt_event, self.peripheral, self.gatt_server_callback) - - def _client_wait(self, gatt_event: GattEvent): - return self._timed_pop(gatt_event, self.central, self.gatt_callback) - - def _timed_pop(self, gatt_event: GattEvent, sl4a, gatt_callback): - expected_event = gatt_event["evt"].format(gatt_callback) - try: - return sl4a.ed.pop_event(expected_event, bt_default_timeout) - except Empty as emp: - raise AssertionError(gatt_event["err"].format(expected_event)) - - def _setup_characteristics_and_descriptors(self, droid): - characteristic_input = [ - { - 'uuid': self.WRITABLE_CHAR_UUID, - 'property': GattCharacteristic.PROPERTY_WRITE | GattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, - 'permission': GattCharacteristic.PERMISSION_WRITE - }, - { - 'uuid': self.READABLE_CHAR_UUID, - 'property': GattCharacteristic.PROPERTY_READ, - 'permission': GattCharacteristic.PROPERTY_READ - }, - { - 'uuid': self.NOTIFIABLE_CHAR_UUID, - 'property': GattCharacteristic.PROPERTY_NOTIFY | GattCharacteristic.PROPERTY_INDICATE, - 'permission': GattCharacteristic.PERMISSION_READ - }, - ] - descriptor_input = [{ - 'uuid': self.WRITABLE_DESC_UUID, - 'property': GattDescriptor.PERMISSION_READ[0] | GattDescriptor.PERMISSION_WRITE[0] - }, { - 'uuid': self.READABLE_DESC_UUID, - 'property': GattDescriptor.PERMISSION_READ[0] | GattDescriptor.PERMISSION_WRITE[0], - }, { - 'uuid': GattCharDesc.GATT_CLIENT_CHARAC_CFG_UUID, - 'property': GattDescriptor.PERMISSION_READ[0] | GattDescriptor.PERMISSION_WRITE[0], - }] - characteristic_list = setup_gatt_characteristics(droid, characteristic_input) - self.notifiable_char_index = characteristic_list[2] - descriptor_list = setup_gatt_descriptors(droid, descriptor_input) - return characteristic_list, descriptor_list - - def _orchestrate_gatt_disconnection(self, bluetooth_gatt, gatt_callback): - logging.info("Disconnecting from peripheral device.") - try: - disconnect_gatt_connection(self.central, bluetooth_gatt, gatt_callback) - except GattTestUtilsError as err: - logging.error(err) - return False - self.central.sl4a.gattClientClose(bluetooth_gatt) - return True - - def _find_service_added_event(self, gatt_server_callback, uuid): - expected_event = GattCallbackString.SERV_ADDED.format(gatt_server_callback) - try: - event = self.peripheral.sl4a.ed.pop_event(expected_event, bt_default_timeout) - except Empty: - logging.error(GattCallbackError.SERV_ADDED_ERR.format(expected_event)) - return False - if event['data']['serviceUuid'].lower() != uuid.lower(): - logging.error("Uuid mismatch. Found: {}, Expected {}.".format(event['data']['serviceUuid'], uuid)) - return False - return True - - def _setup_multiple_services(self): - gatt_server_callback = (self.peripheral.sl4a.gattServerCreateGattServerCallback()) - gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_callback) - characteristic_list, descriptor_list = (self._setup_characteristics_and_descriptors(self.peripheral.sl4a)) - self.peripheral.sl4a.gattServerCharacteristicAddDescriptor(characteristic_list[0], descriptor_list[0]) - self.peripheral.sl4a.gattServerCharacteristicAddDescriptor(characteristic_list[1], descriptor_list[1]) - self.peripheral.sl4a.gattServerCharacteristicAddDescriptor(characteristic_list[2], descriptor_list[2]) - gatt_service3 = self.peripheral.sl4a.gattServerCreateService(self.TEST_SERVICE_UUID, - GattServiceType.SERVICE_TYPE_PRIMARY) - for characteristic in characteristic_list: - self.peripheral.sl4a.gattServerAddCharacteristicToService(gatt_service3, characteristic) - self.peripheral.sl4a.gattServerAddService(gatt_server, gatt_service3) - result = self._find_service_added_event(gatt_server_callback, self.TEST_SERVICE_UUID) - if not result: - return False, False - return gatt_server_callback, gatt_server diff --git a/system/blueberry/tests/sl4a_sl4a/lib/l2cap.py b/system/blueberry/tests/sl4a_sl4a/lib/l2cap.py deleted file mode 100644 index 9604ab72ef3..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/lib/l2cap.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import logging -import queue - -from blueberry.tests.gd.cert.truth import assertThat - - -class L2cap: - - __l2cap_connection_timeout = 10 #seconds - __device = None - __active_client_coc = False - __active_server_coc = False - - def __init__(self, device): - self.__device = device - - def __wait_for_event(self, expected_event_name): - try: - event_info = self.__device.ed.pop_event(expected_event_name, self.__l2cap_connection_timeout) - logging.info(event_info) - except queue.Empty as error: - logging.error("Failed to find event: %s", expected_event_name) - return False - return True - - def create_l2cap_le_coc(self, address, psm, secure): - logging.info("creating l2cap channel with secure=%r and psm %s", secure, psm) - self.__device.sl4a.bluetoothSocketConnBeginConnectThreadPsm(address, True, psm, secure) - assertThat(self.__wait_for_event("BluetoothSocketConnectSuccess")).isTrue() - self.__active_client_coc = True - - # Starts listening on the l2cap server socket, returns the psm - def listen_using_l2cap_le_coc(self, secure): - logging.info("Listening for l2cap channel with secure=%r", secure) - self.__device.sl4a.bluetoothSocketConnBeginAcceptThreadPsm(self.__l2cap_connection_timeout, True, secure) - self.__active_server_coc = True - return self.__device.sl4a.bluetoothSocketConnGetPsm() - - def close_l2cap_le_coc_client(self): - if self.__active_client_coc: - logging.info("Closing LE L2CAP CoC Client") - self.__device.sl4a.bluetoothSocketConnKillConnThread() - self.__active_client_coc = False - - def close_l2cap_le_coc_server(self): - if self.__active_server_coc: - logging.info("Closing LE L2CAP CoC Server") - self.__device.sl4a.bluetoothSocketConnEndAcceptThread() - self.__active_server_coc = False - - def close(self): - self.close_l2cap_le_coc_client() - self.close_l2cap_le_coc_server() - self.__device == None diff --git a/system/blueberry/tests/sl4a_sl4a/lib/le_advertiser.py b/system/blueberry/tests/sl4a_sl4a/lib/le_advertiser.py deleted file mode 100644 index 1c075a3b4c4..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/lib/le_advertiser.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import binascii -import logging -import queue - -from blueberry.facade import common_pb2 as common -from blueberry.tests.gd.cert.closable import Closable -from blueberry.tests.gd.cert.closable import safeClose -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.gd_sl4a.lib.ble_lib import generate_ble_advertise_objects -from blueberry.tests.gd_sl4a.lib.bt_constants import adv_succ -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_advertise_settings_modes -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test - - -class LeAdvertiser(Closable): - - is_advertising = False - device = None - default_timeout = 10 # seconds - advertise_callback = None - advertise_data = None - advertise_settings = None - - def __init__(self, device): - self.device = device - - def __wait_for_event(self, expected_event_name): - try: - event_info = self.device.ed.pop_event(expected_event_name, self.default_timeout) - logging.info(event_info) - except queue.Empty as error: - logging.error("Failed to find event: %s", expected_event_name) - return False - return True - - def advertise_public_extended_pdu(self, address_type=common.RANDOM_DEVICE_ADDRESS, name="SL4A Device"): - if self.is_advertising: - logging.info("Already advertising!") - return - logging.info("Configuring advertisement with address type %d", address_type) - self.is_advertising = True - self.device.sl4a.bleSetScanSettingsLegacy(False) - self.device.sl4a.bleSetAdvertiseSettingsIsConnectable(True) - self.device.sl4a.bleSetAdvertiseDataIncludeDeviceName(True) - self.device.sl4a.bleSetAdvertiseSettingsAdvertiseMode(ble_advertise_settings_modes['low_latency']) - self.device.sl4a.bleSetAdvertiseSettingsOwnAddressType(address_type) - self.advertise_callback, self.advertise_data, self.advertise_settings = generate_ble_advertise_objects( - self.device.sl4a) - self.device.sl4a.bleStartBleAdvertising(self.advertise_callback, self.advertise_data, self.advertise_settings) - - # Wait for SL4A cert to start advertising - assertThat(self.__wait_for_event(adv_succ.format(self.advertise_callback))).isTrue() - logging.info("Advertising started") - - def get_local_advertising_name(self): - return self.device.sl4a.bluetoothGetLocalName() - - def stop_advertising(self): - if self.is_advertising: - logging.info("Stopping advertisement") - self.device.sl4a.bleStopBleAdvertising(self.advertise_callback) - self.is_advertising = False - - def close(self): - self.stop_advertising() - self.device = None diff --git a/system/blueberry/tests/sl4a_sl4a/lib/le_scanner.py b/system/blueberry/tests/sl4a_sl4a/lib/le_scanner.py deleted file mode 100644 index 2e67d8af551..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/lib/le_scanner.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import logging -import queue - -from blueberry.facade import common_pb2 as common -from blueberry.tests.gd.cert.closable import Closable -from blueberry.tests.gd.cert.closable import safeClose -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.gd_sl4a.lib.ble_lib import generate_ble_scan_objects -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_scan_settings_modes -from blueberry.tests.gd_sl4a.lib.bt_constants import scan_result -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test - - -class LeScanner(Closable): - - is_scanning = False - device = None - filter_list = None - scan_settings = None - scan_callback = None - - def __init__(self, device): - self.device = device - - def __wait_for_scan_result_event(self, expected_event_name, timeout=60): - try: - event_info = self.device.ed.pop_event(expected_event_name, timeout) - except queue.Empty as error: - logging.error("Could not find scan result event: %s", expected_event_name) - return None - return event_info['data']['Result']['deviceInfo']['address'] - - def scan_for_address_expect_none(self, address, addr_type): - if self.is_scanning: - print("Already scanning!") - return None - self.is_scanning = True - logging.info("Start scanning for identity address {} or type {}".format(address, addr_type)) - self.device.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) - self.device.sl4a.bleSetScanSettingsLegacy(False) - self.filter_list, self.scan_settings, self.scan_callback = generate_ble_scan_objects(self.device.sl4a) - expected_event_name = scan_result.format(self.scan_callback) - - # Start scanning on SL4A DUT - self.device.sl4a.bleSetScanFilterDeviceAddressAndType(address, addr_type) - self.device.sl4a.bleBuildScanFilter(self.filter_list) - self.device.sl4a.bleStartBleScan(self.filter_list, self.scan_settings, self.scan_callback) - - # Verify that scan result is received on SL4A DUT - advertising_address = self.__wait_for_scan_result_event(expected_event_name, 1) - assertThat(advertising_address).isNone() - logging.info("Filter advertisement with address {}".format(advertising_address)) - return advertising_address - - def scan_for_address(self, address, addr_type): - if self.is_scanning: - print("Already scanning!") - return None - self.is_scanning = True - logging.info("Start scanning for identity address {} or type {}".format(address, addr_type)) - self.device.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) - self.device.sl4a.bleSetScanSettingsLegacy(False) - self.filter_list, self.scan_settings, self.scan_callback = generate_ble_scan_objects(self.device.sl4a) - expected_event_name = scan_result.format(self.scan_callback) - - # Start scanning on SL4A DUT - self.device.sl4a.bleSetScanFilterDeviceAddressAndType(address, addr_type) - self.device.sl4a.bleBuildScanFilter(self.filter_list) - self.device.sl4a.bleStartBleScan(self.filter_list, self.scan_settings, self.scan_callback) - - # Verify that scan result is received on SL4A DUT - advertising_address = self.__wait_for_scan_result_event(expected_event_name) - assertThat(advertising_address).isNotNone() - logging.info("Filter advertisement with address {}".format(advertising_address)) - return advertising_address - - def scan_for_address_with_irk(self, address, addr_type, irk): - if self.is_scanning: - print("Already scanning!") - return None - self.is_scanning = True - logging.info("Start scanning for identity address {} or type {} using irk {}".format(address, addr_type, irk)) - self.device.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) - self.device.sl4a.bleSetScanSettingsLegacy(False) - self.filter_list, self.scan_settings, self.scan_callback = generate_ble_scan_objects(self.device.sl4a) - expected_event_name = scan_result.format(self.scan_callback) - - # Start scanning on SL4A DUT - self.device.sl4a.bleSetScanFilterDeviceAddressTypeAndIrkHexString(address, addr_type, irk) - self.device.sl4a.bleBuildScanFilter(self.filter_list) - self.device.sl4a.bleStartBleScan(self.filter_list, self.scan_settings, self.scan_callback) - - # Verify that scan result is received on SL4A DUT - advertising_address = self.__wait_for_scan_result_event(expected_event_name) - assertThat(advertising_address).isNotNone() - logging.info("Filter advertisement with address {}".format(advertising_address)) - return advertising_address - - def scan_for_address_with_irk_pending_intent(self, address, addr_type, irk): - if self.is_scanning: - print("Already scanning!") - return None - self.is_scanning = True - logging.info("Start scanning for identity address {} or type {} using irk {}".format(address, addr_type, irk)) - self.device.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) - self.device.sl4a.bleSetScanSettingsLegacy(False) - self.filter_list, self.scan_settings, self.scan_callback = generate_ble_scan_objects(self.device.sl4a) - # Hard code here since callback index iterates and will cause this to fail if ran - # Second as the impl in SL4A sends this since it's a single callback for broadcast. - expected_event_name = "BleScan1onScanResults" - - # Start scanning on SL4A DUT - self.device.sl4a.bleSetScanFilterDeviceAddressTypeAndIrkHexString(address, addr_type, irk) - self.device.sl4a.bleBuildScanFilter(self.filter_list) - self.device.sl4a.bleStartBleScanPendingIntent(self.filter_list, self.scan_settings) - - # Verify that scan result is received on SL4A DUT - advertising_address = self.__wait_for_scan_result_event(expected_event_name) - assertThat(advertising_address).isNotNone() - logging.info("Filter advertisement with address {}".format(advertising_address)) - return advertising_address - - def scan_for_name(self, name): - if self.is_scanning: - print("Already scanning!") - return - self.is_scanning = True - logging.info("Start scanning for name {}".format(name)) - self.device.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) - self.device.sl4a.bleSetScanSettingsLegacy(False) - self.filter_list, self.scan_settings, self.scan_callback = generate_ble_scan_objects(self.device.sl4a) - expected_event_name = scan_result.format(1) - self.device.ed.clear_events(expected_event_name) - - # Start scanning on SL4A DUT - self.device.sl4a.bleSetScanFilterDeviceName(name) - self.device.sl4a.bleBuildScanFilter(self.filter_list) - self.device.sl4a.bleStartBleScanPendingIntent(self.filter_list, self.scan_settings) - - # Verify that scan result is received on SL4A DUT - advertising_address = self.__wait_for_scan_result_event(expected_event_name) - assertThat(advertising_address).isNotNone() - logging.info("Filter advertisement with address {}".format(advertising_address)) - return advertising_address - - def stop_scanning(self): - """ - Warning: no java callback registered for this - """ - if self.is_scanning: - logging.info("Stopping scan") - self.device.sl4a.bleStopBleScan(self.scan_callback) - self.is_scanning = False - - def close(self): - self.stop_scanning() - self.device = None diff --git a/system/blueberry/tests/sl4a_sl4a/lib/oob_data.py b/system/blueberry/tests/sl4a_sl4a/lib/oob_data.py deleted file mode 100644 index e54c467f0d3..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/lib/oob_data.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - - -class OobData: - """ - This represents the data generated from the device - """ - - address = None - confirmation = None - randomizer = None - - ADDRESS_WITH_TYPE_LENGTH = 14 - - def __init__(self, address, confirmation, randomizer): - self.address = address - self.confirmation = confirmation - self.randomizer = randomizer - - def to_sl4a_address(self): - oob_address = self.address.upper() - address_str_octets = [] - i = 1 - buf = "" - for c in oob_address: - buf += c - if i % 2 == 0: - address_str_octets.append(buf) - buf = "" - i += 1 - address_str_octets = address_str_octets[:6] - address_str_octets.reverse() - return ":".join(address_str_octets) - - def to_sl4a_address_type(self): - if len(self.address) != self.ADDRESS_WITH_TYPE_LENGTH: - return -1 - return self.address.upper()[-1] diff --git a/system/blueberry/tests/sl4a_sl4a/lib/security.py b/system/blueberry/tests/sl4a_sl4a/lib/security.py deleted file mode 100644 index 5181a3eaf94..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/lib/security.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import queue -import logging - -from blueberry.tests.gd.cert.closable import Closable -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.sl4a_sl4a.lib.oob_data import OobData - - -class Security: - - # Events sent from SL4A - SL4A_EVENT_GENERATE_OOB_DATA_SUCCESS = "GeneratedOobData" - SL4A_EVENT_GENERATE_OOB_DATA_ERROR = "ErrorOobData" - SL4A_EVENT_BONDED = "Bonded" - SL4A_EVENT_UNBONDED = "Unbonded" - - # Matches tBT_TRANSPORT - # Used Strings because ints were causing gRPC problems - TRANSPORT_AUTO = "0" - TRANSPORT_BREDR = "1" - TRANSPORT_LE = "2" - - __default_timeout = 10 # seconds - __default_bonding_timeout = 60 # seconds - __device = None - - def __init__(self, device): - self.__device = device - self.__device.sl4a.bluetoothStartPairingHelper(True) - - # Returns a tuple formatted as . The OobData is - # populated if the statuscode is 0 (SUCCESS), else it will be None - def generate_oob_data(self, transport, wait_for_oob_data_callback=True): - logging.info("Generating local OOB data") - self.__device.sl4a.bluetoothGenerateLocalOobData(transport) - - if wait_for_oob_data_callback is False: - return 0, None - else: - # Check for oob data generation success - try: - generate_success_event = self.__device.ed.pop_event(self.SL4A_EVENT_GENERATE_OOB_DATA_SUCCESS, - self.__default_timeout) - except queue.Empty as error: - logging.error("Failed to generate OOB data!") - # Check if generating oob data failed without blocking - try: - generate_failure_event = self.__device.ed.pop_event(self.SL4A_EVENT_GENERATE_OOB_DATA_ERROR, 0) - except queue.Empty as error: - logging.error("Failed to generate OOB Data without error code") - assertThat(True).isFalse() - - errorcode = generate_failure_event["data"]["Error"] - logging.info("Generating local oob data failed with error code %d", errorcode) - return errorcode, None - - logging.info("OOB ADDR with Type: %s", generate_success_event["data"]["address_with_type"]) - return 0, OobData(generate_success_event["data"]["address_with_type"], - generate_success_event["data"]["confirmation"], generate_success_event["data"]["randomizer"]) - - def ensure_device_bonded(self): - bond_state = None - try: - bond_state = self.__device.ed.pop_event(self.SL4A_EVENT_BONDED, self.__default_bonding_timeout) - except queue.Empty as error: - logging.error("Failed to get bond event!") - - assertThat(bond_state).isNotNone() - logging.info("Bonded: %s", bond_state["data"]["bonded_state"]) - assertThat(bond_state["data"]["bonded_state"]).isEqualTo(True) - - def create_bond_out_of_band(self, - oob_data, - bt_device_object_address=None, - bt_device_object_address_type=-1, - wait_for_device_bonded=True): - assertThat(oob_data).isNotNone() - oob_data_address = oob_data.to_sl4a_address() - oob_data_address_type = oob_data.to_sl4a_address_type() - - # If a BT Device object address isn't specified, default to the oob data - # address and type - if bt_device_object_address is None: - bt_device_object_address = oob_data_address - bt_device_object_address_type = oob_data_address_type - - logging.info("Bonding OOB with device addr=%s, device addr type=%s, oob addr=%s, oob addr type=%s", - bt_device_object_address, bt_device_object_address_type, oob_data_address, oob_data_address_type) - bond_start = self.__device.sl4a.bluetoothCreateLeBondOutOfBand( - oob_data_address, oob_data_address_type, oob_data.confirmation, oob_data.randomizer, - bt_device_object_address, bt_device_object_address_type) - assertThat(bond_start).isTrue() - - if wait_for_device_bonded: - self.ensure_device_bonded() - - def create_bond_numeric_comparison(self, address, transport=TRANSPORT_LE, wait_for_device_bonded=True): - assertThat(address).isNotNone() - if transport == self.TRANSPORT_LE: - self.__device.sl4a.bluetoothLeBond(address) - else: - self.__device.sl4a.bluetoothBond(address) - self.ensure_device_bonded() - - def remove_all_bonded_devices(self): - bonded_devices = self.__device.sl4a.bluetoothGetBondedDevices() - for device in bonded_devices: - logging.info(device) - self.remove_bond(device["address"]) - - def remove_bond(self, address): - if self.__device.sl4a.bluetoothUnbond(address): - bond_state = None - try: - bond_state = self.__device.ed.pop_event(self.SL4A_EVENT_UNBONDED, self.__default_timeout) - except queue.Empty as error: - logging.error("Failed to get bond event!") - assertThat(bond_state).isNotNone() - assertThat(bond_state["data"]["bonded_state"]).isEqualTo(False) - else: - logging.info("remove_bond: Bluetooth Device with address: %s does not exist", address) - - def close(self): - self.remove_all_bonded_devices() - self.__device.sl4a.bluetoothStartPairingHelper(False) - self.__device = None diff --git a/system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py b/system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py deleted file mode 100644 index c692556be42..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python3 -# -# 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. - -import logging -import os -import traceback -from functools import wraps - -from blueberry.tests.gd.cert.closable import safeClose -from blueberry.tests.gd.cert.context import get_current_context -from blueberry.tests.gd_sl4a.lib.ble_lib import BleLib -from blueberry.tests.gd_sl4a.lib.ble_lib import disable_bluetooth -from blueberry.tests.gd_sl4a.lib.ble_lib import enable_bluetooth -from blueberry.tests.sl4a_sl4a.lib.le_advertiser import LeAdvertiser -from blueberry.tests.sl4a_sl4a.lib.le_scanner import LeScanner -from blueberry.tests.sl4a_sl4a.lib.l2cap import L2cap -from blueberry.tests.sl4a_sl4a.lib.security import Security -from blueberry.utils.mobly_sl4a_utils import setup_sl4a -from blueberry.utils.mobly_sl4a_utils import teardown_sl4a -from grpc import RpcError -from mobly import signals -from mobly.base_test import BaseTestClass -from mobly.controllers import android_device -from mobly.controllers.android_device import MOBLY_CONTROLLER_CONFIG_NAME as ANDROID_DEVICE_CONFIG_NAME -from mobly.controllers.android_device_lib.adb import AdbError - - -class Sl4aSl4aBaseTestClass(BaseTestClass): - - # DUT - dut_advertiser_ = None - dut_scanner_ = None - dut_security_ = None - dut_l2cap_ = None - - # CERT - cert_advertiser_ = None - cert_scanner_ = None - cert_security_ = None - cert_l2cap_ = None - - SUBPROCESS_WAIT_TIMEOUT_SECONDS = 10 - - def setup_class(self): - self.log_path_base = get_current_context().get_full_output_path() - self.verbose_mode = bool(self.user_params.get('verbose_mode', False)) - - # Parse and construct Android device objects - self.android_devices = self.register_controller(android_device, required=True) - - # Setup SL4A for dut, overriding default mobly port settings - self.dut = self.android_devices[0] - server_port = int(self.controller_configs[ANDROID_DEVICE_CONFIG_NAME][0]['server_port']) - forwarded_port = int(self.controller_configs[ANDROID_DEVICE_CONFIG_NAME][0]['forwarded_port']) - setup_sl4a(self.dut, server_port, forwarded_port) - - # Setup SL4A for cert, overriding default mobly port settings - self.cert = self.android_devices[1] - server_port = int(self.controller_configs[ANDROID_DEVICE_CONFIG_NAME][1]['server_port']) - forwarded_port = int(self.controller_configs[ANDROID_DEVICE_CONFIG_NAME][1]['forwarded_port']) - setup_sl4a(self.cert, server_port, forwarded_port) - - # Enable full btsnoop log - self.dut.adb.root() - self.dut.adb.shell("setprop persist.bluetooth.btsnooplogmode full") - getprop_result = self.dut.adb.getprop("persist.bluetooth.btsnooplogmode") - if getprop_result is None or ("full" not in getprop_result.lower()): - self.dut.log.warning( - "Failed to enable Bluetooth HCI Snoop Logging on DUT, mode is {}".format(getprop_result)) - self.cert.adb.root() - self.cert.adb.shell("setprop persist.bluetooth.btsnooplogmode full") - getprop_result = self.cert.adb.getprop("persist.bluetooth.btsnooplogmode") - if getprop_result is None or ("full" not in getprop_result.lower()): - self.cert.log.warning( - "Failed to enable Bluetooth HCI Snoop Logging on CERT, mode is {}".format(getprop_result)) - - self.ble = BleLib(dut=self.dut) - - def teardown_class(self): - teardown_sl4a(self.cert) - teardown_sl4a(self.dut) - super().teardown_class() - - def setup_device_for_test(self, device): - device.ed.clear_all_events() - device.sl4a.setScreenTimeout(500) - device.sl4a.wakeUpNow() - - # Always start tests with Bluetooth enabled and BLE disabled. - device.sl4a.bluetoothDisableBLE() - disable_bluetooth(device.sl4a, device.ed) - # Enable full verbose logging for Bluetooth - device.adb.shell("setprop log.tag.bluetooth VERBOSE") - # Then enable Bluetooth - enable_bluetooth(device.sl4a, device.ed) - device.sl4a.bluetoothDisableBLE() - - def setup_test(self): - self.setup_device_for_test(self.dut) - self.setup_device_for_test(self.cert) - self.dut_advertiser_ = LeAdvertiser(self.dut) - self.dut_scanner_ = LeScanner(self.dut) - self.dut_security_ = Security(self.dut) - self.dut_l2cap_ = L2cap(self.dut) - self.cert_advertiser_ = LeAdvertiser(self.cert) - self.cert_scanner_ = LeScanner(self.cert) - self.cert_security_ = Security(self.cert) - self.cert_l2cap_ = L2cap(self.cert) - return True - - def teardown_test(self): - # Go ahead and remove everything before turning off the stack - safeClose(self.dut_advertiser_) - safeClose(self.dut_scanner_) - safeClose(self.dut_security_) - safeClose(self.dut_l2cap_) - safeClose(self.cert_advertiser_) - safeClose(self.cert_scanner_) - safeClose(self.cert_security_) - safeClose(self.cert_l2cap_) - self.dut_advertiser_ = None - self.dut_scanner_ = None - self.dut_security_ = None - self.cert_advertiser_ = None - self.cert_l2cap_ = None - self.cert_scanner_ = None - self.cert_security_ = None - - # Make sure BLE is disabled and Bluetooth is disabled after test - self.dut.sl4a.bluetoothDisableBLE() - disable_bluetooth(self.dut.sl4a, self.dut.ed) - self.cert.sl4a.bluetoothDisableBLE() - disable_bluetooth(self.cert.sl4a, self.cert.ed) - - current_test_dir = get_current_context().get_full_output_path() - - # Pull DUT logs - self.pull_logs(current_test_dir, self.dut) - - # Pull CERT logs - self.pull_logs(current_test_dir, self.cert) - return True - - def pull_logs(self, base_dir, device): - try: - device.adb.pull([ - "/data/misc/bluetooth/logs/btsnoop_hci.log", - os.path.join(base_dir, "DUT_%s_btsnoop_hci.log" % device.serial) - ]) - device.adb.pull([ - "/data/misc/bluedroid/bt_config.conf", - os.path.join(base_dir, "DUT_%s_bt_config.conf" % device.serial) - ]) - except AdbError as error: - logging.warning("Failed to pull logs from DUT: " + str(error)) - - def __getattribute__(self, name): - attr = super().__getattribute__(name) - if not callable(attr) or not Sl4aSl4aBaseTestClass.__is_entry_function(name): - return attr - - @wraps(attr) - def __wrapped(*args, **kwargs): - try: - return attr(*args, **kwargs) - except RpcError as e: - exception_info = "".join(traceback.format_exception(e.__class__, e, e.__traceback__)) - raise signals.TestFailure("RpcError during test\n\nRpcError:\n\n%s" % (exception_info)) - - return __wrapped - - __ENTRY_METHODS = {"setup_class", "teardown_class", "setup_test", "teardown_test"} - - @staticmethod - def __is_entry_function(name): - return name.startswith("test_") or name in Sl4aSl4aBaseTestClass.__ENTRY_METHODS diff --git a/system/blueberry/tests/sl4a_sl4a/scanning/le_scanning.py b/system/blueberry/tests/sl4a_sl4a/scanning/le_scanning.py deleted file mode 100644 index 336067ec154..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/scanning/le_scanning.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import binascii -import io -import logging -import os -import queue -import time - -from blueberry.tests.gd.cert.context import get_current_context -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_address_types -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test -from blueberry.tests.sl4a_sl4a.lib.security import Security -from mobly import test_runner - - -class LeScanningTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass): - - def __get_cert_public_address_and_irk_from_bt_config(self): - # Pull IRK from SL4A cert side to pass in from SL4A DUT side when scanning - bt_config_file_path = os.path.join(get_current_context().get_full_output_path(), - "DUT_%s_bt_config.conf" % self.cert.serial) - try: - self.cert.adb.pull(["/data/misc/bluedroid/bt_config.conf", bt_config_file_path]) - except AdbError as error: - logging.error("Failed to pull SL4A cert BT config") - return False - logging.debug("Reading SL4A cert BT config") - with io.open(bt_config_file_path) as f: - for line in f.readlines(): - stripped_line = line.strip() - if (stripped_line.startswith("Address")): - address_fields = stripped_line.split(' ') - # API currently requires public address to be capitalized - address = address_fields[2].upper() - logging.debug("Found cert address: %s" % address) - continue - if (stripped_line.startswith("LE_LOCAL_KEY_IRK")): - irk_fields = stripped_line.split(' ') - irk = irk_fields[2] - logging.debug("Found cert IRK: %s" % irk) - continue - - return address, irk - - def setup_class(self): - super().setup_class() - - def setup_test(self): - assertThat(super().setup_test()).isTrue() - - def teardown_test(self): - super().teardown_test() - - def test_scan_result_address(self): - cert_public_address, irk = self.__get_cert_public_address_and_irk_from_bt_config() - self.cert_advertiser_.advertise_public_extended_pdu() - advertising_name = self.cert_advertiser_.get_local_advertising_name() - - # Scan with name and verify we get back a scan result with the RPA - scan_result_addr = self.dut_scanner_.scan_for_name(advertising_name) - assertThat(scan_result_addr).isNotNone() - assertThat(scan_result_addr).isNotEqualTo(cert_public_address) - - # Bond - logging.info("Bonding with %s", scan_result_addr) - self.dut_security_.create_bond_numeric_comparison(scan_result_addr) - self.dut_scanner_.stop_scanning() - - # Start advertising again and scan for identity address - scan_result_addr = self.dut_scanner_.scan_for_address(cert_public_address, ble_address_types["public"]) - assertThat(scan_result_addr).isNotNone() - assertThat(scan_result_addr).isNotEqualTo(cert_public_address) - - # Teardown advertiser and scanner - self.dut_scanner_.stop_scanning() - self.cert_advertiser_.stop_advertising() - - -if __name__ == '__main__': - test_runner.main() \ No newline at end of file diff --git a/system/blueberry/tests/sl4a_sl4a/security/irk_rotation_test.py b/system/blueberry/tests/sl4a_sl4a/security/irk_rotation_test.py deleted file mode 100644 index 982826956e3..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/security/irk_rotation_test.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import binascii -import io -import logging -import os -import queue - -from blueberry.facade import common_pb2 as common -from blueberry.tests.gd.cert.context import get_current_context -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.gd_sl4a.lib.ble_lib import disable_bluetooth -from blueberry.tests.gd_sl4a.lib.ble_lib import enable_bluetooth -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_address_types -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test -from blueberry.tests.sl4a_sl4a.lib.security import Security -from blueberry.utils.bt_gatt_constants import GattCallbackString -from blueberry.utils.bt_gatt_constants import GattTransport -from mobly import test_runner - - -class IrkRotationTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass): - - def setup_class(self): - super().setup_class() - self.default_timeout = 10 # seconds - - def setup_test(self): - assertThat(super().setup_test()).isTrue() - - def teardown_test(self): - current_test_dir = get_current_context().get_full_output_path() - self.cert.adb.pull([ - "/data/misc/bluetooth/logs/btsnoop_hci.log", - os.path.join(current_test_dir, "CERT_%s_btsnoop_hci.log" % self.cert.serial) - ]) - self.cert.adb.pull([ - "/data/misc/bluetooth/logs/btsnoop_hci.log.last", - os.path.join(current_test_dir, "CERT_%s_btsnoop_hci.log.last" % self.cert.serial) - ]) - super().teardown_test() - self.cert.adb.shell("setprop bluetooth.core.gap.le.privacy.enabled \'\'") - - def _wait_for_event(self, expected_event_name, device): - try: - event_info = device.ed.pop_event(expected_event_name, self.default_timeout) - logging.info(event_info) - except queue.Empty as error: - logging.error("Failed to find event: %s", expected_event_name) - return False - return True - - def __get_cert_public_address_and_irk_from_bt_config(self): - # Pull IRK from SL4A cert side to pass in from SL4A DUT side when scanning - bt_config_file_path = os.path.join(get_current_context().get_full_output_path(), - "DUT_%s_bt_config.conf" % self.cert.serial) - try: - self.cert.adb.pull(["/data/misc/bluedroid/bt_config.conf", bt_config_file_path]) - except AdbError as error: - logging.error("Failed to pull SL4A cert BT config") - return False - logging.debug("Reading SL4A cert BT config") - with io.open(bt_config_file_path) as f: - for line in f.readlines(): - stripped_line = line.strip() - if (stripped_line.startswith("Address")): - address_fields = stripped_line.split(' ') - # API currently requires public address to be capitalized - address = address_fields[2].upper() - logging.debug("Found cert address: %s" % address) - continue - if (stripped_line.startswith("LE_LOCAL_KEY_IRK")): - irk_fields = stripped_line.split(' ') - irk = irk_fields[2] - logging.debug("Found cert IRK: %s" % irk) - continue - - return address, irk - - def __test_le_reconnect_after_irk_rotation_cert_privacy_enabled(self): - self._test_le_reconnect_after_irk_rotation(True) - - def test_le_reconnect_after_irk_rotation_cert_privacy_disabled(self): - self.cert.sl4a.bluetoothDisableBLE() - disable_bluetooth(self.cert.sl4a, self.cert.ed) - self.cert.adb.shell("setprop bluetooth.core.gap.le.privacy.enabled false") - self.cert.adb.shell("setprop log.tag.bluetooth VERBOSE") - enable_bluetooth(self.cert.sl4a, self.cert.ed) - self.cert.sl4a.bluetoothDisableBLE() - self._test_le_reconnect_after_irk_rotation(False) - - def _bond_remote_device(self, cert_privacy_enabled, cert_public_address): - if cert_privacy_enabled: - self.cert_advertiser_.advertise_public_extended_pdu() - else: - self.cert_advertiser_.advertise_public_extended_pdu(common.PUBLIC_DEVICE_ADDRESS) - - advertising_device_name = self.cert_advertiser_.get_local_advertising_name() - connect_address = self.dut_scanner_.scan_for_name(advertising_device_name) - - # Bond - logging.info("Bonding with %s", connect_address) - self.dut_security_.create_bond_numeric_comparison(connect_address) - self.dut_scanner_.stop_scanning() - self.cert_advertiser_.stop_advertising() - - return connect_address - - def _test_le_reconnect_after_irk_rotation(self, cert_privacy_enabled): - - cert_public_address, irk = self.__get_cert_public_address_and_irk_from_bt_config() - self._bond_remote_device(cert_privacy_enabled, cert_public_address) - - # Remove all bonded devices to rotate the IRK - logging.info("Unbonding all devices") - self.dut_security_.remove_all_bonded_devices() - self.cert_security_.remove_all_bonded_devices() - - # Bond again - logging.info("Rebonding remote device") - connect_address = self._bond_remote_device(cert_privacy_enabled, cert_public_address) - - # Connect GATT - logging.info("Connecting GATT to %s", connect_address) - gatt_callback = self.dut.sl4a.gattCreateGattCallback() - bluetooth_gatt = self.dut.sl4a.gattClientConnectGatt(gatt_callback, connect_address, False, - GattTransport.TRANSPORT_LE, False, None) - assertThat(bluetooth_gatt).isNotNone() - expected_event_name = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback) - assertThat(self._wait_for_event(expected_event_name, self.dut)).isTrue() - - # Close GATT connection - logging.info("Closing GATT connection") - self.dut.sl4a.gattClientClose(bluetooth_gatt) - - # Reconnect GATT - logging.info("Reconnecting GATT") - gatt_callback = self.dut.sl4a.gattCreateGattCallback() - bluetooth_gatt = self.dut.sl4a.gattClientConnectGatt(gatt_callback, connect_address, False, - GattTransport.TRANSPORT_LE, False, None) - assertThat(bluetooth_gatt).isNotNone() - expected_event_name = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback) - assertThat(self._wait_for_event(expected_event_name, self.dut)).isTrue() - - # Disconnect GATT - logging.info("Disconnecting GATT") - self.dut.sl4a.gattClientDisconnect(gatt_callback) - expected_event_name = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback) - assertThat(self._wait_for_event(expected_event_name, self.dut)).isTrue() - - # Reconnect GATT - logging.info("Reconnecting GATT") - self.dut.sl4a.gattClientReconnect(gatt_callback) - expected_event_name = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback) - assertThat(self._wait_for_event(expected_event_name, self.dut)).isTrue() - - -if __name__ == '__main__': - test_runner.main() diff --git a/system/blueberry/tests/sl4a_sl4a/security/oob_pairing_test.py b/system/blueberry/tests/sl4a_sl4a/security/oob_pairing_test.py deleted file mode 100644 index 63972a718b7..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/security/oob_pairing_test.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 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. - -import binascii -import io -import logging -import os -import queue -import time - -from blueberry.tests.gd.cert.context import get_current_context -from blueberry.tests.gd.cert.truth import assertThat -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_address_types -from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test -from blueberry.tests.sl4a_sl4a.lib.security import Security -from mobly import test_runner - - -class OobPairingTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass): - - def __get_cert_public_address_and_irk_from_bt_config(self): - # Pull IRK from SL4A cert side to pass in from SL4A DUT side when scanning - bt_config_file_path = os.path.join(get_current_context().get_full_output_path(), - "DUT_%s_bt_config.conf" % self.cert.serial) - try: - self.cert.adb.pull(["/data/misc/bluedroid/bt_config.conf", bt_config_file_path]) - except AdbError as error: - logging.error("Failed to pull SL4A cert BT config") - return False - logging.debug("Reading SL4A cert BT config") - with io.open(bt_config_file_path) as f: - for line in f.readlines(): - stripped_line = line.strip() - if (stripped_line.startswith("Address")): - address_fields = stripped_line.split(' ') - # API currently requires public address to be capitalized - address = address_fields[2].upper() - logging.debug("Found cert address: %s" % address) - continue - if (stripped_line.startswith("LE_LOCAL_KEY_IRK")): - irk_fields = stripped_line.split(' ') - irk = irk_fields[2] - logging.debug("Found cert IRK: %s" % irk) - continue - - return address, irk - - def __get_dut_public_address_and_irk_from_bt_config(self): - # Pull IRK from SL4A dut side - bt_config_file_path = os.path.join(get_current_context().get_full_output_path(), - "DUT_%s_bt_config.conf" % self.dut.serial) - try: - self.dut.adb.pull(["/data/misc/bluedroid/bt_config.conf", bt_config_file_path]) - except AdbError as error: - logging.error("Failed to pull SL4A dut BT config") - return False - logging.debug("Reading SL4A dut BT config") - with io.open(bt_config_file_path) as f: - for line in f.readlines(): - stripped_line = line.strip() - if (stripped_line.startswith("Address")): - address_fields = stripped_line.split(' ') - # API currently requires public address to be capitalized - address = address_fields[2].upper() - logging.debug("Found dut address: %s" % address) - continue - if (stripped_line.startswith("LE_LOCAL_KEY_IRK")): - irk_fields = stripped_line.split(' ') - irk = irk_fields[2] - logging.debug("Found dut IRK: %s" % irk) - continue - - return address, irk - - def setup_class(self): - super().setup_class() - - def setup_test(self): - assertThat(super().setup_test()).isTrue() - - def teardown_test(self): - super().teardown_test() - - def __test_scan(self, address_type="public"): - cert_public_address, irk = self.__get_cert_public_address_and_irk_from_bt_config() - rpa_address = self.cert_advertiser_.advertise_public_extended_pdu() - self.dut_scanner_.start_identity_address_scan(cert_public_address, ble_address_types[address_type]) - self.dut_scanner_.stop_scanning() - self.cert_advertiser_.stop_advertising() - - def __create_le_bond_oob_single_sided(self, wait_for_oob_data=True, wait_for_device_bonded=True): - oob_data = self.cert_security_.generate_oob_data(Security.TRANSPORT_LE, wait_for_oob_data) - if wait_for_oob_data: - assertThat(oob_data[0]).isEqualTo(0) - assertThat(oob_data[1]).isNotNone() - self.dut_security_.create_bond_out_of_band(oob_data[1], None, -1, wait_for_device_bonded) - - def __create_le_bond_oob_double_sided(self, wait_for_oob_data=True, wait_for_device_bonded=True): - # Genearte OOB data on DUT, but we don't use it - self.dut_security_.generate_oob_data(Security.TRANSPORT_LE, wait_for_oob_data) - self.__create_le_bond_oob_single_sided(wait_for_oob_data, wait_for_device_bonded) - - def test_classic_generate_local_oob_data(self): - oob_data = self.dut_security_.generate_oob_data(Security.TRANSPORT_BREDR) - assertThat(oob_data[0]).isEqualTo(0) - assertThat(oob_data[1]).isNotNone() - oob_data = self.dut_security_.generate_oob_data(Security.TRANSPORT_BREDR) - assertThat(oob_data[0]).isEqualTo(0) - assertThat(oob_data[1]).isNotNone() - - def test_classic_generate_local_oob_data_stress(self): - for i in range(1, 20): - self.test_classic_generate_local_oob_data() - - def test_le_generate_local_oob_data(self): - oob_data = self.dut_security_.generate_oob_data(Security.TRANSPORT_LE) - assertThat(oob_data[0]).isEqualTo(0) - assertThat(oob_data[1]).isNotNone() - oob_data = self.cert_security_.generate_oob_data(Security.TRANSPORT_LE) - assertThat(oob_data[0]).isEqualTo(0) - assertThat(oob_data[1]).isNotNone() - - def test_le_generate_local_oob_data_stress(self): - for i in range(1, 20): - self.test_le_generate_local_oob_data() - - def test_le_bond(self): - self.__create_le_bond_oob_single_sided() - - def test_le_bond_oob_stress(self): - for i in range(0, 10): - logging.info("Stress #%d" % i) - self.__create_le_bond_oob_single_sided() - self.dut_security_.remove_all_bonded_devices() - self.cert_security_.remove_all_bonded_devices() - - def test_le_generate_local_oob_data_after_le_bond_oob(self): - self.__create_le_bond_oob_single_sided() - self.test_le_generate_local_oob_data() - - def test_le_generate_oob_data_while_bonding(self): - self.__create_le_bond_oob_double_sided(True, False) - self.dut_security_.generate_oob_data(Security.TRANSPORT_LE, False) - for i in range(0, 10): - oob_data = self.dut_security_.generate_oob_data(Security.TRANSPORT_LE, True) - logging.info("OOB Data came back with code: %d", oob_data[0]) - - def test_le_oob_advertiser_not_using_public_address(self): - #TODO(optedoblivion): Use sysprop and make another test to handle non privacy case - oob_data = self.dut_security_.generate_oob_data(Security.TRANSPORT_LE) - assertThat(oob_data[0]).isEqualTo(0) - assertThat(oob_data[1]).isNotNone() - advertiser_address = oob_data[1].to_sl4a_address() - dut_public_address, dut_irk = self.__get_dut_public_address_and_irk_from_bt_config() - logging.info("DUT Advertiser Address: %s " % advertiser_address) - logging.info("DUT Public Address: %s " % dut_public_address) - assertThat(advertiser_address).isNotEqualTo(dut_public_address) - - -if __name__ == '__main__': - test_runner.main() diff --git a/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_device_config.yaml b/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_device_config.yaml deleted file mode 100644 index e96a272ea1c..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_device_config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_description: Bluetooth testing with SL4A -TestBeds: -- Name: AndroidDeviceCert - Controllers: - AndroidDevice: - - label: dut - # Preferred server port number forwarded from Android to the host PC - # via adb for SL4A connections - forwarded_port: '8897' - # Preferred server port used by SL4A on Android device - server_port: '8897' - serial: 'DUT' - - label: cert - # Preferred server port number forwarded from Android to the host PC - # via adb for SL4A connections - forwarded_port: '8899' - # Preferred server port used by SL4A on Android device - server_port: '8899' - serial: 'CERT' -logpath: "/tmp/logs" diff --git a/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py b/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py deleted file mode 100644 index 4dc099f20de..00000000000 --- a/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python3 -# -# 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. - -from blueberry.tests.sl4a_sl4a.advertising.le_advertising import LeAdvertisingTest -from blueberry.tests.sl4a_sl4a.gatt.gatt_connect_test import GattConnectTest -from blueberry.tests.sl4a_sl4a.gatt.gatt_connect_with_irk_test import GattConnectWithIrkTest -from blueberry.tests.sl4a_sl4a.gatt.gatt_notify_test import GattNotifyTest -from blueberry.tests.sl4a_sl4a.l2cap.le_l2cap_coc_test import LeL2capCoCTest -from blueberry.tests.sl4a_sl4a.scanning.le_scanning import LeScanningTest -from blueberry.tests.sl4a_sl4a.security.oob_pairing_test import OobPairingTest - -from mobly import suite_runner -import argparse - -ALL_TESTS = [ - GattConnectTest, - GattConnectWithIrkTest, - GattNotifyTest, - LeAdvertisingTest, - LeL2capCoCTest, - LeScanningTest, - OobPairingTest, -] - - -def main(): - """ - Local test runner that allows to specify list of tests to and customize - test config file location - """ - parser = argparse.ArgumentParser(description="Run local GD SL4A tests.") - parser.add_argument('-c', - '--config', - type=str, - required=True, - metavar='', - help='Path to the test configuration file.') - parser.add_argument('--tests', - '--test_case', - nargs='+', - type=str, - metavar='[ClassA[.test_a] ClassB[.test_b] ...]', - help='A list of test classes and optional tests to execute.') - parser.add_argument("--all_tests", "-A", type=bool, dest="all_tests", default=False, nargs="?") - parser.add_argument("--presubmit", type=bool, dest="presubmit", default=False, nargs="?") - parser.add_argument("--postsubmit", type=bool, dest="postsubmit", default=False, nargs="?") - args = parser.parse_args() - test_list = ALL_TESTS - if args.all_tests: - test_list = ALL_TESTS - elif args.presubmit: - test_list = ALL_TESTS - elif args.postsubmit: - test_list = ALL_TESTS - # Do not pass this layer's cmd line argument to next layer - argv = ["--config", args.config] - if args.tests: - argv.append("--tests") - for test in args.tests: - argv.append(test) - - suite_runner.run_suite(test_list, argv=argv) - - -if __name__ == "__main__": - main() diff --git a/system/blueberry/utils/bt_gatt_utils.py b/system/blueberry/utils/bt_gatt_utils.py index 6bb282ac41b..b59972778f2 100644 --- a/system/blueberry/utils/bt_gatt_utils.py +++ b/system/blueberry/utils/bt_gatt_utils.py @@ -31,7 +31,6 @@ from blueberry.utils.bt_gatt_constants import GattPhyMask from blueberry.utils.bt_gatt_constants import GattServiceType from blueberry.utils.bt_gatt_constants import GattTransport from blueberry.utils.bt_test_utils import BtTestUtilsError -from blueberry.utils.bt_test_utils import get_mac_address_of_generic_advertisement from mobly.controllers.android_device import AndroidDevice from mobly.controllers.android_device_lib.event_dispatcher import EventDispatcher from mobly.controllers.android_device_lib.sl4a_client import Sl4aClient @@ -114,27 +113,6 @@ def wait_for_gatt_disconnect_event(central: AndroidDevice, gatt_callback): return -def orchestrate_gatt_connection(central: AndroidDevice, - peripheral: AndroidDevice, - transport=GattTransport.TRANSPORT_LE, - mac_address=None, - autoconnect=False, - opportunistic=False): - adv_callback = None - if mac_address is None: - if transport == GattTransport.TRANSPORT_LE: - try: - mac_address, adv_callback, scan_callback = (get_mac_address_of_generic_advertisement( - central, peripheral)) - except BtTestUtilsError as err: - raise GattTestUtilsError("Error in getting mac address: {}".format(err)) - else: - mac_address = peripheral.sl4a.bluetoothGetLocalAddress() - adv_callback = None - bluetooth_gatt, gatt_callback = setup_gatt_connection(central, mac_address, autoconnect, transport, opportunistic) - return bluetooth_gatt, gatt_callback, adv_callback - - def run_continuous_write_descriptor(cen_droid: Sl4aClient, cen_ed: EventDispatcher, per_droid: Sl4aClient, diff --git a/system/blueberry/utils/bt_test_utils.py b/system/blueberry/utils/bt_test_utils.py index 414be14938a..33440d961c7 100644 --- a/system/blueberry/utils/bt_test_utils.py +++ b/system/blueberry/utils/bt_test_utils.py @@ -17,11 +17,6 @@ import wave from queue import Empty from typing import Optional -from blueberry.tests.gd_sl4a.lib.ble_lib import generate_ble_advertise_objects -from blueberry.tests.gd_sl4a.lib.bt_constants import adv_succ -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_advertise_settings_modes -from blueberry.tests.gd_sl4a.lib.bt_constants import ble_advertise_settings_tx_powers -from blueberry.tests.gd_sl4a.lib.bt_constants import bt_default_timeout from mobly.controllers.android_device import AndroidDevice @@ -204,71 +199,3 @@ def write_record_file(file_name, audio_params, frames): wf.setframerate(audio_params['sample_rate']) wf.writeframes(frames) wf.close() - - -def get_mac_address_of_generic_advertisement(scan_device, adv_device, adv_addr_type=None): - """Start generic advertisement and get it's mac address by LE scanning. - - Args: - scan_ad: The Android device to use as the scanner. - adv_device: The Android device to use as the advertiser. - adv_addr_type: The address type for the advertiser (refer to AdvertiseSettings.java) - - Returns: - mac_address: The mac address of the advertisement. - advertise_callback: The advertise callback id of the active - advertisement. - """ - adv_device.sl4a.bleSetAdvertiseDataIncludeDeviceName(True) - adv_device.sl4a.bleSetAdvertiseSettingsAdvertiseMode(ble_advertise_settings_modes['low_latency']) - adv_device.sl4a.bleSetAdvertiseSettingsIsConnectable(True) - adv_device.sl4a.bleSetAdvertiseSettingsTxPowerLevel(ble_advertise_settings_tx_powers['high']) - - if adv_addr_type is not None: - adv_device.sl4a.bleSetAdvertiseSettingsOwnAddressType(adv_addr_type) - - advertise_callback, advertise_data, advertise_settings = (generate_ble_advertise_objects(adv_device.sl4a)) - adv_device.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings) - try: - adv_device.ed.pop_event(adv_succ.format(advertise_callback), bt_default_timeout) - except Empty as err: - raise BtTestUtilsError("Advertiser did not start successfully {}".format(err)) - filter_list = scan_device.sl4a.bleGenFilterList() - scan_settings = scan_device.sl4a.bleBuildScanSetting() - scan_callback = scan_device.sl4a.bleGenScanCallback() - scan_device.sl4a.bleSetScanFilterDeviceName(adv_device.sl4a.bluetoothGetLocalName()) - scan_device.sl4a.bleBuildScanFilter(filter_list) - scan_device.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback) - try: - event = scan_device.sl4a.ed.pop_event("BleScan{}onScanResults".format(scan_callback), bt_default_timeout) - except Empty as err: - raise BtTestUtilsError("Scanner did not find advertisement {}".format(err)) - mac_address = event['data']['Result']['deviceInfo']['address'] - return mac_address, advertise_callback, scan_callback - - -def clear_bonded_devices(ad: AndroidDevice): - """Clear bonded devices from the input Android device. - - Args: - ad: the Android device performing the connection. - Returns: - True if clearing bonded devices was successful, false if unsuccessful. - """ - bonded_device_list = ad.sl4a.bluetoothGetBondedDevices() - while bonded_device_list: - device_address = bonded_device_list[0]['address'] - if not ad.sl4a.bluetoothUnbond(device_address): - ad.log.error("Failed to unbond {} from {}".format(device_address, ad.serial)) - return False - ad.log.info("Successfully unbonded {} from {}".format(device_address, ad.serial)) - #TODO: wait for BOND_STATE_CHANGED intent instead of waiting - time.sleep(1) - - # If device was first connected using LE transport, after bonding it is - # accessible through it's LE address, and through it classic address. - # Unbonding it will unbond two devices representing different - # "addresses". Attempt to unbond such already unbonded devices will - # result in bluetoothUnbond returning false. - bonded_device_list = ad.sl4a.bluetoothGetBondedDevices() - return True diff --git a/system/blueberry/utils/mobly_sl4a_utils.py b/system/blueberry/utils/mobly_sl4a_utils.py deleted file mode 100644 index 25d86cfac3a..00000000000 --- a/system/blueberry/utils/mobly_sl4a_utils.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2016 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. - -import logging - -import mobly.controllers.android_device_lib.sl4a_client as sl4a_client -from mobly.controllers.android_device import AndroidDevice -from mobly.controllers.android_device_lib.adb import AdbError -from mobly.controllers.android_device_lib.jsonrpc_client_base import AppRestoreConnectionError -from mobly.controllers.android_device_lib.services.sl4a_service import Sl4aService - - -class FakeFuture: - """ - A fake Future object to override default mobly behavior - """ - - def set_result(self, result): - logging.debug("Setting fake result {}".format(result)) - - -def setup_sl4a(device: AndroidDevice, server_port: int, forwarded_port: int): - """ - A method that setups up SL4A instance on mobly - :param device: an AndroidDevice instance - :param server_port: Preferred server port used by SL4A on Android device - :param forwarded_port: Preferred server port number forwarded from Android to - the host PC via adb for SL4A connections - :return: None - """ - sl4a_client._DEVICE_SIDE_PORT = server_port - sl4a_client._APP_START_WAIT_TIME = 0.5 - if device.sl4a is not None: - device.log.error("SL4A is not none when registering") - device.services.register('sl4a', Sl4aService, start_service=False) - # Start the SL4A service and event dispatcher - try: - device.sl4a.start() - except AppRestoreConnectionError as exp: - device.log.debug("AppRestoreConnectionError {}".format(exp)) - # Pause the dispatcher, but do not stop the service - try: - device.sl4a.pause() - except AdbError as exp: - device.log.debug("Failed to pause() {}".format(exp)) - sl4a_client._APP_START_WAIT_TIME = 2 * 60 - # Restart the service with a new host port - device.sl4a.restore_app_connection(port=forwarded_port) - - -def teardown_sl4a(device: AndroidDevice): - """ - A method to tear down SL4A interface on mobly - :param device: an AndroidDevice instance that already contains SL4a - :return: None - """ - if device.sl4a.is_alive: - # Both self.dut.sl4a and self.dut.sl4a.ed._sl4a are Sl4aClient instances - # If we do not set host_port to None here, host_poart will be removed twice from Android - # The 2nd removal will trigger and exception that spam the test result - # TODO: Resolve this issue in mobly - device.log.info("Clearing host_port to prevent mobly crash {}".format(device.sl4a._sl4a_client.host_port)) - device.sl4a._sl4a_client.host_port = None - # Moreover concurrent.Future.set_result() should never be called from thread that is - # waiting for the future. However, mobly calls it and cause InvalidStateError when it - # tries to do that after the thread pool has stopped, overriding it here - # TODO: Resolve this issue in mobly - try: - device.sl4a.ed.poller = FakeFuture() - except Exception as e: - print(e) - try: - # Guarded by is_alive internally - device.sl4a.stop() - except AdbError as exp: - device.log.warning("Failed top stop()".format(exp)) diff --git a/system/gd/cert/run b/system/gd/cert/run index 4aa006deee3..94708ff69cd 100755 --- a/system/gd/cert/run +++ b/system/gd/cert/run @@ -123,12 +123,6 @@ function parse_options { echo -e " Makes use of ashmem as best as possible for targeted speed increases." echo -e "${BLUE} --device${NOCOLOR}" echo -e " Run the test on the 2 real devices." - echo -e "${BLUE} --sl4a${NOCOLOR}" - echo -e " Run GD Sl4A combination tests using the default gd_sl4a config." - echo -e " Please install the correct SL4A build to DUT manually before running tests." - echo -e "${BLUE} --sl4a_sl4a${NOCOLOR}" - echo -e " Run SL$A combination tests using the default sl4a_sl4a config." - echo -e " Please install the correct SL4A build to DUT and cert manually before running tests." echo -e "${BLUE} --topshim${NOCOLOR}" echo -e " Run Topshim combination tests using the default topshim config." echo -e "${BLUE} --rust${NOCOLOR}" @@ -193,18 +187,6 @@ function parse_options { TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_host_config.yaml" shift # past argument ;; - --sl4a) - TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd_sl4a/gd_sl4a_device_config.yaml" - TEST_RUNNER="blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py" - DEVICE_TEST=true - shift # past argument - ;; - --sl4a_sl4a) - TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_device_config.yaml" - TEST_RUNNER="blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py" - DEVICE_TEST=true - shift # past argument - ;; --topshim) TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/topshim/topshim_host_config.yaml" TEST_RUNNER="blueberry/tests/topshim/topshim_test_runner.py" -- GitLab From 6c8f475e616362c35bc0a65fc1fd3836797b15a1 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Wed, 6 Nov 2024 01:43:02 +0000 Subject: [PATCH 580/875] system/stack/btu: Fix -Wmissing-prototype errors Bug: 369381361 Test: m com.android.btservices Flag: EXEMPT, no logical change Change-Id: I9f22d660df900ba7ab2a6faa04fd998e4fbe2da3 --- system/main/shim/shim.cc | 3 +- system/stack/Android.bp | 2 -- system/stack/BUILD.gn | 1 - system/stack/btu/btu_event.cc | 45 ------------------------- system/stack/btu/btu_hcif.cc | 36 ++++++++++++++------ system/stack/include/btu_hcif.h | 5 +-- system/test/mock/mock_bta_sys_main.cc | 5 --- system/test/mock/mock_bta_sys_main.h | 10 ------ system/test/mock/mock_btu_task.cc | 28 --------------- system/test/mock/mock_stack_btu_hcif.cc | 14 +------- 10 files changed, 30 insertions(+), 119 deletions(-) delete mode 100644 system/stack/btu/btu_event.cc delete mode 100644 system/test/mock/mock_btu_task.cc diff --git a/system/main/shim/shim.cc b/system/main/shim/shim.cc index af5eed03cb7..69c70cd9ba4 100644 --- a/system/main/shim/shim.cc +++ b/system/main/shim/shim.cc @@ -22,12 +22,11 @@ #include "main/shim/hci_layer.h" #include "main/shim/stack.h" +#include "stack/include/btu_hcif.h" #include "stack/include/main_thread.h" static const hci_t* hci; -void btu_hci_msg_process(BT_HDR* p_msg); - static void post_to_main_message_loop(BT_HDR* p_msg) { if (do_in_main_thread(base::Bind(&btu_hci_msg_process, p_msg)) != BT_STATUS_SUCCESS) { bluetooth::log::error("do_in_main_thread failed"); diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 4516dcbadbd..0a7b6521c69 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -273,7 +273,6 @@ cc_library_static { "btm/btm_sec_cb.cc", "btm/btm_security_client_interface.cc", "btm/security_event_parser.cc", - "btu/btu_event.cc", "btu/btu_hcif.cc", "connection_manager/connection_manager.cc", "eatt/eatt.cc", @@ -1990,7 +1989,6 @@ cc_test { ":TestMockStackL2cap", ":TestMockStackMetrics", ":TestMockStackSmp", - "btu/btu_event.cc", "btu/btu_hcif.cc", "btu/main_thread.cc", "test/stack_btu_test.cc", diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn index 559aa1f366c..dfbdd7db384 100644 --- a/system/stack/BUILD.gn +++ b/system/stack/BUILD.gn @@ -118,7 +118,6 @@ source_set("stack") { "btm/hfp_lc3_decoder_linux.cc", "btm/hfp_msbc_encoder.cc", "btm/hfp_msbc_decoder.cc", - "btu/btu_event.cc", "btu/btu_hcif.cc", "btu/main_thread.cc", "eatt/eatt.cc", diff --git a/system/stack/btu/btu_event.cc b/system/stack/btu/btu_event.cc deleted file mode 100644 index 02d701d6f61..00000000000 --- a/system/stack/btu/btu_event.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2023 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 "btm_iso_api.h" -#include "osi/include/allocator.h" -#include "stack/include/bt_hdr.h" -#include "stack/include/bt_types.h" -#include "stack/include/btu_hcif.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using bluetooth::hci::IsoManager; - -void btu_hci_msg_process(BT_HDR* p_msg) { - /* Determine the input message type. */ - switch (p_msg->event & BT_EVT_MASK) { - case BT_EVT_TO_BTU_HCI_EVT: - btu_hcif_process_event((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg); - osi_free(p_msg); - break; - - case BT_EVT_TO_BTU_HCI_ISO: - IsoManager::GetInstance()->HandleIsoData(p_msg); - osi_free(p_msg); - break; - - default: - osi_free(p_msg); - break; - } -} diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc index 9dc7d98bc26..7d8a0cd6180 100644 --- a/system/stack/btu/btu_hcif.cc +++ b/system/stack/btu/btu_hcif.cc @@ -36,10 +36,12 @@ #include +#include "btm_iso_api.h" #include "common/metrics.h" #include "internal_include/bt_target.h" #include "main/shim/hci_layer.h" #include "osi/include/allocator.h" +#include "stack/include/acl_api.h" #include "stack/include/acl_hci_link_interface.h" #include "stack/include/ble_hci_link_interface.h" #include "stack/include/bt_hdr.h" @@ -48,6 +50,7 @@ #include "stack/include/btm_iso_api.h" #include "stack/include/btm_sec_api_types.h" #include "stack/include/btm_status.h" +#include "stack/include/btu_hcif.h" #include "stack/include/dev_hci_link_interface.h" #include "stack/include/hci_error_code.h" #include "stack/include/hci_evt_length.h" @@ -60,18 +63,10 @@ #include "types/hci_role.h" #include "types/raw_address.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using namespace bluetooth; using base::Location; using bluetooth::hci::IsoManager; -bool BTM_BLE_IS_RESOLVE_BDA(const RawAddress& x); // TODO remove -void BTA_sys_signal_hw_error(); // TODO remove -void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason, - std::string comment); // TODO remove - /******************************************************************************/ /* L O C A L F U N C T I O N P R O T O T Y P E S */ /******************************************************************************/ @@ -212,7 +207,7 @@ static void btu_hcif_log_event_metrics(uint8_t evt_code, const uint8_t* p_event) * Returns void * ******************************************************************************/ -void btu_hcif_process_event(uint8_t /* controller_id */, const BT_HDR* p_msg) { +static void btu_hcif_process_event(uint8_t /* controller_id */, const BT_HDR* p_msg) { uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset; uint8_t hci_evt_code, hci_evt_len; uint8_t ble_sub_code; @@ -582,12 +577,12 @@ struct cmd_with_cb_data { base::Location posted_from; }; -void cmd_with_cb_data_init(cmd_with_cb_data* cb_wrapper) { +static void cmd_with_cb_data_init(cmd_with_cb_data* cb_wrapper) { new (&cb_wrapper->cb) hci_cmd_cb; new (&cb_wrapper->posted_from) Location; } -void cmd_with_cb_data_cleanup(cmd_with_cb_data* cb_wrapper) { +static void cmd_with_cb_data_cleanup(cmd_with_cb_data* cb_wrapper) { cb_wrapper->cb.~hci_cmd_cb(); cb_wrapper->posted_from.~Location(); } @@ -1443,3 +1438,22 @@ static void btu_ble_proc_ltk_req(uint8_t* p, uint16_t evt_len) { /********************************************** * End of BLE Events Handler **********************************************/ + +void btu_hci_msg_process(BT_HDR* p_msg) { + /* Determine the input message type. */ + switch (p_msg->event & BT_EVT_MASK) { + case BT_EVT_TO_BTU_HCI_EVT: + btu_hcif_process_event((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg); + osi_free(p_msg); + break; + + case BT_EVT_TO_BTU_HCI_ISO: + IsoManager::GetInstance()->HandleIsoData(p_msg); + osi_free(p_msg); + break; + + default: + osi_free(p_msg); + break; + } +} diff --git a/system/stack/include/btu_hcif.h b/system/stack/include/btu_hcif.h index 0053d9703d0..13ee0f1493f 100644 --- a/system/stack/include/btu_hcif.h +++ b/system/stack/include/btu_hcif.h @@ -26,11 +26,12 @@ /* Functions provided by btu_hcif.cc *********************************** */ -void btu_hcif_process_event(uint8_t controller_id, const BT_HDR* p_buf); void btu_hcif_send_cmd(uint8_t controller_id, const BT_HDR* p_msg); void btu_hcif_send_cmd_with_cb(const base::Location& posted_from, uint16_t opcode, uint8_t* params, uint8_t params_len, base::OnceCallback cb); +void btu_hci_msg_process(BT_HDR* p_msg); + namespace bluetooth::legacy::testing { void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status, const uint8_t* p_cmd); void btu_hcif_process_event(uint8_t /* controller_id */, const BT_HDR* p_msg); -} // namespace bluetooth::legacy::testing \ No newline at end of file +} // namespace bluetooth::legacy::testing diff --git a/system/test/mock/mock_bta_sys_main.cc b/system/test/mock/mock_bta_sys_main.cc index 709be46b211..dd7e10e6ea3 100644 --- a/system/test/mock/mock_bta_sys_main.cc +++ b/system/test/mock/mock_bta_sys_main.cc @@ -38,7 +38,6 @@ namespace mock { namespace bta_sys_main { // Function state capture and return values, if needed -struct BTA_sys_signal_hw_error BTA_sys_signal_hw_error; struct bta_sys_deregister bta_sys_deregister; struct bta_sys_disable bta_sys_disable; struct bta_sys_init bta_sys_init; @@ -53,10 +52,6 @@ struct bta_sys_start_timer bta_sys_start_timer; } // namespace test // Mocked functions, if any -void BTA_sys_signal_hw_error() { - inc_func_call_count(__func__); - test::mock::bta_sys_main::BTA_sys_signal_hw_error(); -} void bta_sys_deregister(uint8_t id) { inc_func_call_count(__func__); test::mock::bta_sys_main::bta_sys_deregister(id); diff --git a/system/test/mock/mock_bta_sys_main.h b/system/test/mock/mock_bta_sys_main.h index 0862d6d4cea..3dc24dd4c02 100644 --- a/system/test/mock/mock_bta_sys_main.h +++ b/system/test/mock/mock_bta_sys_main.h @@ -34,16 +34,6 @@ namespace test { namespace mock { namespace bta_sys_main { -// Shared state between mocked functions and tests -// Name: BTA_sys_signal_hw_error -// Params: -// Return: void -struct BTA_sys_signal_hw_error { - std::function body{[]() {}}; - void operator()() { body(); } -}; -extern struct BTA_sys_signal_hw_error BTA_sys_signal_hw_error; - // Name: bta_sys_deregister // Params: uint8_t id // Return: void diff --git a/system/test/mock/mock_btu_task.cc b/system/test/mock/mock_btu_task.cc deleted file mode 100644 index bf5bf2a314e..00000000000 --- a/system/test/mock/mock_btu_task.cc +++ /dev/null @@ -1,28 +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:7 - */ - -#include "stack/include/bt_hdr.h" -#include "test/common/mock_functions.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -void btu_hci_msg_process(BT_HDR* /* p_msg */) { inc_func_call_count(__func__); } diff --git a/system/test/mock/mock_stack_btu_hcif.cc b/system/test/mock/mock_stack_btu_hcif.cc index 4fecd7bcc2c..0a4da4bc036 100644 --- a/system/test/mock/mock_stack_btu_hcif.cc +++ b/system/test/mock/mock_stack_btu_hcif.cc @@ -28,20 +28,9 @@ #include "stack/include/btu_hcif.h" #include "test/common/mock_functions.h" -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - using hci_cmd_cb = base::OnceCallback; -struct cmd_with_cb_data { - hci_cmd_cb cb; - base::Location posted_from; -}; - -void btu_hcif_process_event(uint8_t /* controller_id */, BT_HDR* /* p_msg */) { - inc_func_call_count(__func__); -} void btu_hcif_send_cmd(uint8_t /* controller_id */, const BT_HDR* /* p_buf */) { inc_func_call_count(__func__); } @@ -50,5 +39,4 @@ void btu_hcif_send_cmd_with_cb(const base::Location& /* posted_from */, uint16_t hci_cmd_cb /* cb */) { inc_func_call_count(__func__); } -void cmd_with_cb_data_cleanup(cmd_with_cb_data* /* cb_wrapper */) { inc_func_call_count(__func__); } -void cmd_with_cb_data_init(cmd_with_cb_data* /* cb_wrapper */) { inc_func_call_count(__func__); } +void btu_hci_msg_process(BT_HDR* /* p_msg */) { inc_func_call_count(__func__); } -- GitLab From 5dbc960daff38d83f3c1d78fb483eb2983e7d2ee Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 5 Nov 2024 20:13:47 -0800 Subject: [PATCH 581/875] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ia5c6dac31d2f6d4071b006c1328c83ef83179f40 --- android/app/res/values-in/strings_sap.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/res/values-in/strings_sap.xml b/android/app/res/values-in/strings_sap.xml index a5cb0b7ba3d..ad3f786cc64 100644 --- a/android/app/res/values-in/strings_sap.xml +++ b/android/app/res/values-in/strings_sap.xml @@ -5,6 +5,6 @@ "Akses SIM Bluetooth" "Minta klien untuk memutus sambungan?" "Menunggu klien untuk memutus sambungan" - "Putuskan koneksi" + "Berhenti hubungkan" "Putuskan paksa sambungan" -- GitLab From 0ae282244f1fee0b2146d541406c1436a3b9eaa2 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 5 Nov 2024 20:14:13 -0800 Subject: [PATCH 582/875] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Id3c7bcd6f3f53a5314df123cbdbde28fd9168046 --- android/app/res/values-bs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/res/values-bs/strings.xml b/android/app/res/values-bs/strings.xml index 6a3e9f10bcc..cd9f65c9291 100644 --- a/android/app/res/values-bs/strings.xml +++ b/android/app/res/values-bs/strings.xml @@ -102,7 +102,7 @@ "%1$s Slanje dovršeno." "Dolazna prenošenja" "Odlazna prenošenja" - "Historija prijenosa je prazna." + "Historija prenosa je prazna." "Sve stavke će biti izbrisane sa spiska." "Bluetooth dijeljenje: poslani fajlovi" "Bluetooth dijeljenje: primljeni fajlovi" -- GitLab From 64d465969a8d632aeb259f65a122a6afb3fa1470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 6 Nov 2024 10:34:25 +0000 Subject: [PATCH 583/875] leaudio: Fix removing CISes from the local storage Remove reduntant UpdateConfiguration call to connection manager when there is no active cises. Also make sure that cig structure is updated before connection_manager is called, as connection manager is getting CIS state from this structure. Bug: 331775328 Flag: EXEMPT, regression tested with unit tests. Test: atest bluetooth_le_audio_test Change-Id: Ib9933baabf36c6aa424aaf42b1ccaeb0f89bb6cd --- system/bta/le_audio/device_groups.cc | 38 +++---- system/bta/le_audio/state_machine_test.cc | 122 ++++++++++++++++++++++ 2 files changed, 141 insertions(+), 19 deletions(-) diff --git a/system/bta/le_audio/device_groups.cc b/system/bta/le_audio/device_groups.cc index 2eda1feee23..0a99c9abd91 100644 --- a/system/bta/le_audio/device_groups.cc +++ b/system/bta/le_audio/device_groups.cc @@ -1891,29 +1891,29 @@ void LeAudioDeviceGroup::RemoveCisFromStreamIfNeeded(LeAudioDevice* leAudioDevic stream_conf.stream_params.source.num_of_devices, stream_conf.stream_params.source.num_of_channels); - if (stream_conf.stream_params.sink.num_of_channels == 0) { - ClearSinksFromConfiguration(); - } + cig.UnassignCis(leAudioDevice, cis_conn_hdl); - if (stream_conf.stream_params.source.num_of_channels == 0) { - ClearSourcesFromConfiguration(); + if (old_sink_channels > 0) { + if (stream_conf.stream_params.sink.num_of_channels == 0) { + ClearSinksFromConfiguration(); + } else if (old_sink_channels > stream_conf.stream_params.sink.num_of_channels) { + CodecManager::GetInstance()->UpdateCisConfiguration( + cig.cises, + stream_conf.stream_params.get(bluetooth::le_audio::types::kLeAudioDirectionSink), + bluetooth::le_audio::types::kLeAudioDirectionSink); + } } - /* Update CodecManager CIS configuration */ - if (old_sink_channels > stream_conf.stream_params.sink.num_of_channels) { - CodecManager::GetInstance()->UpdateCisConfiguration( - cig.cises, - stream_conf.stream_params.get(bluetooth::le_audio::types::kLeAudioDirectionSink), - bluetooth::le_audio::types::kLeAudioDirectionSink); - } - if (old_source_channels > stream_conf.stream_params.source.num_of_channels) { - CodecManager::GetInstance()->UpdateCisConfiguration( - cig.cises, - stream_conf.stream_params.get(bluetooth::le_audio::types::kLeAudioDirectionSource), - bluetooth::le_audio::types::kLeAudioDirectionSource); + if (old_source_channels > 0) { + if (stream_conf.stream_params.source.num_of_channels == 0) { + ClearSourcesFromConfiguration(); + } else if (old_source_channels > stream_conf.stream_params.source.num_of_channels) { + CodecManager::GetInstance()->UpdateCisConfiguration( + cig.cises, + stream_conf.stream_params.get(bluetooth::le_audio::types::kLeAudioDirectionSource), + bluetooth::le_audio::types::kLeAudioDirectionSource); + } } - - cig.UnassignCis(leAudioDevice, cis_conn_hdl); } bool LeAudioDeviceGroup::IsPendingConfiguration(void) const { diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index dc601a5b409..7593bdeaf51 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -3459,6 +3459,9 @@ TEST_F(StateMachineTest, testReleaseSingle) { EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1); EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1); + EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0); + EXPECT_CALL(*mock_codec_manager_, ClearCisConfiguration(_)).Times(0); + InjectInitialIdleNotification(group); // Start the configuration and stream Media content @@ -3469,6 +3472,9 @@ TEST_F(StateMachineTest, testReleaseSingle) { // Check if group has transitioned to a proper state ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + + testing::Mock::VerifyAndClearExpectations(mock_codec_manager_); + reset_mock_function_count_map(); // Validate GroupStreamStatus EXPECT_CALL(mock_callbacks_, @@ -3477,11 +3483,24 @@ TEST_F(StateMachineTest, testReleaseSingle) { StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE)); // Stop the stream + EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0); + + /* ClearCisConfiguration is called for each direction unconditionaly when stream goes to idle. + * In addition, it is called when handling CIS disconnection and here we want Sink to be called. + */ + EXPECT_CALL(*mock_codec_manager_, + ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSink)) + .Times(2); + EXPECT_CALL(*mock_codec_manager_, + ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSource)) + .Times(1); + LeAudioGroupStateMachine::Get()->StopStream(group); // Check if group has transitioned to a proper state ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + testing::Mock::VerifyAndClearExpectations(mock_codec_manager_); } TEST_F(StateMachineTest, testReleaseCachingSingle) { @@ -3815,6 +3834,87 @@ static void InjectCisDisconnected(LeAudioDeviceGroup* group, LeAudioDevice* leAu } } +TEST_F(StateMachineTest, testStartAndStopStreamConversational_VerifyCodecManagerCallsOnCisRemoval) { + const auto context_type = kContextTypeConversational; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + // Prepare multiple fake connected devices in a group + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareReceiverStartReadyHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + + auto* leAudioDevice = group->GetFirstDevice(); + + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4); + EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2); + EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1); + + InjectInitialIdleNotification(group); + + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)) + .Times(1); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream(group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + reset_mock_function_count_map(); + + // Validate GroupStreamStatus + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING)); + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE)); + + // This is called when 1 CIS got disconnected. + EXPECT_CALL(mock_callbacks_, + StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING)) + .Times(1); + + EXPECT_CALL(*mock_codec_manager_, + UpdateCisConfiguration(_, _, bluetooth::le_audio::types::kLeAudioDirectionSink)) + .Times(1); + EXPECT_CALL(*mock_codec_manager_, + UpdateCisConfiguration(_, _, bluetooth::le_audio::types::kLeAudioDirectionSource)) + .Times(1); + EXPECT_CALL(*mock_codec_manager_, ClearCisConfiguration(_)).Times(0); + + InjectCisDisconnected(group, leAudioDevice, HCI_ERR_PEER_USER); + testing::Mock::VerifyAndClearExpectations(mock_codec_manager_); + + // Stop the stream + EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0); + EXPECT_CALL(*mock_codec_manager_, + ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSink)) + .Times(2); + EXPECT_CALL(*mock_codec_manager_, + ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSource)) + .Times(2); + + LeAudioGroupStateMachine::Get()->StopStream(group); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + testing::Mock::VerifyAndClearExpectations(mock_codec_manager_); +} + TEST_F(StateMachineTest, testReleaseMultiple_CisDisconnectedBeforeGettingToIdleState) { const auto context_type = kContextTypeMedia; const auto leaudio_group_id = 6; @@ -4189,6 +4289,10 @@ TEST_F(StateMachineTest, testReleaseBidirectional) { EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2); EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1); + // 1 for Sink and 1 for Source + EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0); + EXPECT_CALL(*mock_codec_manager_, ClearCisConfiguration(_)).Times(0); + InjectInitialIdleNotification(group); // Start the configuration and stream Media content @@ -4201,14 +4305,32 @@ TEST_F(StateMachineTest, testReleaseBidirectional) { ASSERT_EQ(1, get_func_call_count("alarm_cancel")); reset_mock_function_count_map(); + testing::Mock::VerifyAndClearExpectations(mock_codec_manager_); + + group->PrintDebugState(); // Stop the stream + // This will be called once after first CIS is disconnected + EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(1); + + /* ClearCisConfiguration is called for each direction unconditionaly when stream goes to idle. + * In addition, it is called when handling CIS disconnection and here we want Sink and Source to + * be called. + */ + EXPECT_CALL(*mock_codec_manager_, + ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSink)) + .Times(2); + EXPECT_CALL(*mock_codec_manager_, + ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSource)) + .Times(2); + LeAudioGroupStateMachine::Get()->StopStream(group); // Check if group has transitioned to a proper state ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); ASSERT_EQ(1, get_func_call_count("alarm_cancel")); reset_mock_function_count_map(); + testing::Mock::VerifyAndClearExpectations(mock_codec_manager_); } TEST_F(StateMachineTest, testDisableAndReleaseBidirectional) { -- GitLab From 72d193930b245d86542f9612521b2bd68f5acb39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 30 Oct 2024 13:50:31 +0000 Subject: [PATCH 584/875] ActiveDeviceManager: Fix A2DP or HFP Active device changes to null When A2DP or HFP devices is removed from the Active Devices, it shall not inactivate LeAudioDevice when not needed. This is regression after: 7cdf85a0285 Updates active device policy to support dual mode audio Note: HFP case there is similar logic which also was fixed Bug: 367917846 Flag: Exempt, Obvious fix, regression tested with unit tests Test: atest ActiveDeviceManagerTest Change-Id: I6bb71abb746e68ec9a833f0756e4a3109bd101db --- .../btservice/ActiveDeviceManager.java | 59 ++++++++++++++----- .../btservice/ActiveDeviceManagerTest.java | 19 +++++- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java index 4b563ac248c..c75097f2267 100644 --- a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +++ b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java @@ -614,11 +614,24 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac if (device != null) { setHearingAidActiveDevice(null, true); } - if (Utils.isDualModeAudioEnabled() - && mAdapterService.isAllSupportedClassicAudioProfilesActive(device)) { - setLeAudioActiveDevice(device); - } else { - setLeAudioActiveDevice(null, true); + + if (Utils.isDualModeAudioEnabled()) { + if (device != null) { + boolean isDualModeDevice = + mAdapterService.isAllSupportedClassicAudioProfilesActive(device); + if (isDualModeDevice) { + setLeAudioActiveDevice(device); + } + } else { + boolean wasDualModeDevice = + mAdapterService.isAllSupportedClassicAudioProfilesActive( + mA2dpActiveDevice); + if (wasDualModeDevice) { + // remove LE audio active device when it was actived as dual mode device + // before + setLeAudioActiveDevice(null, true); + } + } } } // Just assign locally the new value @@ -677,28 +690,42 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac + device + ", mHfpActiveDevice=" + mHfpActiveDevice); + if (!Objects.equals(mHfpActiveDevice, device)) { if (device != null) { setHearingAidActiveDevice(null, true); } - if (Utils.isDualModeAudioEnabled() - && mAdapterService.isAllSupportedClassicAudioProfilesActive(device)) { - setLeAudioActiveDevice(device); - } else { + + if (Utils.isDualModeAudioEnabled()) { if (device != null) { - // remove LE audio active device when it is not null, and not dual mode - setLeAudioActiveDevice(null, true); + boolean isDualModeDevice = + mAdapterService.isAllSupportedClassicAudioProfilesActive(device); + if (isDualModeDevice) { + setLeAudioActiveDevice(device); + } } else { - Log.d( - TAG, - "HFP active device is null. Try to fallback to le audio active" - + " device"); + boolean wasDualModeDevice = + mAdapterService.isAllSupportedClassicAudioProfilesActive( + mA2dpActiveDevice); + if (wasDualModeDevice) { + // remove LE audio active device when it was actived as dual mode device + // before + setLeAudioActiveDevice(null, true); + } + + Log.d(TAG, "HFP active device is null. Try to fallback to le audio device"); synchronized (mLock) { - setFallbackDeviceActiveLocked(device); + setFallbackDeviceActiveLocked(null); } } + } else { + Log.d(TAG, "HFP active device is null. Try to fallback to le audio device"); + synchronized (mLock) { + setFallbackDeviceActiveLocked(null); + } } } + // Just assign locally the new value mHfpActiveDevice = device; diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index 9acb612ff05..6bd86827276 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -644,6 +644,20 @@ public class ActiveDeviceManagerTest { verify(mHeadsetService, never()).setActiveDevice(any()); } + @Test + public void a2dpDeactivated_makeSureToNotRemoveLeAudioDevice() { + a2dpActiveDeviceChanged(null); + mTestLooper.dispatchAll(); + verify(mLeAudioService, never()).removeActiveDevice(anyBoolean()); + } + + @Test + public void hfpDeactivated_makeSureToNotRemoveLeAudioDevice() { + headsetActiveDeviceChanged(null); + mTestLooper.dispatchAll(); + verify(mLeAudioService, never()).removeActiveDevice(anyBoolean()); + } + @Test public void a2dpActivated_whileActivatingA2dpHeadset() { a2dpConnected(mA2dpDevice, false); @@ -1477,9 +1491,8 @@ public class ActiveDeviceManagerTest { headsetActiveDeviceChanged(mDualModeAudioDevice); mTestLooper.dispatchAll(); - // When A2DP device is getting active, first LeAudio device is removed from active devices - // and later added - verify(mLeAudioService).removeActiveDevice(anyBoolean()); + // When Hfp device is getting active and it is dual mode device LeAudioDevice will be added. + verify(mLeAudioService, never()).removeActiveDevice(anyBoolean()); verify(mLeAudioService).setActiveDevice(mDualModeAudioDevice); Assert.assertEquals(mDualModeAudioDevice, mActiveDeviceManager.getA2dpActiveDevice()); -- GitLab From aecd84410678b6d2a1c25e6c1d72172981d64cde Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 31 Oct 2024 16:45:19 +0000 Subject: [PATCH 585/875] VolumeControl: Fix restoring earbuds volume If we stream to one earbud and the second earbud connects with a different volume level and a flag saying that it is a User-set volume is set, we should realign its volume to the existing stream volume that was probably already adjusted to the users liking. We should apply this new volume to the system only if this is the first earbud that has connected. To make sure there is no race between connection and volume state change events, we need to pass the volume event via the state machine just like the connection event is. Otherwise the order of events arrival in the service may differ from the order they were sent. Bug: 373377157 Test: atest GoogleBluetoothInstrumentationTests Flag: EXEMPT; Regression covered with unit test Change-Id: Ifec0ae193a32019e091380dcc7b23f5fe097211f --- .../bluetooth/vc/VolumeControlService.java | 31 ++++++++++++++----- .../bluetooth/vc/VolumeControlStackEvent.java | 2 -- .../vc/VolumeControlStateMachine.java | 22 ++++++++++--- .../vc/VolumeControlServiceTest.java | 15 ++++++--- 4 files changed, 53 insertions(+), 17 deletions(-) diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 23c287bd2d1..0629bb6ff06 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -785,12 +785,13 @@ public class VolumeControlService extends ProfileService { + (", flags: " + flags)); /* We are here, because system has just started and LeAudio device is connected. If * remote device has User Persistent flag set, Android sets the volume to local cache - * and to the audio system. + * and to the audio system if not already streaming to other devices. * If Reset Flag is set, then Android sets to remote devices either cached volume volume * taken from audio manager. * Note, to match BR/EDR behavior, don't show volume change in UI here */ - if ((flags & VOLUME_FLAGS_PERSISTED_USER_SET_VOLUME_MASK) == 0x01) { + if (((flags & VOLUME_FLAGS_PERSISTED_USER_SET_VOLUME_MASK) == 0x01) + && (getConnectedDevices().size() == 1)) { updateGroupCacheAndAudioSystem(groupId, volume, mute, false); return; } @@ -1138,12 +1139,12 @@ public class VolumeControlService extends ProfileService { input.setPropSettings(id, unit, min, max); } - void messageFromNative(VolumeControlStackEvent stackEvent) { + void handleStackEvent(VolumeControlStackEvent stackEvent) { if (!isAvailable()) { Log.e(TAG, "Event ignored, service not available: " + stackEvent); return; } - Log.d(TAG, "messageFromNative: " + stackEvent); + Log.d(TAG, "handleStackEvent: " + stackEvent); if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED) { handleVolumeControlChanged( @@ -1182,20 +1183,36 @@ public class VolumeControlService extends ProfileService { return; } + Log.e(TAG, "Unhandled event: " + stackEvent); + } + + void messageFromNative(VolumeControlStackEvent stackEvent) { + Log.d(TAG, "messageFromNative: " + stackEvent); + + // Group events should be handled here directly + boolean isGroupEvent = (stackEvent.device == null); + if (isGroupEvent) { + handleStackEvent(stackEvent); + return; + } + + // Other device events should be serialized via their state machines so they are processed + // in the same order they were sent from the native code. synchronized (mStateMachines) { - VolumeControlStateMachine sm = mStateMachines.get(device); + VolumeControlStateMachine sm = mStateMachines.get(stackEvent.device); if (sm == null) { if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { switch (stackEvent.valueInt1) { case STATE_CONNECTED, STATE_CONNECTING -> { - sm = getOrCreateStateMachine(device); + sm = getOrCreateStateMachine(stackEvent.device); } } } } if (sm == null) { - Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); + Log.w(TAG, "Cannot forward stack event: no state machine: " + stackEvent); + handleStackEvent(stackEvent); return; } sm.sendMessage(VolumeControlStateMachine.MESSAGE_STACK_EVENT, stackEvent); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index b1f28406318..e662921d5f1 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -102,8 +102,6 @@ public class VolumeControlStackEvent { private static String eventTypeValue2ToString(int type, int value) { switch (type) { - case EVENT_TYPE_CONNECTION_STATE_CHANGED: - return BluetoothProfile.getConnectionStateName(value); case EVENT_TYPE_VOLUME_STATE_CHANGED: return "{volume:" + value + "}"; case EVENT_TYPE_DEVICE_AVAILABLE: diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java index 1e1ca9aa167..71f520cbd9e 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStateMachine.java @@ -157,7 +157,10 @@ class VolumeControlStateMachine extends StateMachine { case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); } - default -> Log.e(TAG, "Disconnected: ignoring stack event: " + event); + default -> { + Log.e(TAG, "Disconnected: forwarding stack event: " + event); + mService.handleStackEvent(event); + } } } default -> { @@ -262,7 +265,14 @@ class VolumeControlStateMachine extends StateMachine { case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); } - default -> Log.e(TAG, "Connecting: ignoring stack event: " + event); + case VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED -> { + Log.w(TAG, "Defer volume change received while connecting: " + mDevice); + deferMessage(message); + } + default -> { + Log.e(TAG, "Connecting: forwarding stack event: " + event); + mService.handleStackEvent(event); + } } } default -> { @@ -355,7 +365,10 @@ class VolumeControlStateMachine extends StateMachine { case VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> { processConnectionEvent(event.valueInt1); } - default -> Log.e(TAG, "Disconnecting: ignoring stack event: " + event); + default -> { + Log.e(TAG, "Disconnecting: forwarding stack event: " + event); + mService.handleStackEvent(event); + } } } default -> { @@ -452,7 +465,8 @@ class VolumeControlStateMachine extends StateMachine { processConnectionEvent(event.valueInt1); } default -> { - Log.e(TAG, "Connected: ignoring stack event: " + event); + Log.e(TAG, "Connected: forwarding stack event: " + event); + mService.handleStackEvent(event); } } } 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 c7538991000..18388e1223d 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 @@ -610,8 +610,8 @@ public class VolumeControlServiceTest { (int) Math.round((double) (volumeDevice * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); - // Connect second device and read different volume. Expect it will be set to AF and to - // another set member + // Connect second device and read different volume. Expect it will NOT be set to AF + // and to another set member, but the existing volume gets applied to it generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); generateConnectionMessageFromNative(mDeviceTwo, STATE_CONNECTED, STATE_DISCONNECTED); assertThat(mService.getConnectionState(mDeviceTwo)).isEqualTo(STATE_CONNECTED); @@ -625,9 +625,12 @@ public class VolumeControlServiceTest { flags, initialMuteState, initialAutonomousFlag); - expectedAfVol = + + expectedAfVol = volumeDevice; + int unexpectedAfVol = (int) Math.round((double) (volumeDeviceTwo * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); - verify(mAudioManager).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); + verify(mAudioManager, times(0)).setStreamVolume(anyInt(), eq(unexpectedAfVol), anyInt()); + verify(mNativeInterface).setGroupVolume(eq(groupId), eq(expectedAfVol)); } private void testConnectedDeviceWithResetFlag( @@ -1276,6 +1279,7 @@ public class VolumeControlServiceTest { stackEvent.valueBool1 = mute; stackEvent.valueBool2 = isAutonomous; mService.messageFromNative(stackEvent); + mLooper.dispatchAll(); } private void generateDeviceOffsetChangedMessageFromNative( @@ -1288,6 +1292,7 @@ public class VolumeControlServiceTest { event.valueInt1 = extOffsetIndex; // external output index event.valueInt2 = offset; // offset value mService.messageFromNative(event); + mLooper.dispatchAll(); } private void generateDeviceLocationChangedMessageFromNative( @@ -1300,6 +1305,7 @@ public class VolumeControlServiceTest { event.valueInt1 = extOffsetIndex; // external output index event.valueInt2 = location; // location mService.messageFromNative(event); + mLooper.dispatchAll(); } private void generateDeviceDescriptionChangedMessageFromNative( @@ -1312,6 +1318,7 @@ public class VolumeControlServiceTest { event.valueInt1 = extOffsetIndex; // external output index event.valueString1 = description; // description mService.messageFromNative(event); + mLooper.dispatchAll(); } @SafeVarargs -- GitLab From 99c133635c1c458660903be1f5dba51368246fc9 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 3 Oct 2024 21:20:22 +0000 Subject: [PATCH 586/875] Supports back to back concurrent measurement. Uses different config ids for the requester and the responder Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 374950512 Test: m com.android.btservices Change-Id: Ic7f2d15d20a920e787f473cfab398649d0882236 --- system/gd/hci/distance_measurement_manager.cc | 121 +++++++++++++----- 1 file changed, 89 insertions(+), 32 deletions(-) diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 545fa4d7f2c..f9e2dc3fd11 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -49,7 +49,6 @@ static constexpr int8_t kRSSIDropOffAt1M = 41; static constexpr uint8_t kCsMaxTxPower = 10; // 10 dBm static constexpr CsSyncAntennaSelection kCsSyncAntennaSelection = CsSyncAntennaSelection::ANTENNAS_IN_ORDER; -static constexpr uint8_t kConfigId = 0x01; // Use 0x01 to create config and enable procedure static constexpr uint8_t kMinMainModeSteps = 0x02; static constexpr uint8_t kMaxMainModeSteps = 0x05; static constexpr uint8_t kMainModeRepetition = 0x00; // No repetition @@ -68,6 +67,8 @@ static constexpr uint8_t kProcedureDataBufferSize = 0x10; // Buffer size of Pro static constexpr uint16_t kMtuForRasData = 507; // 512 - 5 static constexpr uint16_t kRangingCounterMask = 0x0FFF; static constexpr uint8_t kInvalidConfigId = 0xFF; +static constexpr uint8_t kMinConfigId = 0; +static constexpr uint8_t kMaxConfigId = 3; static constexpr uint16_t kDefaultIntervalMs = 1000; // 1s static constexpr uint8_t kMaxRetryCounterForCreateConfig = 0x03; @@ -173,7 +174,6 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { bool measurement_ongoing = false; bool ras_connected = false; bool setup_complete = false; - bool config_set = false; uint8_t retry_counter_for_create_config = 0; uint16_t n_procedure_count = 0; CsMainModeType main_mode_type = CsMainModeType::MODE_2; @@ -181,7 +181,11 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { CsRttType rtt_type = CsRttType::RTT_AA_ONLY; bool remote_support_phase_based_ranging = false; uint8_t remote_num_antennas_supported_ = 0x01; - uint8_t config_id = kInvalidConfigId; + // sending from host to controller with CS config command, request the controller to use it. + uint8_t requesting_config_id = kInvalidConfigId; + // received from controller to host with CS config complete event, it will be used + // for the following measruement. + uint8_t used_config_id = kInvalidConfigId; uint8_t selected_tx_power = 0; std::vector procedure_data_list = {}; uint16_t interval_ms = kDefaultIntervalMs; @@ -192,6 +196,26 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { PacketViewForRecombination segment_data_; }; + bool get_free_config_id(uint16_t connection_handle, uint8_t& config_id) { + uint8_t requester_used_config_id = kInvalidConfigId; + if (cs_requester_trackers_.find(connection_handle) != cs_requester_trackers_.end()) { + requester_used_config_id = cs_requester_trackers_[connection_handle].used_config_id; + } + uint8_t responder_used_config_id = kInvalidConfigId; + if (cs_responder_trackers_.find(connection_handle) != cs_responder_trackers_.end()) { + responder_used_config_id = cs_responder_trackers_[connection_handle].used_config_id; + } + + for (auto i = kMinConfigId; i <= kMaxConfigId; i++) { + if (i != requester_used_config_id && i != responder_used_config_id) { + config_id = i; + return true; + } + } + log::warn("config ids are used up."); + return false; + } + void OnOpened( uint16_t connection_handle, const std::vector& vendor_specific_reply) { @@ -335,17 +359,28 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { it = cs_requester_trackers_.find(connection_handle); } it->second.address = cs_remote_address; + if (it->second.used_config_id == kInvalidConfigId) { + uint8_t config_id; + if (get_free_config_id(connection_handle, config_id)) { + it->second.requesting_config_id = config_id; + } else { + log::error("No config id available, stop"); + distance_measurement_callbacks_->OnDistanceMeasurementStopped( + cs_remote_address, REASON_INTERNAL_ERROR, METHOD_CS); + return; + } + } // make sure the repeating_alarm is initialized. if (it->second.repeating_alarm == nullptr) { it->second.repeating_alarm = std::make_unique(handler_); } + it->second.state = CsTrackerState::INIT; it->second.interval_ms = interval; it->second.local_start = true; it->second.measurement_ongoing = true; it->second.waiting_for_start_callback = true; it->second.local_hci_role = local_hci_role; - it->second.config_id = kConfigId; } void start_distance_measurement_with_cs(const Address& cs_remote_address, @@ -367,9 +402,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { send_le_cs_read_remote_supported_capabilities(connection_handle); return; } - if (!cs_requester_trackers_[connection_handle].config_set) { + if (cs_requester_trackers_[connection_handle].used_config_id == kInvalidConfigId) { send_le_cs_create_config(connection_handle, - cs_requester_trackers_[connection_handle].config_id); + cs_requester_trackers_[connection_handle].requesting_config_id); return; } log::info("enable cs procedure regularly with interval: {} ms", @@ -509,7 +544,6 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { it->second.address, identity_address); return; } - cs_responder_trackers_.erase(connection_handle); } @@ -709,7 +743,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } hci_layer_->EnqueueCommand( - LeCsProcedureEnableBuilder::Create(connection_handle, it->second.config_id, enable), + LeCsProcedureEnableBuilder::Create(connection_handle, it->second.used_config_id, + enable), handler_->BindOnceOn(this, &impl::on_cs_procedure_enable_command_status_cb, connection_handle, enable)); } @@ -782,10 +817,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { req_it->second.remote_num_antennas_supported_ = event_view.GetNumAntennasSupported(); req_it->second.setup_complete = true; log::info("Setup phase complete, connection_handle: {}, address: {}", connection_handle, - cs_requester_trackers_[connection_handle].address); + req_it->second.address); req_it->second.retry_counter_for_create_config = 0; - send_le_cs_create_config(connection_handle, - cs_requester_trackers_[connection_handle].config_id); + send_le_cs_create_config(connection_handle, req_it->second.requesting_config_id); } log::info( "connection_handle:{}, num_antennas_supported:{}, max_antenna_paths_supported:{}, " @@ -823,11 +857,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { return; } auto req_it = cs_requester_trackers_.find(connection_handle); - if (req_it != cs_requester_trackers_.end() && req_it->second.measurement_ongoing && - !req_it->second.config_set) { - req_it->second.config_set = true; + if (req_it != cs_requester_trackers_.end() && req_it->second.measurement_ongoing) { send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), - req_it->second.config_id, + req_it->second.used_config_id, req_it->second.remote_num_antennas_supported_); } auto res_it = cs_responder_trackers_.find(connection_handle); @@ -856,18 +888,22 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::info("send_le_cs_create_config, retry counter {}", cs_requester_trackers_[connection_handle].retry_counter_for_create_config); send_le_cs_create_config(connection_handle, - cs_requester_trackers_[connection_handle].config_id); + cs_requester_trackers_[connection_handle].requesting_config_id); } else { handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR); } return; } uint8_t config_id = event_view.GetConfigId(); + if (event_view.GetAction() == CsAction::CONFIG_REMOVED) { + on_cs_config_removed(connection_handle, config_id); + return; + } check_and_handle_conflict(connection_handle, config_id, CsTrackerState::WAIT_FOR_CONFIG_COMPLETE); - uint8_t valid_requester_states = static_cast(CsTrackerState::WAIT_FOR_CONFIG_COMPLETE); + auto valid_requester_states = static_cast(CsTrackerState::WAIT_FOR_CONFIG_COMPLETE); // any state, as the remote can start over at any time. - uint8_t valid_responder_states = static_cast(CsTrackerState::UNSPECIFIED); + auto valid_responder_states = static_cast(CsTrackerState::UNSPECIFIED); CsTracker* live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states, valid_responder_states); @@ -875,11 +911,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::warn("Can't find cs tracker for connection_handle {}", connection_handle); return; } - // assign the config_id, as this may be the 1st time to get the config_id from responder. - live_tracker->config_id = config_id; - if (event_view.GetAction() == CsAction::CONFIG_REMOVED) { - return; - } + + live_tracker->used_config_id = config_id; log::info("Get {}", event_view.ToString()); live_tracker->role = event_view.GetRole(); live_tracker->main_mode_type = event_view.GetMainModeType(); @@ -895,6 +928,21 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } + void on_cs_config_removed(uint16_t connection_handle, uint8_t config_id) { + // suppose it only has 1 requester and 1 responder per ACL. + auto req_it = cs_requester_trackers_.find(connection_handle); + if (req_it != cs_requester_trackers_.end() && req_it->second.used_config_id == config_id) { + req_it->second.used_config_id = kInvalidConfigId; + return; + } + auto res_it = cs_responder_trackers_.find(connection_handle); + if (res_it != cs_responder_trackers_.end() && res_it->second.used_config_id == config_id) { + res_it->second.used_config_id = kInvalidConfigId; + return; + } + log::warn("The removed config was not used, something was wrong."); + } + void on_cs_set_procedure_parameters(CommandCompleteView view) { auto complete_view = LeCsSetProcedureParametersCompleteView::Create(view); if (!complete_view.IsValid()) { @@ -930,17 +978,23 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { // CAVEAT: if the remote is sending request with the same config id, the behavior is undefined. auto req_it = cs_requester_trackers_.find(connection_handle); if (req_it != cs_requester_trackers_.end() && req_it->second.state != CsTrackerState::STOPPED && - req_it->second.config_id == config_id && (valid_requester_states & static_cast(req_it->second.state)) != 0) { - return &cs_requester_trackers_[connection_handle]; + uint8_t req_config_id = req_it->second.used_config_id; + if (req_it->second.state == CsTrackerState::WAIT_FOR_CONFIG_COMPLETE) { + req_config_id = req_it->second.requesting_config_id; + } + if (req_config_id == config_id) { + return &(req_it->second); + } } auto res_it = cs_responder_trackers_.find(connection_handle); if (res_it != cs_responder_trackers_.end() && - (res_it->second.config_id == kInvalidConfigId || res_it->second.config_id == config_id) && + (res_it->second.used_config_id == kInvalidConfigId || + res_it->second.used_config_id == config_id) && (valid_responder_states == static_cast(CsTrackerState::UNSPECIFIED) || (valid_responder_states & static_cast(res_it->second.state)) != 0)) { - return &cs_responder_trackers_[connection_handle]; + return &(res_it->second); } log::error("no valid tracker to handle the event."); return nullptr; @@ -955,14 +1009,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (it == cs_requester_trackers_.end()) { return; } - if (event_config_id != it->second.config_id) { + if (event_config_id != it->second.used_config_id) { return; } if (it->second.state == expected_requester_state) { return; } log::warn("unexpected request from remote, which is conflict with the local measurement."); - it->second.config_set = false; + it->second.used_config_id = kInvalidConfigId; if (it->second.state != CsTrackerState::STOPPED) { stop_distance_measurement(it->second.address, connection_handle, DistanceMeasurementMethod::METHOD_CS); @@ -1001,10 +1055,13 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::error("no tracker is available for {}", connection_handle); return; } + if (live_tracker->used_config_id != config_id) { + log::warn("config_id {} doesn't match the assigned one {}.", config_id, + live_tracker->used_config_id); + return; + } log::debug("Procedure enabled, {}", event_view.ToString()); live_tracker->state = CsTrackerState::STARTED; - // assign the config_id, as this is may be the 1st time to get it for responder; - live_tracker->config_id = config_id; live_tracker->selected_tx_power = event_view.GetSelectedTxPower(); live_tracker->n_procedure_count = event_view.GetProcedureCount(); @@ -1598,7 +1655,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } log::info("Create data for procedure_counter: {}", procedure_counter); - data_list.emplace_back(procedure_counter, num_antenna_paths, live_tracker->config_id, + data_list.emplace_back(procedure_counter, num_antenna_paths, live_tracker->used_config_id, live_tracker->selected_tx_power); // Check if sounding phase-based ranging is supported, and RTT type contains a sounding -- GitLab From 288279c59d28ff7b414444b53e9ecef6755d12d9 Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Mon, 4 Nov 2024 23:29:48 +0000 Subject: [PATCH 587/875] BQR: Do not enqueue HCI command binded to "null" callback instance. Bug: 365653608 Flag: EXEMPT, bug fix Test: m . Change-Id: Id955c06a7d25391b641d0e4bfaa200f8a56e662b --- system/btif/src/btif_bqr.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/system/btif/src/btif_bqr.cc b/system/btif/src/btif_bqr.cc index 765e7a73841..5e7eb73dad6 100644 --- a/system/btif/src/btif_bqr.cc +++ b/system/btif/src/btif_bqr.cc @@ -69,7 +69,8 @@ class BluetoothQualityReportInterfaceImpl; std::unique_ptr bluetoothQualityReportInstance; namespace { -common::PostableContext* to_bind_ = nullptr; +static std::recursive_mutex life_cycle_guard_; +static common::PostableContext* to_bind_ = nullptr; } void BqrVseSubEvt::ParseBqrLinkQualityEvt(uint8_t length, const uint8_t* p_param_buf) { @@ -385,6 +386,7 @@ void EnableBtQualityReport(common::PostableContext* to_bind) { void DisableBtQualityReport() { log::info(""); + std::unique_lock lock(life_cycle_guard_); if (to_bind_ == nullptr) { log::warn("Skipping second call (Lifecycle issue)."); return; @@ -480,6 +482,16 @@ static void BqrVscCompleteCallback(hci::CommandCompleteView complete) { return; } + { + // `DisableBtQualityReport()` set `to_bind_` at nullptr, after sending the command that clear + // reporting. When disabled, we don't want to continue and use nulled `to_bind_` (b/365653608). + std::unique_lock lock(life_cycle_guard_); + if (to_bind_ == nullptr) { + log::info("Disabled"); + return; + } + } + if (vendor_cap_supported_version >= kBqrVndLogVersion) { command_complete_param_len = 13; } -- GitLab From e645383ea1c57d5da40df7bd9f542b39c916bc2f Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Mon, 4 Nov 2024 23:49:02 +0000 Subject: [PATCH 588/875] HCI: Prevent usage of deleted instance Bug: 365653608 Flag: EXEMPT, bug fix Test: m . Change-Id: Ia2eb393dab94e45a058fb9f866ddbb01cc7578a4 --- system/gd/hci/hci_layer.cc | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc index f9847101c03..406d3e59431 100644 --- a/system/gd/hci/hci_layer.cc +++ b/system/gd/hci/hci_layer.cc @@ -59,6 +59,9 @@ using os::Alarm; using os::Handler; using std::unique_ptr; +static std::recursive_mutex life_cycle_guard; +static bool life_cycle_stopped = true; + static std::chrono::milliseconds getHciTimeoutMs() { static auto sHciTimeoutMs = std::chrono::milliseconds(bluetooth::os::GetSystemPropertyUint32Base( "bluetooth.hci.timeout_milliseconds", HciLayer::kHciTimeoutMs.count())); @@ -542,6 +545,10 @@ struct HciLayer::hal_callbacks : public hal::HciHalCallbacks { explicit hal_callbacks(HciLayer& module) : module_(module) {} void hciEventReceived(hal::HciPacket event_bytes) override { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } auto packet = packet::PacketView( std::make_shared>(event_bytes)); EventView event = EventView::Create(packet); @@ -549,6 +556,10 @@ struct HciLayer::hal_callbacks : public hal::HciHalCallbacks { } void aclDataReceived(hal::HciPacket data_bytes) override { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } auto packet = packet::PacketView( std::make_shared>(std::move(data_bytes))); auto acl = std::make_unique(AclView::Create(packet)); @@ -556,6 +567,10 @@ struct HciLayer::hal_callbacks : public hal::HciHalCallbacks { } void scoDataReceived(hal::HciPacket data_bytes) override { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } auto packet = packet::PacketView( std::make_shared>(std::move(data_bytes))); auto sco = std::make_unique(ScoView::Create(packet)); @@ -563,6 +578,10 @@ struct HciLayer::hal_callbacks : public hal::HciHalCallbacks { } void isoDataReceived(hal::HciPacket data_bytes) override { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } auto packet = packet::PacketView( std::make_shared>(std::move(data_bytes))); auto iso = std::make_unique(IsoView::Create(packet)); @@ -590,39 +609,71 @@ common::BidiQueueEnd* HciLayer::GetIsoQueueEnd() { void HciLayer::EnqueueCommand(unique_ptr command, ContextualOnceCallback on_complete) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::enqueue_command, std::move(command), std::move(on_complete)); } void HciLayer::EnqueueCommand(unique_ptr command, ContextualOnceCallback on_status) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::enqueue_command, std::move(command), std::move(on_status)); } void HciLayer::RegisterEventHandler(EventCode event, ContextualCallback handler) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::register_event, event, handler); } void HciLayer::UnregisterEventHandler(EventCode event) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::unregister_event, event); } void HciLayer::RegisterLeEventHandler(SubeventCode event, ContextualCallback handler) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::register_le_event, event, handler); } void HciLayer::UnregisterLeEventHandler(SubeventCode event) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::unregister_le_event, event); } void HciLayer::RegisterVendorSpecificEventHandler( VseSubeventCode event, ContextualCallback handler) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::register_vs_event, event, handler); } void HciLayer::UnregisterVendorSpecificEventHandler(VseSubeventCode event) { + std::unique_lock lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } CallOn(impl_, &impl::unregister_vs_event, event); } @@ -830,9 +881,11 @@ void HciLayer::ListDependencies(ModuleList* list) const { } void HciLayer::Start() { + std::unique_lock lock(life_cycle_guard); auto hal = GetDependency(); impl_ = new impl(hal, *this); hal_callbacks_ = new hal_callbacks(*this); + life_cycle_stopped = false; Handler* handler = GetHandler(); impl_->acl_queue_.GetDownEnd()->RegisterDequeue(handler, @@ -860,6 +913,7 @@ void HciLayer::StartWithNoHalDependencies(Handler* handler) { } void HciLayer::Stop() { + std::unique_lock lock(life_cycle_guard); auto hal = GetDependency(); hal->unregisterIncomingPacketCallback(); delete hal_callbacks_; @@ -868,6 +922,8 @@ void HciLayer::Stop() { impl_->sco_queue_.GetDownEnd()->UnregisterDequeue(); impl_->iso_queue_.GetDownEnd()->UnregisterDequeue(); delete impl_; + + life_cycle_stopped = true; } } // namespace hci -- GitLab From bfefb319effd1769113fe027458451bded0fb222 Mon Sep 17 00:00:00 2001 From: Chienyuan Huang Date: Fri, 1 Nov 2024 18:12:43 +0000 Subject: [PATCH 589/875] CS: Use half channels and increase max_procedure_counter when interval less than 1s Flag: com.android.bluetooth.flags.channel_sounding_in_stack Bug: 324185011 Bug: 369478354 Test: m com.android.btservice Change-Id: I4dae9fa1420fe72013b729aec4cf8116d9c40db4 --- .../gatt/DistanceMeasurementManager.java | 2 +- system/gd/hci/distance_measurement_manager.cc | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java index f9f3cc14007..1b78fef4e54 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java @@ -46,7 +46,7 @@ public class DistanceMeasurementManager { private static final int RSSI_HIGH_FREQUENCY_INTERVAL_MS = 500; private static final int CS_LOW_FREQUENCY_INTERVAL_MS = 5000; private static final int CS_MEDIUM_FREQUENCY_INTERVAL_MS = 3000; - private static final int CS_HIGH_FREQUENCY_INTERVAL_MS = 1000; + private static final int CS_HIGH_FREQUENCY_INTERVAL_MS = 200; private final AdapterService mAdapterService; private HandlerThread mHandlerThread; diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 08fe9fb193b..fc93fa9232b 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -186,6 +186,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { uint8_t selected_tx_power = 0; std::vector procedure_data_list = {}; uint16_t interval_ms = kDefaultIntervalMs; + uint16_t max_procedure_count = 1; bool waiting_for_start_callback = false; std::unique_ptr repeating_alarm = nullptr; // RAS data @@ -341,6 +342,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { it->second.repeating_alarm = std::make_unique(handler_); } it->second.state = CsTrackerState::INIT; + // If the interval is less than 1 second, update it to 1 second and increase the + // max_procedure_count + if (interval < 1000) { + it->second.max_procedure_count = 1000 / interval; + interval = 1000; + log::info("Update interval to 1s and max_procedure_count to {}", + it->second.max_procedure_count); + } it->second.interval_ms = interval; it->second.local_start = true; it->second.measurement_ongoing = true; @@ -618,7 +627,11 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { log::warn("no cs tracker found for {}", connection_handle); } cs_requester_trackers_[connection_handle].state = CsTrackerState::WAIT_FOR_CONFIG_COMPLETE; - auto channel_vector = common::FromHexString("1FFFFFFFFFFFFC7FFFFC"); // use all 72 Channel + auto channel_vector = common::FromHexString("1FFFFFFFFFFFFC7FFFFC"); // use all 72 Channels + // If the interval is less than or equal to 1 second, then use half channels + if (cs_requester_trackers_[connection_handle].interval_ms <= 1000) { + channel_vector = common::FromHexString("15555555555554555554"); + } std::array channel_map; std::copy(channel_vector->begin(), channel_vector->end(), channel_map.begin()); std::reverse(channel_map.begin(), channel_map.end()); @@ -656,8 +669,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { hci_layer_->EnqueueCommand( LeCsSetProcedureParametersBuilder::Create( connection_handle, config_id, kMaxProcedureLen, kMinProcedureInterval, - kMaxProcedureInterval, kMaxProcedureCount, kMinSubeventLen, kMaxSubeventLen, - tone_antenna_config_selection, CsPhy::LE_1M_PHY, kTxPwrDelta, + kMaxProcedureInterval, + cs_requester_trackers_[connection_handle].max_procedure_count, kMinSubeventLen, + kMaxSubeventLen, tone_antenna_config_selection, CsPhy::LE_1M_PHY, kTxPwrDelta, preferred_peer_antenna, CsSnrControl::NOT_APPLIED, CsSnrControl::NOT_APPLIED), handler_->BindOnceOn(this, &impl::on_cs_set_procedure_parameters)); } -- GitLab From cc4b7636e0450bf06fa89441f67c9d384b234874 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Wed, 6 Nov 2024 19:13:44 +0000 Subject: [PATCH 590/875] Do not update device properties of already bonded devices Data from advertisements and inquiry results should not be used to update device properties of already bonded devices. Change-Id: Ic1f6caa5d243fd3ea5dca32c04200d8411b53668 Ignore-AOSP-First: security Flag: com.android.bluetooth.flags.guard_bonded_device_properties Test: mmm packages/modules/Bluetooth Bug: 376927763 Bug: 376928594 --- system/btif/src/btif_dm.cc | 26 ++++++++++++++++++++++++- system/main/shim/le_scanning_manager.cc | 12 +++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 102242545b3..1cf1bc35dfc 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -1325,6 +1325,31 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* } break; case BTA_DM_INQ_RES_EVT: { + RawAddress& bdaddr = p_search_data->inq_res.bd_addr; + + // Do not update device properties of already bonded devices. + if (com::android::bluetooth::flags::guard_bonded_device_properties() && + btm_sec_is_a_bonded_dev(bdaddr)) { + log::debug("Ignore device properties from discovery results for the bonded device: {}", + bdaddr); + + bool restrict_report = + osi_property_get_bool("bluetooth.restrict_discovered_device.enabled", false); + if (restrict_report && p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE && + !(p_search_data->inq_res.ble_evt_type & BTM_BLE_CONNECTABLE_MASK)) { + log::debug("Ble device {} is not connectable", bdaddr); + break; + } + + bt_property_t bt_property[] = { + {BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr}, + {BT_PROPERTY_REMOTE_RSSI, sizeof(p_search_data->inq_res.rssi), + &(p_search_data->inq_res.rssi)}}; + GetInterfaceToProfiles()->events->invoke_device_found_cb(ARRAY_SIZE(bt_property), + bt_property); + break; + } + /* inquiry result */ bt_bdname_t bdname; uint8_t remote_name_len = 0; @@ -1335,7 +1360,6 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_search_data->inq_res.remt_name_not_required = check_eir_remote_name(p_search_data, NULL, NULL); } - RawAddress& bdaddr = p_search_data->inq_res.bd_addr; log::verbose("addr:{} device_type=0x{:x}", bdaddr, p_search_data->inq_res.device_type); bdname.name[0] = 0; diff --git a/system/main/shim/le_scanning_manager.cc b/system/main/shim/le_scanning_manager.cc index 3f5f4ad07ad..f4eba9fcc74 100644 --- a/system/main/shim/le_scanning_manager.cc +++ b/system/main/shim/le_scanning_manager.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "btif/include/btif_common.h" @@ -37,6 +38,7 @@ #include "stack/include/advertise_data_parser.h" #include "stack/include/bt_dev_class.h" #include "stack/include/btm_log_history.h" +#include "stack/include/btm_sec_api.h" #include "stack/include/btm_status.h" #include "storage/device.h" #include "storage/le_device.h" @@ -467,9 +469,13 @@ void BleScannerInterfaceImpl::OnScanResult(uint16_t event_type, uint8_t address_ btm_ble_process_adv_addr(raw_address, &ble_addr_type); } - do_in_jni_thread(base::BindOnce(&BleScannerInterfaceImpl::handle_remote_properties, - base::Unretained(this), raw_address, ble_addr_type, - advertising_data)); + // Do not update device properties of already bonded devices. + if (!com::android::bluetooth::flags::guard_bonded_device_properties() || + !btm_sec_is_a_bonded_dev(raw_address)) { + do_in_jni_thread(base::BindOnce(&BleScannerInterfaceImpl::handle_remote_properties, + base::Unretained(this), raw_address, ble_addr_type, + advertising_data)); + } do_in_jni_thread(base::BindOnce( &ScanningCallbacks::OnScanResult, base::Unretained(scanning_callbacks_), event_type, -- GitLab From 573b2d3074e4fa3110e3c4b5a4fe75624553c6ef Mon Sep 17 00:00:00 2001 From: Rongxuan Liu Date: Sat, 26 Oct 2024 03:48:44 +0000 Subject: [PATCH 591/875] [le audio] API broadcast to unicast fallback group changed callback onBroadcastToUnicastFallbackGroupChanged is introduced for app to get notified with broadcast to unicast fallback group update. Bug: 375421718 Bug: 375422410 Test: atest BluetoothLeAudioTest Test: atest LeAudioBroadcastServiceTest Change-Id: I02f0609c2f2c2da1b1472104253693131b05aebb --- .../bluetooth/IBluetoothLeAudioCallback.aidl | 1 + .../bluetooth/le_audio/LeAudioService.java | 26 +++++++++ .../le_audio/LeAudioBroadcastServiceTest.java | 54 +++++++++++++++++++ .../le_audio/LeAudioServiceTest.java | 15 ++++++ framework/api/system-current.txt | 1 + .../android/bluetooth/BluetoothLeAudio.java | 26 +++++++++ 6 files changed, 123 insertions(+) diff --git a/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl index 92ecfe814d4..f333405f5e4 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl @@ -32,4 +32,5 @@ oneway interface IBluetoothLeAudioCallback { void onGroupNodeRemoved(in BluetoothDevice device, int groupId); void onGroupStatusChanged(int groupId, int groupStatus); void onGroupStreamStatusChanged(int groupId, int groupStreamStatus); + void onBroadcastToUnicastFallbackGroupChanged(in int groupId); } 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 0683607ef5a..2e0a80c2df3 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -25,6 +25,7 @@ import static com.android.bluetooth.bass_client.BassConstants.INVALID_BROADCAST_ import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask; import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState; import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment; +import static com.android.bluetooth.flags.Flags.leaudioBroadcastApiManagePrimaryGroup; import static com.android.bluetooth.flags.Flags.leaudioUseAudioModeListener; import static com.android.modules.utils.build.SdkLevel.isAtLeastU; @@ -2943,6 +2944,22 @@ public class LeAudioService extends ProfileService { } } + private void notifyBroadcastToUnicastFallbackGroupChanged(int groupId) { + synchronized (mLeAudioCallbacks) { + int n = mLeAudioCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mLeAudioCallbacks + .getBroadcastItem(i) + .onBroadcastToUnicastFallbackGroupChanged(groupId); + } catch (RemoteException e) { + continue; + } + } + mLeAudioCallbacks.finishBroadcast(); + } + } + private void setGroupAllowedContextMask( int groupId, int sinkContextTypes, int sourceContextTypes) { if (!mLeAudioNativeIsInitialized) { @@ -5075,6 +5092,11 @@ public class LeAudioService extends ProfileService { * @param groupId group id to update */ private void updateFallbackUnicastGroupIdForBroadcast(int groupId) { + if (leaudioBroadcastApiManagePrimaryGroup() + && mUnicastGroupIdDeactivatedForBroadcastTransition == groupId) { + Log.d(TAG, "Skip updateFallbackUnicastGroupIdForBroadcast, already is primary"); + return; + } Log.i( TAG, "Update unicast fallback active group from: " @@ -5097,6 +5119,10 @@ public class LeAudioService extends ProfileService { } finally { Binder.restoreCallingIdentity(callingIdentity); } + + if (leaudioBroadcastApiManagePrimaryGroup()) { + mHandler.post(() -> notifyBroadcastToUnicastFallbackGroupChanged(groupId)); + } } private boolean isAudioModeChangedFromCommunicationToNormal(int previousMode, int currentMode) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 7261d369bf4..1543cd6ac3a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -35,6 +35,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.ParcelUuid; import android.os.RemoteException; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.MediumTest; @@ -86,6 +87,7 @@ public class LeAudioBroadcastServiceTest { private LeAudioService mService; private LeAudioIntentReceiver mLeAudioIntentReceiver; private LinkedBlockingQueue mIntentQueue; + private boolean onBroadcastToUnicastFallbackGroupChangedCallbackCalled = false; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private ActiveDeviceManager mActiveDeviceManager; @@ -1593,6 +1595,58 @@ public class LeAudioBroadcastServiceTest { Assert.assertEquals(mService.mUnicastGroupIdDeactivatedForBroadcastTransition, groupId2); } + @Test + @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP) + public void testOnBroadcastToUnicastFallbackGroupChanged() { + int groupId1 = 1; + int groupId2 = 2; + int broadcastId = 243; + byte[] code = {0x00, 0x01, 0x00, 0x02}; + + onBroadcastToUnicastFallbackGroupChangedCallbackCalled = false; + + IBluetoothLeAudioCallback leAudioCallbacks = + new IBluetoothLeAudioCallback.Stub() { + @Override + public void onCodecConfigChanged(int gid, BluetoothLeAudioCodecStatus status) {} + + @Override + public void onGroupStatusChanged(int gid, int gStatus) {} + + @Override + public void onGroupNodeAdded(BluetoothDevice device, int gid) {} + + @Override + public void onGroupNodeRemoved(BluetoothDevice device, int gid) {} + + @Override + public void onGroupStreamStatusChanged(int groupId, int groupStreamStatus) {} + + @Override + public void onBroadcastToUnicastFallbackGroupChanged(int groupId) { + onBroadcastToUnicastFallbackGroupChangedCallbackCalled = true; + Assert.assertEquals(groupId1, groupId); + } + }; + + synchronized (mService.mLeAudioCallbacks) { + mService.mLeAudioCallbacks.register(leAudioCallbacks); + } + + initializeNative(); + prepareConnectedUnicastDevice(groupId2, mDevice2); + prepareHandoverStreamingBroadcast(groupId1, broadcastId, code); + + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertEquals(groupId1, mService.mUnicastGroupIdDeactivatedForBroadcastTransition); + Assert.assertTrue(onBroadcastToUnicastFallbackGroupChangedCallbackCalled); + + onBroadcastToUnicastFallbackGroupChangedCallbackCalled = false; + synchronized (mService.mLeAudioCallbacks) { + mService.mLeAudioCallbacks.unregister(leAudioCallbacks); + } + } + private class LeAudioIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { 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 6b9668f9cf2..162b9800886 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 @@ -2229,6 +2229,9 @@ public class LeAudioServiceTest { @Override public void onGroupStreamStatusChanged(int groupId, int groupStreamStatus) {} + + @Override + public void onBroadcastToUnicastFallbackGroupChanged(int groupId) {} }; synchronized (mService.mLeAudioCallbacks) { @@ -2287,6 +2290,9 @@ public class LeAudioServiceTest { assertThat(gid == groupId).isTrue(); assertThat(gStreamStatus == groupStreamStatus).isTrue(); } + + @Override + public void onBroadcastToUnicastFallbackGroupChanged(int groupId) {} }; synchronized (mService.mLeAudioCallbacks) { @@ -2400,6 +2406,9 @@ public class LeAudioServiceTest { @Override public void onGroupStreamStatusChanged(int groupId, int groupStreamStatus) {} + + @Override + public void onBroadcastToUnicastFallbackGroupChanged(int groupId) {} }; synchronized (mService.mLeAudioCallbacks) { @@ -2484,6 +2493,9 @@ public class LeAudioServiceTest { @Override public void onGroupStreamStatusChanged(int groupId, int groupStreamStatus) {} + + @Override + public void onBroadcastToUnicastFallbackGroupChanged(int groupId) {} }; synchronized (mService.mLeAudioCallbacks) { @@ -2577,6 +2589,9 @@ public class LeAudioServiceTest { @Override public void onGroupStreamStatusChanged(int groupId, int groupStreamStatus) {} + + @Override + public void onBroadcastToUnicastFallbackGroupChanged(int groupId) {} }; synchronized (mService.mLeAudioCallbacks) { diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 7aa89155b14..37d9491b073 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -503,6 +503,7 @@ package android.bluetooth { } public static interface BluetoothLeAudio.Callback { + method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_api_manage_primary_group") public default void onBroadcastToUnicastFallbackGroupChanged(int); method public void onCodecConfigChanged(int, @NonNull android.bluetooth.BluetoothLeAudioCodecStatus); method public void onGroupNodeAdded(@NonNull android.bluetooth.BluetoothDevice, int); method public void onGroupNodeRemoved(@NonNull android.bluetooth.BluetoothDevice, int); diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index 6bc4a73de97..adecd2d9ef5 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -155,6 +155,24 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { Log.d(TAG, " onGroupStreamStatusChanged is not implemented."); } } + + /** + * Callback invoked when the broadcast to unicast fallback group changes. + * + *

    This callback provides the new broadcast to unicast fallback group ID. It is invoked + * when the broadcast to unicast fallback group is initially set, or when it subsequently + * changes. + * + * @param groupId The ID of the new broadcast to unicast fallback group. + * @hide + */ + @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP) + @SystemApi + default void onBroadcastToUnicastFallbackGroupChanged(int groupId) { + if (DBG) { + Log.d(TAG, "onBroadcastToUnicastFallbackGroupChanged is not implemented."); + } + } } private final CallbackWrapper mCallbackWrapper; @@ -189,6 +207,14 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { mCallbackWrapper.forEach( (cb) -> cb.onGroupStreamStatusChanged(groupId, groupStreamStatus)); } + + @Override + public void onBroadcastToUnicastFallbackGroupChanged(int groupId) { + if (Flags.leaudioBroadcastApiManagePrimaryGroup()) { + mCallbackWrapper.forEach( + (cb) -> cb.onBroadcastToUnicastFallbackGroupChanged(groupId)); + } + } } /** -- GitLab From f6954e8746c12b56d69233d3e7830e72d8ee92ad Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Sun, 3 Nov 2024 20:54:52 +0800 Subject: [PATCH 592/875] Fix some VisibleForTesting usage problem in Metadata * It will cause lint error "Should only be accessed from tests or within private scope" Bug: 377101095 Test: m Bluetooth Change-Id: I83f27140f99d92ed9462bab746352fd8360b7700 --- .../com/android/bluetooth/btservice/storage/Metadata.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java b/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java index 3e86bf92294..3dfc5124407 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java @@ -28,13 +28,11 @@ import androidx.room.Embedded; import androidx.room.Entity; import androidx.room.PrimaryKey; -import com.android.internal.annotations.VisibleForTesting; - import java.util.ArrayList; import java.util.List; @Entity(tableName = "metadata") -@VisibleForTesting + public class Metadata { @PrimaryKey @NonNull private String address; @@ -117,7 +115,6 @@ public class Metadata { } } - @VisibleForTesting public String getAddress() { return address; } @@ -205,7 +202,6 @@ public class Metadata { } } - @VisibleForTesting public int getProfileConnectionPolicy(int profile) { switch (profile) { case BluetoothProfile.A2DP: @@ -345,7 +341,6 @@ public class Metadata { } } - @VisibleForTesting public byte[] getCustomizedMeta(int key) { byte[] value = null; switch (key) { -- GitLab From 4e7ccecce5452839d0c6c185144995bc4e417939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 6 Nov 2024 20:46:37 +0000 Subject: [PATCH 593/875] AdapterService: Remove A2DP device from active devices when switching to LeAudio Bug: 368997665 Flag: EXEMPT, obvious fix Test: mmm packages/modules/Bluetooth Test: manual test switch between LE HS and A2DP device Change-Id: I6137364f32714fe23ceca2538a2e52979a691bc4 --- .../src/com/android/bluetooth/btservice/AdapterService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index d1feef50d5c..468c65a5283 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -5074,6 +5074,10 @@ public class AdapterService extends Service { */ mLeAudioService.removeActiveDevice(true /* hasFallbackDevice */); } else { + if (mA2dpService != null && mA2dpService.getActiveDevice() != null) { + // TODO: b/312396770 + mA2dpService.removeActiveDevice(false); + } mLeAudioService.setActiveDevice(device); } } -- GitLab From 02482f38d43b9dd47fdc39dd2efac5a74df6095f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Mon, 4 Nov 2024 12:59:30 +0000 Subject: [PATCH 594/875] leaudio: Always start VBC timeout on Local Sink Suspend To make sure there is no hanging configuration from the Local Sink, make sure to start timeout. Bug: 375334939 Test: atest bluetooth_le_audio_test Flag: EXEMPT, regression tested with unit tests Change-Id: Ib2df3fc444148a974a5f310d9db97a1b21a8d3bf --- system/bta/le_audio/client.cc | 10 +++++----- system/bta/le_audio/le_audio_client_test.cc | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index cd4ee7b803e..d620fe78109 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -4310,6 +4310,11 @@ public: "r_state: " + ToString(audio_receiver_state_) + ", s_state: " + ToString(audio_sender_state_)); + /* If the local sink direction is used, we want to monitor + * if back channel is actually needed. + */ + StartVbcCloseTimeout(); + /* Note: This callback is from audio hal driver. * Bluetooth peer is a Source for Audio Framework. * e.g. Peer is microphone. @@ -4334,11 +4339,6 @@ public: if ((audio_sender_state_ == AudioState::IDLE) || (audio_sender_state_ == AudioState::READY_TO_RELEASE)) { OnAudioSuspend(); - } else { - /* If the local sink direction is used, we want to monitor - * if back channel is actually needed. - */ - StartVbcCloseTimeout(); } log::info("OUT: audio_receiver_state_: {}, audio_sender_state_: {}", diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 37367f040d7..55bfd261240 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -9971,8 +9971,8 @@ TEST_F(UnicastTest, SwitchBetweenMicrophoneAndSoundEffectScenario) { LocalAudioSinkSuspend(); SyncOnMainLoop(); - // VBC and Suspend - ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop")); + log::info("Expect VBC and Suspend timeouts to be started"); + ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); ASSERT_EQ(0, get_func_call_count("alarm_cancel")); log::info("Resume local source with touch tone - expect suspend timeout to be canceled"); @@ -9981,7 +9981,8 @@ TEST_F(UnicastTest, SwitchBetweenMicrophoneAndSoundEffectScenario) { LocalAudioSourceResume(); SyncOnMainLoop(); - ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + log::info("Expect VBC and Suspend timeouts to be started"); + ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); auto group = streaming_groups.at(group_id); group->PrintDebugState(); -- GitLab From ccf2dde724022f22e0c289e3ba5cd42ba75ba250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Mon, 28 Oct 2024 16:26:02 +0000 Subject: [PATCH 595/875] leaudio: Fix switching from Live to Game context Android does assumptions on possible bidirectional context types and use it when aligning metadata while creating stream. Some devices uses e.g. Game and Voiceassistant as unidirection which later breaks a logic when decision is taken about stream reconfiguration. E.g. we could incorrectly reconfigure stream from existing LIVE to unidirectional GAME while recording. This patch should fix it. Bug: 375334939 Flag: Exempt, regression tested with unit tests and new test added. Test: atest bluetooth_le_audio_test Change-Id: I0ff5513ffb768f6e9e28ef05d87e53761e5259b6 --- system/bta/le_audio/client.cc | 75 ++++++++++------ system/bta/le_audio/device_groups.cc | 60 +++++++++++-- system/bta/le_audio/device_groups.h | 2 + system/bta/le_audio/le_audio_client_test.cc | 98 +++++++++++++++++++-- system/bta/le_audio/le_audio_types.cc | 24 +++-- system/bta/le_audio/le_audio_types.h | 6 +- 6 files changed, 216 insertions(+), 49 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index d620fe78109..3eebd4bb8f9 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -116,8 +116,6 @@ using bluetooth::le_audio::types::BidirectionalPair; using bluetooth::le_audio::types::DataPathState; using bluetooth::le_audio::types::hdl_pair; using bluetooth::le_audio::types::kDefaultScanDurationS; -using bluetooth::le_audio::types::kLeAudioContextAllBidir; -using bluetooth::le_audio::types::kLeAudioContextAllRemoteSinkOnly; using bluetooth::le_audio::types::kLeAudioContextAllRemoteSource; using bluetooth::le_audio::types::kLeAudioContextAllTypesArray; using bluetooth::le_audio::types::LeAudioContextType; @@ -909,13 +907,6 @@ public: return false; } - /* Make sure we do not take the local sink metadata when only the local - * source scenario is about to be started (e.g. MEDIA). - */ - if (!kLeAudioContextAllBidir.test(configuration_context_type)) { - remote_contexts.source.clear(); - } - /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */ auto ccid_contexts = remote_contexts; if (IsInVoipCall() && !IsInCall()) { @@ -4764,13 +4755,23 @@ public: if (contexts_pair.get(dir) == AudioContexts(LeAudioContextType::UNSPECIFIED)) { auto is_other_direction_streaming = (*local_hal_state == AudioState::STARTED) || (*local_hal_state == AudioState::READY_TO_START); - if (is_other_direction_streaming && - (contexts_pair.get(other_dir) != AudioContexts(LeAudioContextType::UNSPECIFIED))) { + if (is_other_direction_streaming) { + auto supported_contexts = group->GetAllSupportedSingleDirectionOnlyContextTypes(dir); + auto common_part = supported_contexts & contexts_pair.get(other_dir); + log::info( - "Other direction is streaming. Aligning other direction " - "metadata to match the current direction context: {}", - ToString(contexts_pair.get(other_dir))); - contexts_pair.get(dir) = contexts_pair.get(other_dir); + "Other direction is streaming. Possible aligning other direction " + "metadata to match the remote {} direction context: {}. Remote {} supported " + "contexts: {} ", + other_dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" + : " Source", + ToString(contexts_pair.get(other_dir)), + dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" : " Source", + ToString(supported_contexts)); + + if (common_part.value() != 0) { + contexts_pair.get(dir) = common_part; + } } } else { log::debug("Removing UNSPECIFIED from the remote {} context: {}", @@ -4870,13 +4871,16 @@ public: .sink = local_metadata_context_types_.source, .source = local_metadata_context_types_.sink}; + auto all_bidirectional_contexts = group->GetAllSupportedBidirectionalContextTypes(); + log::debug("all_bidirectional_contexts {}", ToString(all_bidirectional_contexts)); + /* Make sure we have CONVERSATIONAL when in a call and it is not mixed * with any other bidirectional context */ if (IsInCall() || IsInVoipCall()) { log::debug("In Call preference used: {}, voip call: {}", IsInCall(), IsInVoipCall()); - remote_metadata.sink.unset_all(kLeAudioContextAllBidir); - remote_metadata.source.unset_all(kLeAudioContextAllBidir); + remote_metadata.sink.unset_all(all_bidirectional_contexts); + remote_metadata.source.unset_all(all_bidirectional_contexts); remote_metadata.sink.set(LeAudioContextType::CONVERSATIONAL); remote_metadata.source.set(LeAudioContextType::CONVERSATIONAL); } @@ -4907,32 +4911,46 @@ public: log::debug("is_ongoing_call_on_other_direction={}", is_ongoing_call_on_other_direction ? "True" : "False"); - if (remote_metadata.get(remote_other_direction).test_any(kLeAudioContextAllBidir) && + if (remote_metadata.get(remote_other_direction).test_any(all_bidirectional_contexts) && !is_streaming_other_direction) { log::debug("The other direction is not streaming bidirectional, ignore that context."); remote_metadata.get(remote_other_direction).clear(); } + auto single_direction_only_context_types = + group->GetAllSupportedSingleDirectionOnlyContextTypes(remote_direction); + auto single_other_direction_only_context_types = + group->GetAllSupportedSingleDirectionOnlyContextTypes(remote_other_direction); + log::debug( + "single direction only contexts : {} for direction {}, single direction contexts {} " + "for {}", + ToString(single_direction_only_context_types), remote_direction_str, + ToString(single_other_direction_only_context_types), remote_other_direction_str); + /* Mixed contexts in the voiceback channel scenarios can confuse the remote * on how to configure each channel. We should align the other direction * metadata for the remote device. */ - if (remote_metadata.get(remote_direction).test_any(kLeAudioContextAllBidir)) { + if (remote_metadata.get(remote_direction).test_any(all_bidirectional_contexts)) { log::debug("Aligning the other direction remote metadata to add this direction context"); if (is_ongoing_call_on_other_direction) { /* Other direction is streaming and is in call */ - remote_metadata.get(remote_direction).unset_all(kLeAudioContextAllBidir); + remote_metadata.get(remote_direction).unset_all(all_bidirectional_contexts); remote_metadata.get(remote_direction).set(LeAudioContextType::CONVERSATIONAL); } else { if (!is_streaming_other_direction) { // Do not take the obsolete metadata remote_metadata.get(remote_other_direction).clear(); + } else { + remote_metadata.get(remote_other_direction).unset_all(all_bidirectional_contexts); + remote_metadata.get(remote_other_direction) + .unset_all(single_direction_only_context_types); } - remote_metadata.get(remote_other_direction).unset_all(kLeAudioContextAllBidir); - remote_metadata.get(remote_other_direction).unset_all(kLeAudioContextAllRemoteSinkOnly); + remote_metadata.get(remote_other_direction) - .set_all(remote_metadata.get(remote_direction) & ~kLeAudioContextAllRemoteSinkOnly); + .set_all(remote_metadata.get(remote_direction) & + ~single_other_direction_only_context_types); } } log::debug("remote_metadata.source= {}", ToString(remote_metadata.source)); @@ -4946,22 +4964,23 @@ public: */ if ((remote_metadata.get(remote_direction).none() && remote_metadata.get(remote_other_direction).any()) || - remote_metadata.get(remote_other_direction).test_any(kLeAudioContextAllBidir)) { + remote_metadata.get(remote_other_direction).test_any(all_bidirectional_contexts)) { log::debug("Aligning this direction remote metadata to add the other direction context"); /* Turn off bidirectional contexts on this direction to avoid mixing * with the other direction bidirectional context */ - remote_metadata.get(remote_direction).unset_all(kLeAudioContextAllBidir); + remote_metadata.get(remote_direction).unset_all(all_bidirectional_contexts); remote_metadata.get(remote_direction).set_all(remote_metadata.get(remote_other_direction)); } } /* Make sure that after alignment no sink only context leaks into the other * direction. */ - remote_metadata.source.unset_all(kLeAudioContextAllRemoteSinkOnly); + remote_metadata.source.unset_all(group->GetAllSupportedSingleDirectionOnlyContextTypes( + bluetooth::le_audio::types::kLeAudioDirectionSink)); - log::debug("remote_metadata.source= {}", ToString(remote_metadata.source)); - log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink)); + log::debug("final remote_metadata.source= {}", ToString(remote_metadata.source)); + log::debug("final remote_metadata.sink= {}", ToString(remote_metadata.sink)); return remote_metadata; } diff --git a/system/bta/le_audio/device_groups.cc b/system/bta/le_audio/device_groups.cc index c60539c4a90..7712f6d4100 100644 --- a/system/bta/le_audio/device_groups.cc +++ b/system/bta/le_audio/device_groups.cc @@ -1061,6 +1061,46 @@ bool LeAudioDeviceGroup::ReloadAudioDirections(void) { return true; } +AudioContexts LeAudioDeviceGroup::GetAllSupportedBidirectionalContextTypes(void) { + auto result = GetSupportedContexts(types::kLeAudioDirectionSink) & + GetSupportedContexts(types::kLeAudioDirectionSource); + + result &= types::kLeAudioContextAllBidir; + + return result; +} + +AudioContexts LeAudioDeviceGroup::GetAllSupportedSingleDirectionOnlyContextTypes( + uint8_t remote_direction) { + AudioContexts result; + + /* Remote device present supported context types on the different directions. + * It might happen that some "single directional" contexts are exposed on both + * directions on the remote side. + * Android takes the decision on the stream configuration based on the contexts therefore + * there is defined list of host bidirectional and host single directional context + * types. This function helps to filter out some missconfigurations on the remote side and return + * single directional context types. + * One of the use cases we want to handle here is is that usually VoiceAssistant and GAME are + * bidirectional but some devices might remove it on purpose from one direction. + */ + auto group_single_dir_only_contexts = + GetSupportedContexts(remote_direction) & ~GetAllSupportedBidirectionalContextTypes(); + + if (remote_direction == types::kLeAudioDirectionSink) { + auto host_all_sink_contexts = + types::kLeAudioContextAllRemoteSinkOnly | types::kLeAudioContextAllBidir; + result = host_all_sink_contexts & group_single_dir_only_contexts; + + } else { + auto host_all_source_contexts = + types::kLeAudioContextAllRemoteSource | types::kLeAudioContextAllBidir; + result = host_all_source_contexts & group_single_dir_only_contexts; + } + + return result; +} + bool LeAudioDeviceGroup::IsInTransition(void) const { return in_transition_; } bool LeAudioDeviceGroup::IsStreaming(void) const { @@ -1197,11 +1237,21 @@ void LeAudioDeviceGroup::CigConfiguration::GenerateCisIds(LeAudioContextType con uint8_t cis_count_unidir_source = 0; int group_size = group_->DesiredSize(); - set_configurations::get_cis_count(context_type, group_size, group_->GetGroupSinkStrategy(), - group_->GetAseCount(types::kLeAudioDirectionSink), - group_->GetAseCount(types::kLeAudioDirectionSource), - cis_count_bidir, cis_count_unidir_sink, - cis_count_unidir_source); + uint8_t expected_remote_directions; + if (group_->GetAllSupportedBidirectionalContextTypes().test(context_type)) { + expected_remote_directions = types::kLeAudioDirectionBoth; + } else if (group_->GetAllSupportedSingleDirectionOnlyContextTypes(types::kLeAudioDirectionSource) + .test(context_type)) { + expected_remote_directions = types::kLeAudioDirectionSource; + } else { + expected_remote_directions = types::kLeAudioDirectionSink; + } + + set_configurations::get_cis_count( + context_type, expected_remote_directions, group_size, group_->GetGroupSinkStrategy(), + group_->GetAseCount(types::kLeAudioDirectionSink), + group_->GetAseCount(types::kLeAudioDirectionSource), cis_count_bidir, + cis_count_unidir_sink, cis_count_unidir_source); uint8_t idx = 0; while (cis_count_bidir > 0) { diff --git a/system/bta/le_audio/device_groups.h b/system/bta/le_audio/device_groups.h index ba11270aca3..40a87b0a71b 100644 --- a/system/bta/le_audio/device_groups.h +++ b/system/bta/le_audio/device_groups.h @@ -218,6 +218,8 @@ public: void ResetPreferredAudioSetConfiguration(void) const; bool ReloadAudioLocations(void); bool ReloadAudioDirections(void); + types::AudioContexts GetAllSupportedBidirectionalContextTypes(void); + types::AudioContexts GetAllSupportedSingleDirectionOnlyContextTypes(uint8_t direction); std::shared_ptr GetActiveConfiguration( void) const; bool IsPendingConfiguration(void) const; diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 55bfd261240..454c371b21e 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -6218,6 +6218,93 @@ TEST_F(UnicastTest, SpeakerStreamingNonDefault) { LocalAudioSourceResume(); } +TEST_F(UnicastTest, TestUnidirectionalGameAndLiveRecording) { + com::android::bluetooth::flags::provider_->le_audio_support_unidirectional_voice_assistant(true); + const RawAddress test_address0 = GetTestAddress(0); + int group_id = bluetooth::groups::kGroupUnknown; + + /** + * Scenario test steps + * 1. Configure group to support GAME only on SINK + * 2. Configure group to support LIVE + * 3. Start recording with LIVE + * 4. Update context type with GAME + * 5. Verify that Configuration did not changed. + */ + + available_snk_context_types_ = + (types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA | + types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::LIVE) + .value(); + supported_snk_context_types_ = available_snk_context_types_; + + available_src_context_types_ = + (types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED).value(); + supported_src_context_types_ = available_src_context_types_; + + default_channel_cnt = 1; + + SetSampleDatabaseEarbudsValid( + 1, test_address0, codec_spec_conf::kLeAudioLocationStereo, + codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004, + /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/, + default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnConnectionState(ConnectionState::CONNECTED, test_address0)) + .Times(1); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) + .WillOnce(DoAll(SaveArg<1>(&group_id))); + + types::BidirectionalPair metadata_contexts = { + .sink = types::AudioContexts(types::LeAudioContextType::LIVE), + .source = types::AudioContexts(types::LeAudioContextType::LIVE)}; + EXPECT_CALL(mock_state_machine_, + StartStream(_, types::LeAudioContextType::LIVE, metadata_contexts, _)) + .Times(1); + + log::info("Connecting LeAudio to {}", test_address0); + ConnectLeAudio(test_address0); + ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); + + // Audio sessions are started only when device gets active + EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1); + + EXPECT_CALL(*mock_codec_manager_, + UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_, + mock_le_audio_sink_hal_client_, true)) + .Times(1); + + LeAudioClient::Get()->GroupSetActive(group_id); + SyncOnMainLoop(); + + UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC); + LocalAudioSinkResume(); + SyncOnMainLoop(); + + Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); + Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); + Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); + Mock::VerifyAndClearExpectations(mock_codec_manager_); + Mock::VerifyAndClearExpectations(&mock_state_machine_); + SyncOnMainLoop(); + + // We do expect only unidirectional CIS + uint8_t cis_count_out = 0; + uint8_t cis_count_in = 1; + + // Verify Data transfer on one local audio source cis + TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40); + SyncOnMainLoop(); + + EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0); + UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN); + LocalAudioSourceResume(); + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); +} + TEST_F(UnicastTest, TestUnidirectionalVoiceAssistant_Sink) { com::android::bluetooth::flags::provider_->le_audio_support_unidirectional_voice_assistant(true); const RawAddress test_address0 = GetTestAddress(0); @@ -6254,7 +6341,7 @@ TEST_F(UnicastTest, TestUnidirectionalVoiceAssistant_Sink) { types::BidirectionalPair metadata_contexts = { .sink = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS), - .source = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED)}; + .source = types::AudioContexts()}; EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, metadata_contexts, _)) .Times(1); @@ -6328,7 +6415,7 @@ TEST_F(UnicastTest, TestUnidirectionalVoiceAssistant_Source) { .WillOnce(DoAll(SaveArg<1>(&group_id))); types::BidirectionalPair metadata_contexts = { - .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED), + .sink = types::AudioContexts(), .source = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS)}; EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, metadata_contexts, _)) @@ -10061,7 +10148,7 @@ TEST_F(UnicastTest, UpdateNotSupportedContextTypeUnspecifiedAvailable) { EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0); types::BidirectionalPair contexts = { .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED), - .source = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED)}; + .source = types::AudioContexts()}; EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::GAME, contexts, _)) .Times(1); UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false); @@ -10129,7 +10216,7 @@ TEST_F(UnicastTest, UpdateNotSupportedContextTypeUnspecifiedAvailable_SpeedUpRec EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0); types::BidirectionalPair contexts = { .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED), - .source = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED)}; + .source = types::AudioContexts()}; EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::GAME, contexts, _)) .Times(1); UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false); @@ -10521,6 +10608,8 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { available_snk_context_types_ | types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value(); available_src_context_types_ = available_snk_context_types_; + available_src_context_types_ &= + ~((types::LeAudioContextType::NOTIFICATIONS | types::LeAudioContextType::MEDIA).value()); supported_src_context_types_ = available_src_context_types_ | types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value(); @@ -10559,7 +10648,6 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { contexts, _)) .Times(1); StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id); - LocalAudioSourceResume(); LocalAudioSinkResume(); // Verify diff --git a/system/bta/le_audio/le_audio_types.cc b/system/bta/le_audio/le_audio_types.cc index 4142251d24d..632a9866268 100644 --- a/system/bta/le_audio/le_audio_types.cc +++ b/system/bta/le_audio/le_audio_types.cc @@ -46,17 +46,21 @@ using types::kLeAudioDirectionSink; using types::kLeAudioDirectionSource; using types::LeAudioCoreCodecConfig; -void get_cis_count(LeAudioContextType context_type, int expected_device_cnt, - types::LeAudioConfigurationStrategy strategy, int avail_group_ase_snk_cnt, - int avail_group_ase_src_count, uint8_t& out_cis_count_bidir, - uint8_t& out_cis_count_unidir_sink, uint8_t& out_cis_count_unidir_source) { +void get_cis_count(LeAudioContextType context_type, uint8_t expected_remote_direction, + int expected_device_cnt, types::LeAudioConfigurationStrategy strategy, + int avail_group_ase_snk_cnt, int avail_group_ase_src_count, + uint8_t& out_cis_count_bidir, uint8_t& out_cis_count_unidir_sink, + uint8_t& out_cis_count_unidir_source) { log::info( - "{} strategy {}, group avail sink ases: {}, group avail source ases {} " + "{} expected_remote_direction {}, strategy {}, group avail sink ases: {}, " + "group avail source ases {} " "expected_device_count {}", - bluetooth::common::ToString(context_type), static_cast(strategy), - avail_group_ase_snk_cnt, avail_group_ase_src_count, expected_device_cnt); + bluetooth::common::ToString(context_type), expected_remote_direction, + static_cast(strategy), avail_group_ase_snk_cnt, avail_group_ase_src_count, + expected_device_cnt); - bool is_bidirectional = types::kLeAudioContextAllBidir.test(context_type); + bool is_bidirectional = expected_remote_direction == types::kLeAudioDirectionBoth; + bool is_source_only = expected_remote_direction == types::kLeAudioDirectionSource; switch (strategy) { case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE: @@ -76,6 +80,8 @@ void get_cis_count(LeAudioContextType context_type, int expected_device_cnt, out_cis_count_unidir_source = expected_device_cnt; } } + } else if (is_source_only) { + out_cis_count_unidir_source = expected_device_cnt; } else { out_cis_count_unidir_sink = expected_device_cnt; } @@ -101,6 +107,8 @@ void get_cis_count(LeAudioContextType context_type, int expected_device_cnt, out_cis_count_unidir_source = 2 * expected_device_cnt; } } + } else if (is_source_only) { + out_cis_count_unidir_source = 2 * expected_device_cnt; } else { out_cis_count_unidir_sink = 2 * expected_device_cnt; } diff --git a/system/bta/le_audio/le_audio_types.h b/system/bta/le_audio/le_audio_types.h index 54e3898cb1a..2d9a46a30f4 100644 --- a/system/bta/le_audio/le_audio_types.h +++ b/system/bta/le_audio/le_audio_types.h @@ -1276,9 +1276,9 @@ static constexpr uint32_t kChannelAllocationStereo = codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight; /* Declarations */ -void get_cis_count(types::LeAudioContextType context_type, int expected_device_cnt, - types::LeAudioConfigurationStrategy strategy, int group_ase_snk_cnt, - int group_ase_src_count, uint8_t& cis_count_bidir, +void get_cis_count(types::LeAudioContextType context_type, uint8_t expected_direction, + int expected_device_cnt, types::LeAudioConfigurationStrategy strategy, + int group_ase_snk_cnt, int group_ase_src_count, uint8_t& cis_count_bidir, uint8_t& cis_count_unidir_sink, uint8_t& cis_count_unidir_source); } // namespace set_configurations -- GitLab From cb111410a6d22059d40faf4e8f0a6d33f6d95f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Mon, 4 Nov 2024 11:07:10 +0000 Subject: [PATCH 596/875] leaudio: Minor fix on parameter name Sometimes we use local_direction and sometimes remote_direction. Make sure in this function we are sure that remote_direction is used Bug: 331775328 Flag: EXEMPT, no function change Test: atest bluetooth_le_audio_client_test Change-Id: Ib2184aad7dd9dfae0bcd409cd36e189d720db14f --- system/bta/le_audio/client.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 3eebd4bb8f9..55664693541 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -4342,14 +4342,21 @@ public: } inline bool IsDirectionAvailableForCurrentConfiguration(const LeAudioDeviceGroup* group, - uint8_t direction) const { + uint8_t remote_direction) const { auto current_config = group->IsUsingPreferredAudioSetConfiguration(configuration_context_type_) ? group->GetCachedPreferredConfiguration(configuration_context_type_) : group->GetCachedConfiguration(configuration_context_type_); + log::debug("configuration_context_type_ = {}, group_id: {}, remote_direction: {}", + ToString(configuration_context_type_), group->group_id_, + remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink ? "Sink" + : "Source"); if (current_config) { - return current_config->confs.get(direction).size() != 0; + log::debug("name = {}, size {}", current_config->name, + current_config->confs.get(remote_direction).size()); + return current_config->confs.get(remote_direction).size() != 0; } + log::debug("no cached configuration"); return false; } -- GitLab From c7edf4446ddadd6d4e37e0e309f4eb25734e52c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Mon, 4 Nov 2024 11:09:06 +0000 Subject: [PATCH 597/875] leaudio: Add reconfiguration guard Android stack choose LeAudio configuration based on the local sink and source metadata. Local Source metadata change does immediate change if needed. Local Sink metadata change just stores metadata and applies it when Local Sink direction is resumed (started). It has been observed that while BT Stack tries to reconfigure the stream, Audio HAL keep changing Metadata on the Local Source which breaks reconfiguration, especially when reconfiguration has been triggered by Local Sink direction. This is because Audio HAL keeps Suspending and Resuming Sink direction but keeps intention of previous revonfiguration - which Android is not aware of. With this change, when reconfiguration is scheduled, BT stack will not allow for other reconfigurations unless 1. Reconfiguration timeout fires 2. All the directions for which reconfiguration has been scheduled, got resumed after Audio HAL was informed about reconfiguration being completed. Bug: 375334939 Flag: Exempt, regression tests with unit tests Test: atest bluetooth_le_audio_client_test Change-Id: I041669332a5d7d465dd1dcfbbe8b353bf65d2883 --- system/bta/le_audio/client.cc | 159 ++++++++++++++++++-- system/bta/le_audio/le_audio_client_test.cc | 100 ++++++++++-- 2 files changed, 236 insertions(+), 23 deletions(-) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 55664693541..b0e465afff9 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -239,6 +239,7 @@ public: alarm_free(close_vbc_timeout_); alarm_free(disable_timer_); alarm_free(suspend_timeout_); + alarm_free(reconfiguration_timeout_); } LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks* callbacks, @@ -263,6 +264,7 @@ public: le_audio_sink_hal_client_(nullptr), close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")), suspend_timeout_(alarm_new("LeAudioSuspendTimeout")), + reconfiguration_timeout_(alarm_new("LeAudioReconfigurationTimeout")), disable_timer_(alarm_new("LeAudioDisableTimer")) { LeAudioGroupStateMachine::Initialize(state_machine_callbacks); groupStateMachine_ = LeAudioGroupStateMachine::Get(); @@ -364,6 +366,79 @@ public: } } + bool IsReconfigurationTimeoutRunning( + int group_id, uint8_t direction = bluetooth::le_audio::types::kLeAudioDirectionBoth) { + if (alarm_is_scheduled(reconfiguration_timeout_)) { + log::debug(" is {} group_id: {}, to check: {}, scheduled: {}", + group_id == reconfiguration_group_ ? "running" : " not running", group_id, + direction, reconfiguration_local_directions_); + return group_id == reconfiguration_group_ && (direction & reconfiguration_local_directions_); + } + return false; + } + + void StartReconfigurationTimeout(int group_id) { + log::debug("group_id: {}", group_id); + + /* This is called when Reconfiguration has been completed. This function starts + * timer which is a guard for unwanted reconfiguration which might happen when Audio HAL + * is sending to Bluetooth stack multiple metadata updates and suspends/resume commands. + * What we want to achieve with this timeout, that BT stack will resume the stream with + * configuration picked up when ReconfigurationComplete command was sent out to Audio HAL. + */ + + if (alarm_is_scheduled(reconfiguration_timeout_)) { + log::info("Is already running for group {}", reconfiguration_group_); + return; + } + + auto group = aseGroups_.FindById(group_id); + if (group == nullptr) { + log::warn("This shall not happen, group_id: {} is not available.", group_id); + return; + } + + if (IsDirectionAvailableForCurrentConfiguration( + group, bluetooth::le_audio::types::kLeAudioDirectionSink)) { + reconfiguration_local_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource; + } + if (IsDirectionAvailableForCurrentConfiguration( + group, bluetooth::le_audio::types::kLeAudioDirectionSource)) { + reconfiguration_local_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink; + } + + log::debug("reconfiguration_local_directions_ : {}", reconfiguration_local_directions_); + + reconfiguration_group_ = group_id; + alarm_set_on_mloop( + reconfiguration_timeout_, kAudioReconfigurationTimeoutMs, + [](void* data) { + if (instance) { + instance->StopReconfigurationTimeout( + PTR_TO_INT(data), bluetooth::le_audio::types::kLeAudioDirectionBoth); + } + }, + INT_TO_PTR(group_id)); + } + + void StopReconfigurationTimeout(int group_id, uint8_t local_direction) { + log::debug("group_id: {}, local_direction {}, reconfiguration directions {}", group_id, + local_direction, reconfiguration_local_directions_); + + reconfiguration_local_directions_ &= ~local_direction; + + if (reconfiguration_local_directions_ != 0) { + log::debug("Wait for remaining directions: {} ", reconfiguration_local_directions_); + return; + } + + if (alarm_is_scheduled(reconfiguration_timeout_)) { + log::debug("Canceling for group_id {}", reconfiguration_group_); + alarm_cancel(reconfiguration_timeout_); + } + reconfiguration_group_ = bluetooth::groups::kGroupUnknown; + } + void StartSuspendTimeout(void) { StopSuspendTimeout(); @@ -619,6 +694,7 @@ public: "s_state: " + ToString(audio_sender_state_)); le_audio_sink_hal_client_->SuspendedForReconfiguration(); } + StartReconfigurationTimeout(active_group_id_); } void ReconfigurationComplete(uint8_t directions) { @@ -1112,6 +1188,8 @@ public: return; } log::info("Call is coming, speed up reconfiguration for a call"); + local_metadata_context_types_.sink.clear(); + local_metadata_context_types_.source.clear(); reconfigure = true; } else { if (configuration_context_type_ == LeAudioContextType::CONVERSATIONAL) { @@ -4176,6 +4254,10 @@ public: /* Stream is not started. Try to do it.*/ if (OnAudioResume(group, bluetooth::le_audio::types::kLeAudioDirectionSource)) { audio_sender_state_ = AudioState::READY_TO_START; + if (IsReconfigurationTimeoutRunning(active_group_id_)) { + StopReconfigurationTimeout(active_group_id_, + bluetooth::le_audio::types::kLeAudioDirectionSource); + } } else { CancelLocalAudioSourceStreamingRequest(); } @@ -4398,11 +4480,12 @@ public: return; } - /* We need new configuration_context_type_ to be selected before we go any - * further. - */ if (audio_receiver_state_ == AudioState::IDLE) { + /* We need new configuration_context_type_ to be selected before we go any + * further. + */ ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSource); + log::info("new_configuration_context = {}", ToString(configuration_context_type_)); } /* Check if the device resume is allowed */ @@ -4437,6 +4520,10 @@ public: case AudioState::IDLE: if (OnAudioResume(group, bluetooth::le_audio::types::kLeAudioDirectionSink)) { audio_receiver_state_ = AudioState::READY_TO_START; + if (IsReconfigurationTimeoutRunning(active_group_id_)) { + StopReconfigurationTimeout(active_group_id_, + bluetooth::le_audio::types::kLeAudioDirectionSink); + } } else { CancelLocalAudioSinkStreamingRequest(); } @@ -4655,11 +4742,6 @@ public: return; } - /* Stop the VBC close timeout timer, since we will reconfigure anyway if the - * VBC was suspended. - */ - StopVbcCloseTimeout(); - log::info( "group_id {} state={}, target_state={}, audio_receiver_state_: {}, " "audio_sender_state_: {}, dsa_mode: {}", @@ -4667,6 +4749,16 @@ public: ToString(audio_receiver_state_), ToString(audio_sender_state_), static_cast(dsa_mode)); + if (IsReconfigurationTimeoutRunning(group->group_id_)) { + log::info("Skip it as group is reconfiguring"); + return; + } + + /* Stop the VBC close timeout timer, since we will reconfigure anyway if the + * VBC was suspended. + */ + StopVbcCloseTimeout(); + group->dsa_.mode = dsa_mode; /* Set the remote sink metadata context from the playback tracks metadata */ @@ -4814,6 +4906,11 @@ public: group->group_id_, ToString(group->GetState()), ToString(group->GetTargetState()), ToString(audio_receiver_state_), ToString(audio_sender_state_)); + if (IsReconfigurationTimeoutRunning(group->group_id_)) { + log::info("Skip it as group is reconfiguring"); + return; + } + /* Set remote source metadata context from the recording tracks metadata */ local_metadata_context_types_.sink = GetAudioContextsFromSinkMetadata(sink_metadata); @@ -4849,11 +4946,21 @@ public: auto is_streaming_other_direction = (other_direction_hal == AudioState::STARTED) || (other_direction_hal == AudioState::READY_TO_START); + + auto local_direction = bluetooth::le_audio::types::kLeAudioDirectionBoth & ~remote_direction; + auto local_other_direction = + bluetooth::le_audio::types::kLeAudioDirectionBoth & ~remote_other_direction; + auto is_releasing_for_reconfiguration = (((audio_receiver_state_ == AudioState::RELEASING) || (audio_sender_state_ == AudioState::RELEASING)) && group->IsPendingConfiguration() && - IsDirectionAvailableForCurrentConfiguration(group, remote_other_direction)); + IsDirectionAvailableForCurrentConfiguration(group, remote_other_direction)) || + IsReconfigurationTimeoutRunning(active_group_id_, local_direction); + + auto is_releasing_for_reconfiguration_other_direction = + is_releasing_for_reconfiguration & + IsReconfigurationTimeoutRunning(active_group_id_, local_other_direction); // Inject conversational when ringtone is played - this is required for all // the VoIP applications which are not using the telecom API. @@ -4915,11 +5022,13 @@ public: log::debug("is_streaming_other_direction= {}", is_streaming_other_direction ? "True" : "False"); log::debug("is_releasing_for_reconfiguration= {}", is_releasing_for_reconfiguration ? "True" : "False"); + log::debug("is_releasing_for_reconfiguration_other_direction= {}", + is_releasing_for_reconfiguration_other_direction ? "True" : "False"); log::debug("is_ongoing_call_on_other_direction={}", is_ongoing_call_on_other_direction ? "True" : "False"); if (remote_metadata.get(remote_other_direction).test_any(all_bidirectional_contexts) && - !is_streaming_other_direction) { + !(is_streaming_other_direction || is_releasing_for_reconfiguration_other_direction)) { log::debug("The other direction is not streaming bidirectional, ignore that context."); remote_metadata.get(remote_other_direction).clear(); } @@ -4946,7 +5055,7 @@ public: remote_metadata.get(remote_direction).unset_all(all_bidirectional_contexts); remote_metadata.get(remote_direction).set(LeAudioContextType::CONVERSATIONAL); } else { - if (!is_streaming_other_direction) { + if (!(is_streaming_other_direction || is_releasing_for_reconfiguration_other_direction)) { // Do not take the obsolete metadata remote_metadata.get(remote_other_direction).clear(); } else { @@ -4964,7 +5073,7 @@ public: log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink)); if (is_releasing_for_reconfiguration || is_streaming_other_direction) { - log::debug("Other direction is streaming. Taking its contexts {}", + log::debug("Other direction is streaming or there is reconfiguration. Taking its contexts {}", ToString(remote_metadata.get(remote_other_direction))); /* If current direction has no valid context or the other direction is * bidirectional scenario, take the other direction context as well @@ -5008,7 +5117,7 @@ public: /* Choose the right configuration context */ auto new_configuration_context = ChooseConfigurationContextType(override_contexts); - log::debug("new_configuration_context= {}.", ToString(new_configuration_context)); + log::info("new_configuration_context= {}.", ToString(new_configuration_context)); BidirectionalPair remote_contexts = {.sink = override_contexts, .source = override_contexts}; return GroupStream(active_group_id_, new_configuration_context, remote_contexts); @@ -5612,6 +5721,12 @@ public: handleAsymmetricPhyForUnicast(group); UpdateLocationsAndContextsAvailability(group); if (group->IsPendingConfiguration()) { + log::debug( + "Pending configuration for group_id: {} pre_configuration_context_type_ : {} " + "-> " + "configuration_context_type_ {}", + group->group_id_, ToString(pre_configuration_context_type_), + ToString(configuration_context_type_)); auto remote_direction = kLeAudioContextAllRemoteSource.test(configuration_context_type_) ? bluetooth::le_audio::types::kLeAudioDirectionSource : bluetooth::le_audio::types::kLeAudioDirectionSink; @@ -5624,6 +5739,11 @@ public: auto remote_contexts = DirectionalRealignMetadataAudioContexts(group, remote_direction); ApplyRemoteMetadataAudioContextPolicy(group, remote_contexts, remote_direction); + log::verbose( + "Pending configuration 2 pre_configuration_context_type_ : {} -> " + "configuration_context_type_ {}", + ToString(pre_configuration_context_type_), + ToString(configuration_context_type_)); if ((configuration_context_type_ != pre_configuration_context_type_) && GroupStream(group->group_id_, configuration_context_type_, remote_contexts)) { /* If configuration succeed wait for new status. */ @@ -5780,8 +5900,21 @@ private: static constexpr uint64_t kAudioDisableTimeoutMs = 3000; static constexpr char kAudioSuspentKeepIsoAliveTimeoutMsProp[] = "persist.bluetooth.leaudio.audio.suspend.timeoutms"; + static constexpr uint64_t kAudioReconfigurationTimeoutMs = 1500; alarm_t* close_vbc_timeout_; alarm_t* suspend_timeout_; + + /* Reconfiguration guard to make sure reconfigration is not broken by unexpected Metadata change. + * When Reconfiguration is scheduled then + * 1. BT stack remembers local directions which should be resumed after reconfiguration + * 2. Blocks another reconfiguration until: + * a) all the reconfigured directions has been resumed + * b) reconfiguration timeout fires + */ + alarm_t* reconfiguration_timeout_; + int reconfiguration_group_ = bluetooth::groups::kGroupUnknown; + uint8_t reconfiguration_local_directions_ = 0; + alarm_t* disable_timer_; static constexpr uint64_t kDeviceAttachDelayMs = 500; diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 454c371b21e..111f051099f 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -859,13 +859,18 @@ protected: metadata_context_types, types::BidirectionalPair> ccid_lists, bool configure_qos) { + auto group_state = group->GetState(); bool isReconfiguration = group->IsPendingConfiguration(); log::info( - "ConfigureStream: group_id {}, context_type {}, configure_qos {}, " + "ConfigureStream: group {} state {}, context type {} sink metadata_ctx {}, " + "source metadata_ctx {}, ccid_sink size {}, ccid_source_size {}, " "isReconfiguration {}", - group->group_id_, bluetooth::common::ToString(context_type), configure_qos, - isReconfiguration); + group->group_id_, bluetooth::common::ToString(group_state), + bluetooth::common::ToString(context_type), + bluetooth::common::ToString(metadata_context_types.sink), + bluetooth::common::ToString(metadata_context_types.source), + ccid_lists.sink.size(), ccid_lists.source.size(), isReconfiguration); /* Do what ReleaseCisIds(group) does: start */ LeAudioDevice* leAudioDevice = group->GetFirstDevice(); @@ -1030,11 +1035,12 @@ protected: auto group_state = group->GetState(); log::info( "StartStream: group {} state {}, context type {} sink metadata_ctx {}, " - "source metadata_ctx {}", + "source metadata_ctx {}, ccid_sink size {}, ccid_source_size {}", group->group_id_, bluetooth::common::ToString(group_state), bluetooth::common::ToString(context_type), bluetooth::common::ToString(metadata_context_types.sink), - bluetooth::common::ToString(metadata_context_types.source)); + bluetooth::common::ToString(metadata_context_types.source), + ccid_lists.sink.size(), ccid_lists.source.size()); /* Do nothing if already streaming - the implementation would * probably update the metadata. @@ -7535,11 +7541,11 @@ TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaForBothMediaAndConv) { is_using_set_before_media_codec_during_media, is_using_set_while_media_codec_during_media, is_reconfig); - // simulate suspend timeout passed, alarm executing + log::info("simulate suspend timeout passed, alarm executing"); fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data); SyncOnMainLoop(); - // SetInCall is used by GTBS - and only then we can expect CCID to be set. + log::info("SetInCall is used by GTBS - and only then we can expect CCID to be set."); LeAudioClient::Get()->SetInCall(true); bool set_before_conv = false; @@ -7553,7 +7559,7 @@ TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaForBothMediaAndConv) { is_using_set_while_conv_codec_during_conv, is_reconfig); LeAudioClient::Get()->SetInCall(false); - // should use preferred codec when switching back to media + log::info("should use preferred codec when switching back to media"); ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig( group_id, static_cast(types::LeAudioContextType::MEDIA)), true); @@ -8310,7 +8316,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) { fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); - // SetInCall is used by GTBS - and only then we can expect CCID to be set. + log::info("SetInCall is used by GTBS - and only then we can expect CCID to be set."); LeAudioClient::Get()->SetInCall(true); // Conversational is a bidirectional scenario so expect GTBS CCID @@ -8331,11 +8337,12 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) { cis_count_in = 2; TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40); + log::info("End call"); LeAudioClient::Get()->SetInCall(false); // Stop StopStreaming(group_id, true); - // Switch back to MEDIA + log::info("Switch back to MEDIA"); ccids = {.sink = {gmcs_ccid}, .source = {}}; types::BidirectionalPair contexts = { .sink = types::AudioContexts(types::LeAudioContextType::MEDIA), @@ -10737,6 +10744,79 @@ TEST_F(UnicastTest, MusicDuringCallContextTypes) { SyncOnMainLoop(); } +TEST_F(UnicastTest, MetadataUpdateDuringReconfiguration) { + com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(true); + const RawAddress test_address0 = GetTestAddress(0); + int group_id = bluetooth::groups::kGroupUnknown; + + /* Scenario + * 1. Start reconfiguration + * 2. Send metadata update + * 3. Make sure metadata updates are ignored + */ + available_snk_context_types_ = + (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE | + types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA | + types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS) + .value(); + supported_snk_context_types_ = + available_snk_context_types_ | + types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value(); + available_src_context_types_ = available_snk_context_types_; + supported_src_context_types_ = + available_src_context_types_ | + types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value(); + + SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft, + codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, + default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/, + true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, + 0 /*rank*/); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnConnectionState(ConnectionState::CONNECTED, test_address0)) + .Times(1); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED)) + .WillOnce(DoAll(SaveArg<1>(&group_id))); + + ConnectLeAudio(test_address0); + ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown); + + // Audio sessions are started only when device gets active + EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1); + LeAudioClient::Get()->GroupSetActive(group_id); + SyncOnMainLoop(); + EXPECT_CALL(mock_state_machine_, + StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, _, _)) + .Times(1); + StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id); + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); + + auto group = streaming_groups.at(group_id); + + stay_at_qos_config_in_start_stream = true; + log::info("Reconfigure to conversational and stay in Codec Config"); + + EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1); + + LeAudioClient::Get()->SetInCall(true); + SyncOnMainLoop(); + + ASSERT_TRUE(group->GetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); + + log::info("Expect not action on metadata change"); + + EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0); + EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0); + + UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC); + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(&mock_state_machine_); +} + TEST_F(UnicastTest, MusicDuringCallContextTypes_SpeedUpReconfigFlagEnabled) { com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(true); -- GitLab From e0553fe41db37a90aa508ef121ebacd41c024b56 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Tue, 5 Nov 2024 15:39:47 -0800 Subject: [PATCH 598/875] stack/a2dp: Inline A2DP_VendorXXX methods Bug: 331817295 Test: m com.android.btservices Test: atest net_test_stack Flag: EXEMPT, no logical change Change-Id: Ic3fadafd324ff33a8169704652a02ad080138c49 --- system/stack/a2dp/a2dp_codec_config.cc | 120 +++++++++++++------ system/stack/a2dp/a2dp_vendor.cc | 160 ------------------------- system/stack/include/a2dp_constants.h | 2 + system/stack/include/a2dp_vendor.h | 32 ----- system/stack/test/stack_a2dp_test.cc | 17 ++- 5 files changed, 93 insertions(+), 238 deletions(-) diff --git a/system/stack/a2dp/a2dp_codec_config.cc b/system/stack/a2dp/a2dp_codec_config.cc index 4a39e0c93b0..73424c36e77 100644 --- a/system/stack/a2dp/a2dp_codec_config.cc +++ b/system/stack/a2dp/a2dp_codec_config.cc @@ -1257,87 +1257,123 @@ bool A2DP_CodecTypeEquals(const uint8_t* p_codec_info_a, const uint8_t* p_codec_ } bool A2DP_CodecEquals(const uint8_t* p_codec_info_a, const uint8_t* p_codec_info_b) { - tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); - tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); + auto codec_id_a = bluetooth::a2dp::ParseCodecId(p_codec_info_a); + auto codec_id_b = bluetooth::a2dp::ParseCodecId(p_codec_info_b); - if (codec_type_a != codec_type_b) { + if (!codec_id_a.has_value() || !codec_id_b.has_value() || codec_id_a != codec_id_b) { return false; } - switch (codec_type_a) { - case A2DP_MEDIA_CT_SBC: + switch (codec_id_a.value()) { + case bluetooth::a2dp::CodecId::SBC: return A2DP_CodecEqualsSbc(p_codec_info_a, p_codec_info_b); #if !defined(EXCLUDE_NONSTANDARD_CODECS) - case A2DP_MEDIA_CT_AAC: + case bluetooth::a2dp::CodecId::AAC: return A2DP_CodecEqualsAac(p_codec_info_a, p_codec_info_b); - case A2DP_MEDIA_CT_NON_A2DP: - return A2DP_VendorCodecEquals(p_codec_info_a, p_codec_info_b); + case bluetooth::a2dp::CodecId::APTX: + return A2DP_VendorCodecEqualsAptx(p_codec_info_a, p_codec_info_b); + case bluetooth::a2dp::CodecId::APTX_HD: + return A2DP_VendorCodecEqualsAptxHd(p_codec_info_a, p_codec_info_b); + case bluetooth::a2dp::CodecId::LDAC: + return A2DP_VendorCodecEqualsLdac(p_codec_info_a, p_codec_info_b); + case bluetooth::a2dp::CodecId::OPUS: + return A2DP_VendorCodecEqualsOpus(p_codec_info_a, p_codec_info_b); #endif default: break; } - log::error("unsupported codec type 0x{:x}", codec_type_a); + log::error("unsupported codec id 0x{:x}", codec_id_a.value()); return false; } int A2DP_GetTrackSampleRate(const uint8_t* p_codec_info) { - tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info); + auto codec_id = bluetooth::a2dp::ParseCodecId(p_codec_info); - switch (codec_type) { - case A2DP_MEDIA_CT_SBC: + if (!codec_id.has_value()) { + return -1; + } + + switch (codec_id.value()) { + case bluetooth::a2dp::CodecId::SBC: return A2DP_GetTrackSampleRateSbc(p_codec_info); #if !defined(EXCLUDE_NONSTANDARD_CODECS) - case A2DP_MEDIA_CT_AAC: + case bluetooth::a2dp::CodecId::AAC: return A2DP_GetTrackSampleRateAac(p_codec_info); - case A2DP_MEDIA_CT_NON_A2DP: - return A2DP_VendorGetTrackSampleRate(p_codec_info); + case bluetooth::a2dp::CodecId::APTX: + return A2DP_VendorGetTrackSampleRateAptx(p_codec_info); + case bluetooth::a2dp::CodecId::APTX_HD: + return A2DP_VendorGetTrackSampleRateAptxHd(p_codec_info); + case bluetooth::a2dp::CodecId::LDAC: + return A2DP_VendorGetTrackSampleRateLdac(p_codec_info); + case bluetooth::a2dp::CodecId::OPUS: + return A2DP_VendorGetTrackSampleRateOpus(p_codec_info); #endif default: break; } - log::error("unsupported codec type 0x{:x}", codec_type); + log::error("unsupported codec id 0x{:x}", codec_id.value()); return -1; } int A2DP_GetTrackBitsPerSample(const uint8_t* p_codec_info) { - tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info); + auto codec_id = bluetooth::a2dp::ParseCodecId(p_codec_info); - switch (codec_type) { - case A2DP_MEDIA_CT_SBC: + if (!codec_id.has_value()) { + return -1; + } + + switch (codec_id.value()) { + case bluetooth::a2dp::CodecId::SBC: return A2DP_GetTrackBitsPerSampleSbc(p_codec_info); #if !defined(EXCLUDE_NONSTANDARD_CODECS) - case A2DP_MEDIA_CT_AAC: + case bluetooth::a2dp::CodecId::AAC: return A2DP_GetTrackBitsPerSampleAac(p_codec_info); - case A2DP_MEDIA_CT_NON_A2DP: - return A2DP_VendorGetTrackBitsPerSample(p_codec_info); + case bluetooth::a2dp::CodecId::APTX: + return A2DP_VendorGetTrackBitsPerSampleAptx(p_codec_info); + case bluetooth::a2dp::CodecId::APTX_HD: + return A2DP_VendorGetTrackBitsPerSampleAptxHd(p_codec_info); + case bluetooth::a2dp::CodecId::LDAC: + return A2DP_VendorGetTrackBitsPerSampleLdac(p_codec_info); + case bluetooth::a2dp::CodecId::OPUS: + return A2DP_VendorGetTrackBitsPerSampleOpus(p_codec_info); #endif default: break; } - log::error("unsupported codec type 0x{:x}", codec_type); + log::error("unsupported codec id 0x{:x}", codec_id.value()); return -1; } int A2DP_GetTrackChannelCount(const uint8_t* p_codec_info) { - tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info); + auto codec_id = bluetooth::a2dp::ParseCodecId(p_codec_info); - switch (codec_type) { - case A2DP_MEDIA_CT_SBC: + if (!codec_id.has_value()) { + return -1; + } + + switch (codec_id.value()) { + case bluetooth::a2dp::CodecId::SBC: return A2DP_GetTrackChannelCountSbc(p_codec_info); #if !defined(EXCLUDE_NONSTANDARD_CODECS) - case A2DP_MEDIA_CT_AAC: + case bluetooth::a2dp::CodecId::AAC: return A2DP_GetTrackChannelCountAac(p_codec_info); - case A2DP_MEDIA_CT_NON_A2DP: - return A2DP_VendorGetTrackChannelCount(p_codec_info); + case bluetooth::a2dp::CodecId::APTX: + return A2DP_VendorGetTrackChannelCountAptx(p_codec_info); + case bluetooth::a2dp::CodecId::APTX_HD: + return A2DP_VendorGetTrackChannelCountAptxHd(p_codec_info); + case bluetooth::a2dp::CodecId::LDAC: + return A2DP_VendorGetTrackChannelCountLdac(p_codec_info); + case bluetooth::a2dp::CodecId::OPUS: + return A2DP_VendorGetTrackChannelCountOpus(p_codec_info); #endif default: break; } - log::error("unsupported codec type 0x{:x}", codec_type); + log::error("unsupported codec id 0x{:x}", codec_id.value()); return -1; } @@ -1363,22 +1399,32 @@ int A2DP_GetSinkTrackChannelType(const uint8_t* p_codec_info) { bool A2DP_GetPacketTimestamp(const uint8_t* p_codec_info, const uint8_t* p_data, uint32_t* p_timestamp) { - tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info); + auto codec_id = bluetooth::a2dp::ParseCodecId(p_codec_info); - switch (codec_type) { - case A2DP_MEDIA_CT_SBC: + if (!codec_id.has_value()) { + return false; + } + + switch (codec_id.value()) { + case bluetooth::a2dp::CodecId::SBC: return A2DP_GetPacketTimestampSbc(p_codec_info, p_data, p_timestamp); #if !defined(EXCLUDE_NONSTANDARD_CODECS) - case A2DP_MEDIA_CT_AAC: + case bluetooth::a2dp::CodecId::AAC: return A2DP_GetPacketTimestampAac(p_codec_info, p_data, p_timestamp); - case A2DP_MEDIA_CT_NON_A2DP: - return A2DP_VendorGetPacketTimestamp(p_codec_info, p_data, p_timestamp); + case bluetooth::a2dp::CodecId::APTX: + return A2DP_VendorGetPacketTimestampAptx(p_codec_info, p_data, p_timestamp); + case bluetooth::a2dp::CodecId::APTX_HD: + return A2DP_VendorGetPacketTimestampAptxHd(p_codec_info, p_data, p_timestamp); + case bluetooth::a2dp::CodecId::LDAC: + return A2DP_VendorGetPacketTimestampLdac(p_codec_info, p_data, p_timestamp); + case bluetooth::a2dp::CodecId::OPUS: + return A2DP_VendorGetPacketTimestampOpus(p_codec_info, p_data, p_timestamp); #endif default: break; } - log::error("unsupported codec type 0x{:x}", codec_type); + log::error("unsupported codec id 0x{:x}", codec_id.value()); return false; } diff --git a/system/stack/a2dp/a2dp_vendor.cc b/system/stack/a2dp/a2dp_vendor.cc index b178c3c9003..f215787d5a4 100644 --- a/system/stack/a2dp/a2dp_vendor.cc +++ b/system/stack/a2dp/a2dp_vendor.cc @@ -233,49 +233,6 @@ bool A2DP_VendorCodecTypeEquals(const uint8_t* p_codec_info_a, const uint8_t* p_ return true; } -bool A2DP_VendorCodecEquals(const uint8_t* p_codec_info_a, const uint8_t* p_codec_info_b) { - tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); - tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); - - if ((codec_type_a != codec_type_b) || (codec_type_a != A2DP_MEDIA_CT_NON_A2DP)) { - return false; - } - - uint32_t vendor_id_a = A2DP_VendorCodecGetVendorId(p_codec_info_a); - uint16_t codec_id_a = A2DP_VendorCodecGetCodecId(p_codec_info_a); - uint32_t vendor_id_b = A2DP_VendorCodecGetVendorId(p_codec_info_b); - uint16_t codec_id_b = A2DP_VendorCodecGetCodecId(p_codec_info_b); - - if ((vendor_id_a != vendor_id_b) || (codec_id_a != codec_id_b)) { - return false; - } - - // Check for aptX - if (vendor_id_a == A2DP_APTX_VENDOR_ID && codec_id_a == A2DP_APTX_CODEC_ID_BLUETOOTH) { - return A2DP_VendorCodecEqualsAptx(p_codec_info_a, p_codec_info_b); - } - - // Check for aptX-HD - if (vendor_id_a == A2DP_APTX_HD_VENDOR_ID && codec_id_a == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) { - return A2DP_VendorCodecEqualsAptxHd(p_codec_info_a, p_codec_info_b); - } - - // Check for LDAC - if (vendor_id_a == A2DP_LDAC_VENDOR_ID && codec_id_a == A2DP_LDAC_CODEC_ID) { - return A2DP_VendorCodecEqualsLdac(p_codec_info_a, p_codec_info_b); - } - - // Check for Opus - if (vendor_id_a == A2DP_OPUS_VENDOR_ID && codec_id_a == A2DP_OPUS_CODEC_ID) { - return A2DP_VendorCodecEqualsOpus(p_codec_info_a, p_codec_info_b); - } - - // Add extra vendor-specific checks based on the - // vendor-specific data stored in "p_codec_info_a" and "p_codec_info_b". - - return false; -} - int A2DP_VendorGetBitRate(const uint8_t* p_codec_info) { uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); @@ -305,93 +262,6 @@ int A2DP_VendorGetBitRate(const uint8_t* p_codec_info) { return -1; } -int A2DP_VendorGetTrackSampleRate(const uint8_t* p_codec_info) { - uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); - uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); - - // Check for aptX - if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetTrackSampleRateAptx(p_codec_info); - } - - // Check for aptX-HD - if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetTrackSampleRateAptxHd(p_codec_info); - } - - // Check for LDAC - if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) { - return A2DP_VendorGetTrackSampleRateLdac(p_codec_info); - } - - // Check for Opus - if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) { - return A2DP_VendorGetTrackSampleRateOpus(p_codec_info); - } - - // Add checks based on - - return -1; -} - -int A2DP_VendorGetTrackBitsPerSample(const uint8_t* p_codec_info) { - uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); - uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); - - // Check for aptX - if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetTrackBitsPerSampleAptx(p_codec_info); - } - - // Check for aptX-HD - if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetTrackBitsPerSampleAptxHd(p_codec_info); - } - - // Check for LDAC - if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) { - return A2DP_VendorGetTrackBitsPerSampleLdac(p_codec_info); - } - - // Check for Opus - if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) { - return A2DP_VendorGetTrackBitsPerSampleOpus(p_codec_info); - } - - // Add checks based on - - return -1; -} - -int A2DP_VendorGetTrackChannelCount(const uint8_t* p_codec_info) { - uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); - uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); - - // Check for aptX - if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetTrackChannelCountAptx(p_codec_info); - } - - // Check for aptX-HD - if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetTrackChannelCountAptxHd(p_codec_info); - } - - // Check for LDAC - if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) { - return A2DP_VendorGetTrackChannelCountLdac(p_codec_info); - } - - // Check for Opus - if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) { - return A2DP_VendorGetTrackChannelCountOpus(p_codec_info); - } - - // Add checks based on - - return -1; -} - int A2DP_VendorGetSinkTrackChannelType(const uint8_t* p_codec_info) { uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); @@ -412,36 +282,6 @@ int A2DP_VendorGetSinkTrackChannelType(const uint8_t* p_codec_info) { return -1; } -bool A2DP_VendorGetPacketTimestamp(const uint8_t* p_codec_info, const uint8_t* p_data, - uint32_t* p_timestamp) { - uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); - uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info); - - // Check for aptX - if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetPacketTimestampAptx(p_codec_info, p_data, p_timestamp); - } - - // Check for aptX-HD - if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) { - return A2DP_VendorGetPacketTimestampAptxHd(p_codec_info, p_data, p_timestamp); - } - - // Check for LDAC - if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) { - return A2DP_VendorGetPacketTimestampLdac(p_codec_info, p_data, p_timestamp); - } - - // Check for Opus - if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) { - return A2DP_VendorGetPacketTimestampOpus(p_codec_info, p_data, p_timestamp); - } - - // Add checks based on - - return false; -} - bool A2DP_VendorBuildCodecHeader(const uint8_t* p_codec_info, BT_HDR* p_buf, uint16_t frames_per_packet) { uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info); diff --git a/system/stack/include/a2dp_constants.h b/system/stack/include/a2dp_constants.h index 55a9b9abd38..090c25a3153 100644 --- a/system/stack/include/a2dp_constants.h +++ b/system/stack/include/a2dp_constants.h @@ -169,6 +169,8 @@ enum tA2DP_STATUS : uint8_t { namespace fmt { template <> +struct formatter : enum_formatter {}; +template <> struct formatter : enum_formatter {}; template <> struct formatter : enum_formatter {}; diff --git a/system/stack/include/a2dp_vendor.h b/system/stack/include/a2dp_vendor.h index bc78341a004..00159e7ba47 100644 --- a/system/stack/include/a2dp_vendor.h +++ b/system/stack/include/a2dp_vendor.h @@ -100,30 +100,6 @@ const char* A2DP_VendorCodecName(const uint8_t* p_codec_info); // If the codec type is not recognized, the return value is false. bool A2DP_VendorCodecTypeEquals(const uint8_t* p_codec_info_a, const uint8_t* p_codec_info_b); -// Checks whether two A2DP vendor-specific codecs |p_codec_info_a| and -// |p_codec_info_b| are exactly the same. -// Returns true if the two codecs are exactly the same, otherwise false. -// If the codec type is not recognized, the return value is false. -bool A2DP_VendorCodecEquals(const uint8_t* p_codec_info_a, const uint8_t* p_codec_info_b); - -// Gets the track sample rate value for the A2DP vendor-specific codec. -// |p_codec_info| is a pointer to the vendor-specific codec_info to decode. -// Returns the track sample rate on success, or -1 if |p_codec_info| -// contains invalid codec information. -int A2DP_VendorGetTrackSampleRate(const uint8_t* p_codec_info); - -// Gets the track bits per sample value for the A2DP vendor-specific codec. -// |p_codec_info| is a pointer to the vendor-specific codec_info to decode. -// Returns the track sample rate on success, or -1 if |p_codec_info| -// contains invalid codec information. -int A2DP_VendorGetTrackBitsPerSample(const uint8_t* p_codec_info); - -// Gets the channel count for the A2DP vendor-specific codec. -// |p_codec_info| is a pointer to the vendor-specific codec_info to decode. -// Returns the channel count on success, or -1 if |p_codec_info| -// contains invalid codec information. -int A2DP_VendorGetTrackChannelCount(const uint8_t* p_codec_info); - // Gets the bitrate for the A2DP vendor-specific codec. // |p_codec_info| is a pointer to the vendor-specific codec_info to decode. // Returns the channel count on success, or -1 if |p_codec_info| @@ -137,14 +113,6 @@ int A2DP_VendorGetBitRate(const uint8_t* p_codec_info); // contains invalid codec information. int A2DP_VendorGetSinkTrackChannelType(const uint8_t* p_codec_info); -// Gets the A2DP codec-specific audio data timestamp from an audio packet. -// |p_codec_info| contains the codec information. -// |p_data| contains the audio data. -// The timestamp is stored in |p_timestamp|. -// Returns true on success, otherwise false. -bool A2DP_VendorGetPacketTimestamp(const uint8_t* p_codec_info, const uint8_t* p_data, - uint32_t* p_timestamp); - // Builds A2DP vendor-specific codec header for audio data. // |p_codec_info| contains the codec information. // |p_buf| contains the audio data. diff --git a/system/stack/test/stack_a2dp_test.cc b/system/stack/test/stack_a2dp_test.cc index c78ad6285e1..1c6a6ad1372 100644 --- a/system/stack/test/stack_a2dp_test.cc +++ b/system/stack/test/stack_a2dp_test.cc @@ -579,7 +579,7 @@ TEST_F(StackA2dpTest, test_a2dp_codec_equals) { // Test two identical Opus codecs memset(codec_info_opus_test, 0xAB, sizeof(codec_info_opus_test)); memcpy(codec_info_opus_test, codec_info_opus, sizeof(codec_info_opus)); - ASSERT_TRUE(A2DP_VendorCodecEquals(codec_info_opus, codec_info_opus_test)); + ASSERT_TRUE(A2DP_CodecEquals(codec_info_opus, codec_info_opus_test)); // Test two identical non-A2DP codecs that are not recognized memset(codec_info_non_a2dp_test, 0xAB, sizeof(codec_info_non_a2dp_test)); @@ -627,14 +627,14 @@ TEST_F(StackA2dpTest, test_a2dp_codec_equals) { TEST_F(StackA2dpTest, test_a2dp_get_track_sample_rate) { EXPECT_EQ(A2DP_GetTrackSampleRate(codec_info_sbc), 44100); EXPECT_EQ(A2DP_GetTrackSampleRate(codec_info_aac), 44100); - ASSERT_EQ(A2DP_VendorGetTrackSampleRate(codec_info_opus), 48000); + ASSERT_EQ(A2DP_GetTrackSampleRate(codec_info_opus), 48000); EXPECT_EQ(A2DP_GetTrackSampleRate(codec_info_non_a2dp), -1); } TEST_F(StackA2dpTest, test_a2dp_get_track_channel_count) { EXPECT_EQ(A2DP_GetTrackChannelCount(codec_info_sbc), 2); EXPECT_EQ(A2DP_GetTrackChannelCount(codec_info_aac), 2); - ASSERT_EQ(A2DP_VendorGetTrackChannelCount(codec_info_opus), 2); + ASSERT_EQ(A2DP_GetTrackChannelCount(codec_info_opus), 2); EXPECT_EQ(A2DP_GetTrackChannelCount(codec_info_non_a2dp), -1); } @@ -687,7 +687,7 @@ TEST_F(StackA2dpTest, test_a2dp_get_max_bitpool_sbc) { TEST_F(StackA2dpTest, test_a2dp_get_sink_track_channel_type) { EXPECT_EQ(A2DP_GetSinkTrackChannelType(codec_info_sbc), 3); EXPECT_EQ(A2DP_GetSinkTrackChannelType(codec_info_aac), 3); - ASSERT_EQ(A2DP_VendorGetSinkTrackChannelType(codec_info_opus), 2); + ASSERT_EQ(A2DP_GetSinkTrackChannelType(codec_info_opus), 2); EXPECT_EQ(A2DP_GetSinkTrackChannelType(codec_info_non_a2dp), -1); } @@ -735,7 +735,7 @@ TEST_F(StackA2dpTest, test_a2dp_get_packet_timestamp) { memset(a2dp_data, 0xAB, sizeof(a2dp_data)); *p_ts = 0x12345678; timestamp = 0xFFFFFFFF; - ASSERT_TRUE(A2DP_VendorGetPacketTimestamp(codec_info_opus, a2dp_data, ×tamp)); + ASSERT_TRUE(A2DP_GetPacketTimestamp(codec_info_opus, a2dp_data, ×tamp)); ASSERT_EQ(timestamp, static_cast(0x12345678)); memset(a2dp_data, 0xAB, sizeof(a2dp_data)); @@ -818,10 +818,9 @@ TEST_F(StackA2dpTest, test_a2dp_source_codec_index) { EXPECT_EQ(A2DP_SourceCodecIndex(codec_info_aac_capability), BTAV_A2DP_CODEC_INDEX_SOURCE_AAC); EXPECT_EQ(A2DP_SourceCodecIndex(codec_info_aac_sink_capability), BTAV_A2DP_CODEC_INDEX_SOURCE_AAC); - ASSERT_EQ(A2DP_VendorSourceCodecIndex(codec_info_opus), BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS); - ASSERT_EQ(A2DP_VendorSourceCodecIndex(codec_info_opus_capability), - BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS); - ASSERT_EQ(A2DP_VendorSourceCodecIndex(codec_info_opus_sink_capability), + ASSERT_EQ(A2DP_SourceCodecIndex(codec_info_opus), BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS); + ASSERT_EQ(A2DP_SourceCodecIndex(codec_info_opus_capability), BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS); + ASSERT_EQ(A2DP_SourceCodecIndex(codec_info_opus_sink_capability), BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS); EXPECT_EQ(A2DP_SourceCodecIndex(codec_info_non_a2dp), BTAV_A2DP_CODEC_INDEX_MAX); } -- GitLab From 2145924a1eb9fdc68dbe81a2aa64432d0c41e618 Mon Sep 17 00:00:00 2001 From: Henri Chataing Date: Thu, 31 Oct 2024 10:36:33 -0700 Subject: [PATCH 599/875] audio_hal_interface: Refine implementation of A2DP StopRequest Bug: 365022887 Test: m com.android.btservices Test: Manual streaming test Flag: EXEMPT, minor bug fix Change-Id: Ia7138bbb1ecb9e3f2e0e3103a75823e46240d891 --- system/audio_hal_interface/a2dp_encoding.h | 1 + .../aidl/a2dp/a2dp_encoding_aidl.cc | 2 +- system/btif/src/btif_a2dp_source.cc | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/system/audio_hal_interface/a2dp_encoding.h b/system/audio_hal_interface/a2dp_encoding.h index 84e31a82c6b..5c8e68cc2f7 100644 --- a/system/audio_hal_interface/a2dp_encoding.h +++ b/system/audio_hal_interface/a2dp_encoding.h @@ -55,6 +55,7 @@ public: return BluetoothAudioStatus::FAILURE; } virtual BluetoothAudioStatus SuspendStream() const { return BluetoothAudioStatus::FAILURE; } + virtual BluetoothAudioStatus StopStream() const { return SuspendStream(); } virtual BluetoothAudioStatus SetLatencyMode(bool /*low_latency*/) const { return BluetoothAudioStatus::FAILURE; } diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc index f99fa9ba284..cde3eedd397 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc @@ -185,7 +185,7 @@ BluetoothAudioStatus A2dpTransport::SuspendRequest() { void A2dpTransport::StopRequest() { log::info(""); - auto status = bluetooth_audio_port_->SuspendStream(); + auto status = bluetooth_audio_port_->StopStream(); a2dp_pending_cmd_ = status == BluetoothAudioStatus::PENDING ? A2DP_CTRL_CMD_STOP : A2DP_CTRL_CMD_NONE; } diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 3f3bc5a4790..f1a70f879a1 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -364,6 +364,7 @@ class A2dpAudioPort : public bluetooth::audio::a2dp::BluetoothAudioPort { // Check if the stream has already been started. if (btif_av_stream_started_ready(A2dpType::kSource)) { + log::verbose("stream is already started"); return BluetoothAudioStatus::SUCCESS; } @@ -386,6 +387,7 @@ class A2dpAudioPort : public bluetooth::audio::a2dp::BluetoothAudioPort { // Check if the stream is already suspended. if (!btif_av_stream_started_ready(A2dpType::kSource)) { btif_av_clear_remote_suspend_flag(A2dpType::kSource); + log::verbose("stream is already suspended"); return BluetoothAudioStatus::SUCCESS; } @@ -395,6 +397,20 @@ class A2dpAudioPort : public bluetooth::audio::a2dp::BluetoothAudioPort { return BluetoothAudioStatus::PENDING; } + BluetoothAudioStatus StopStream() const override { + // Check if the stream is already suspended. + if (!btif_av_stream_started_ready(A2dpType::kSource)) { + btif_av_clear_remote_suspend_flag(A2dpType::kSource); + log::verbose("stream is already stopped"); + return BluetoothAudioStatus::SUCCESS; + } + + // Post stop event. The stop request is pending, but completion is not + // notified to the HAL. + btif_av_stream_stop(RawAddress::kEmpty); + return BluetoothAudioStatus::PENDING; + } + BluetoothAudioStatus SetLatencyMode(bool low_latency) const override { btif_av_set_low_latency(low_latency); return BluetoothAudioStatus::SUCCESS; -- GitLab From a4a8fd198f5fcdfdb5cdd50d34c2580d7d2c1bbd Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Thu, 7 Nov 2024 09:43:48 +0800 Subject: [PATCH 600/875] floss: Fix 'android-base/parseint.h' file not found This fixes the breakage caused by https://r.android.com/3324693 Bug: 369703686 Bug: 360917504 Tag: #floss Test: mmm packages/modules/Bluetooth Test: USE=floss_upstream emerge-brya floss Test: USE=floss_upstream emerge-rauru floss Flag: EXEMPT, Floss-only change Change-Id: I8ed5a2921b9075ce8fb7974a6eca3c9be1cdabe0 --- system/gd/metrics/BUILD.gn | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/system/gd/metrics/BUILD.gn b/system/gd/metrics/BUILD.gn index 2b3453c359d..ff0d72e81ea 100644 --- a/system/gd/metrics/BUILD.gn +++ b/system/gd/metrics/BUILD.gn @@ -21,7 +21,10 @@ source_set("BluetoothMetricsSources_chromeos") { "chromeos/metrics_event.cc", ] - deps = [ "//bt/system/gd:gd_default_deps" ] + deps = [ + "//bt/system/gd:gd_default_deps", + "//bt/floss/android-base:android-base", + ] configs += [ "//bt/system/gd:gd_defaults", "//bt/system/log:log_defaults", -- GitLab From 6dea2095c6cd1be0b1ae75fc673406156d8f1e23 Mon Sep 17 00:00:00 2001 From: wentjin Date: Thu, 25 Jul 2024 13:46:59 +0800 Subject: [PATCH 601/875] Store active player avoid it was deleted by other threads Root cause: The player was cleaned by other threads when set player active which caused BT crash. Bug: 377409171 Test: m com.android.btservices Change-Id: I79cc6d05140d3b54c954ad5208288a71a4ea27a2 --- .../bluetooth/audio_util/MediaPlayerList.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java index 019e7e508ae..e9e0f8c714f 100644 --- a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java +++ b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java @@ -971,24 +971,35 @@ public class MediaPlayerList { return; } - if (playerId == mActivePlayerId) { - Log.w(TAG, getActivePlayer().getPackageName() + " is already the active player"); + int previousActivePlayerId = mActivePlayerId; + MediaPlayerWrapper previousPlayer = getActivePlayer(); + + if (playerId == previousActivePlayerId) { + if (previousPlayer != null) { + Log.w(TAG, previousPlayer.getPackageName() + " is already the active player"); + } return; } - if (mActivePlayerId != NO_ACTIVE_PLAYER) getActivePlayer().unregisterCallback(); + if (previousActivePlayerId != NO_ACTIVE_PLAYER && previousPlayer != null) { + previousPlayer.unregisterCallback(); + } mActivePlayerId = playerId; - getActivePlayer().registerCallback(mMediaPlayerCallback); + + MediaPlayerWrapper player = getActivePlayer(); + if (player == null) return; + + player.registerCallback(mMediaPlayerCallback); mActivePlayerLogger.logd( - TAG, "setActivePlayer(): setting player to " + getActivePlayer().getPackageName()); + TAG, "setActivePlayer(): setting player to " + player.getPackageName()); if (mPlayerSettingsListener != null) { - mPlayerSettingsListener.onActivePlayerChanged(getActivePlayer()); + mPlayerSettingsListener.onActivePlayerChanged(player); } // Ensure that metadata is synced on the new player - if (!getActivePlayer().isMetadataSynced()) { + if (!player.isMetadataSynced()) { Log.w(TAG, "setActivePlayer(): Metadata not synced on new player"); return; } @@ -1006,7 +1017,7 @@ public class MediaPlayerList { } } - MediaData data = getActivePlayer().getCurrentMediaData(); + MediaData data = player.getCurrentMediaData(); if (mAudioPlaybackIsActive) { data.state = mCurrMediaData.state; Log.d(TAG, "setActivePlayer mAudioPlaybackIsActive=true, state=" + data.state); -- GitLab From 903152615de31e596c71c4f60ae178f4dd331382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 31 Oct 2024 09:15:15 +0000 Subject: [PATCH 602/875] has_client.cc: cleanup device when GATT operations may be pending We should clear device that is getting disconnected after it was already disconnected, otherwise it's GATT queue may have pending elements that will belong to next device that gets same connection ID. Bug: 361721967 Test: atest --host --no-bazel-mode bluetooth_has_test Change-Id: Iea06ff952e78534cf672fc1296f220e52e89ac84 --- system/bta/has/has_client.cc | 33 ++++++++++++++++++++++------- system/bta/has/has_client_test.cc | 35 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 15f69ab76a8..915472dd85c 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -429,7 +429,7 @@ public: ClearDeviceInformationAndStartSearch(device); } else { log::error("Devices {}: Control point not usable. Disconnecting!", device->addr); - BTA_GATTC_Close(device->conn_id); + CleanAndDisconnectByConnId(conn_id); } } @@ -475,7 +475,7 @@ public: ClearDeviceInformationAndStartSearch(device); } else { log::error("Devices {}: Control point not usable. Disconnecting!", device->addr); - BTA_GATTC_Close(device->conn_id); + CleanAndDisconnectByConnId(conn_id); } } @@ -1137,7 +1137,7 @@ private: /* Both of these CCC are mandatory */ if (enabling_ntf && (status != GATT_SUCCESS)) { log::error("Failed to register for notifications on handle=0x{:x}", handle); - BTA_GATTC_Close(conn_id); + CleanAndDisconnectByConnId(conn_id); return; } } @@ -1189,20 +1189,22 @@ private: return; } + tCONN_ID conn_id = device->conn_id; + if (status != GATT_SUCCESS) { if (status == GATT_DATABASE_OUT_OF_SYNC) { log::info("Database out of sync for {}", device->addr); ClearDeviceInformationAndStartSearch(device); } else { log::error("Could not read characteristic at handle=0x{:04x}", handle); - BTA_GATTC_Close(device->conn_id); + CleanAndDisconnectByConnId(conn_id); } return; } if (len != 1) { log::error("Invalid features value length={} at handle=0x{:x}", len, handle); - BTA_GATTC_Close(device->conn_id); + CleanAndDisconnectByConnId(conn_id); return; } @@ -1565,9 +1567,11 @@ private: void OnHasCtpValueNotification(HasDevice* device, uint16_t len, const uint8_t* value) { auto ntf_opt = HasCtpNtf::FromCharacteristicValue(len, value); + tCONN_ID conn_id = device->conn_id; + if (!ntf_opt.has_value()) { log::error("Unhandled notification for device: {}", *device); - BTA_GATTC_Close(device->conn_id); + CleanAndDisconnectByConnId(conn_id); return; } @@ -1591,19 +1595,22 @@ private: return; } + tCONN_ID conn_id = device->conn_id; + if (status != GATT_SUCCESS) { if (status == GATT_DATABASE_OUT_OF_SYNC) { log::info("Database out of sync for {}", device->addr); ClearDeviceInformationAndStartSearch(device); } else { log::error("Could not read characteristic at handle=0x{:04x}", handle); - BTA_GATTC_Close(device->conn_id); + CleanAndDisconnectByConnId(conn_id); + return; } } if (len != 1) { log::error("Invalid preset value length={} at handle=0x{:x}", len, handle); - BTA_GATTC_Close(device->conn_id); + CleanAndDisconnectByConnId(conn_id); return; } @@ -1717,6 +1724,16 @@ private: device.ConnectionCleanUp(); } + void CleanAndDisconnectByConnId(tCONN_ID conn_id) { + auto device_iter = + std::find_if(devices_.begin(), devices_.end(), HasDevice::MatchConnId(conn_id)); + if (device_iter != devices_.end()) { + DoDisconnectCleanUp(*device_iter); + devices_.erase(device_iter); + } + BTA_GATTC_Close(conn_id); + } + /* These below are all GATT service discovery, validation, cache & storage */ bool CacheAttributeHandles(const gatt::Service& service, HasDevice* device) { log::debug("device={}", device->addr); diff --git a/system/bta/has/has_client_test.cc b/system/bta/has/has_client_test.cc index b0656e41b5b..eaa07278f5a 100644 --- a/system/bta/has/has_client_test.cc +++ b/system/bta/has/has_client_test.cc @@ -1602,6 +1602,41 @@ TEST_F(HasClientTest, test_discovery_has_broken_no_active_preset_ntf) { TestConnect(test_address); } +TEST_F(HasClientTest, test_cp_not_usable_read_all_presets) { + osi_property_set_bool("persist.bluetooth.has.always_use_preset_cache", false); + + const RawAddress test_address = GetTestAddress(1); + std::set has_presets = {{ + HasPreset(1, HasPreset::kPropertyAvailable, "Universal"), + HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable, "Preset2"), + }}; + + SetSampleDatabaseHasPresetsNtf(test_address, + bluetooth::has::kFeatureBitHearingAidTypeBanded | + bluetooth::has::kFeatureBitWritablePresets | + bluetooth::has::kFeatureBitDynamicPresets, + has_presets); + + ON_CALL(gatt_queue, ReadCharacteristic(_, HasDbBuilder::kActivePresetIndexValHdl, _, _)) + .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb, + void* cb_data) -> void { + std::vector value; + + tGATT_STATUS status = GATT_ERROR; + if (cb) { + cb(conn_id, status, handle, value.size(), value.data(), cb_data); + } + })); + + EXPECT_CALL(*callbacks, + OnDeviceAvailable(test_address, bluetooth::has::kFeatureBitHearingAidTypeBanded | + bluetooth::has::kFeatureBitWritablePresets | + bluetooth::has::kFeatureBitDynamicPresets)); + EXPECT_CALL(gatt_queue, Clean(1)).Times(1); + + TestConnect(test_address); +} + TEST_F(HasClientTest, test_discovery_has_features_ntf) { const RawAddress test_address = GetTestAddress(1); auto test_conn_id = GetTestConnId(test_address); -- GitLab From 1a1cfcd064a6aff7d962269cb8f3d8987075241d Mon Sep 17 00:00:00 2001 From: Michal Belusiak Date: Thu, 7 Nov 2024 13:12:34 +0000 Subject: [PATCH 603/875] le_audio: Change dialer sounds to SOUNDEFFECTS instead of MEDIA MEDIA causes handover from broadcast to unicast which is not expected in dialer usage. There is no reason to use MEDIA for such sounds. Bug: 377856052 Test: atest bluetooth_le_audio_client_test --host Flag: EXEMPT; simple fix Change-Id: Ie5ab5834dfd5e44fcb3f38fc7bbd14e6f50d56a1 --- system/bta/le_audio/le_audio_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/bta/le_audio/le_audio_utils.cc b/system/bta/le_audio/le_audio_utils.cc index 719d017607a..8a1bb6cbfc4 100644 --- a/system/bta/le_audio/le_audio_utils.cc +++ b/system/bta/le_audio/le_audio_utils.cc @@ -64,7 +64,7 @@ LeAudioContextType AudioContentToLeAudioContext(audio_content_type_t content_typ return LeAudioContextType::RINGTONE; } - return LeAudioContextType::MEDIA; + return LeAudioContextType::SOUNDEFFECTS; case AUDIO_USAGE_GAME: return LeAudioContextType::GAME; case AUDIO_USAGE_NOTIFICATION: -- GitLab From f192f5ebe2349d545b996346903a472f297d4f4d Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Wed, 6 Nov 2024 21:47:44 +0100 Subject: [PATCH 604/875] Improve key_missing_classic_device handling For IO Capabilities Response, or Authentication Complete event, we should also report key missing and disconnect Bug: 333634398 Bug: 377513028 Test: mma -j32; Test: connect twice to device that forgot bond Flag: com.android.bluetooth.flags.key_missing_classic_device Change-Id: I6c1c76c7764d4038374d0f5c5fedbcbf2ba65798 --- system/stack/btm/btm_sec.cc | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index 6572ba5eb6a..3118203c24a 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -2445,7 +2445,7 @@ void btm_io_capabilities_req(RawAddress p) { auto p_dev_rec = btm_find_dev(p); if (p_dev_rec != NULL) { btm_sec_disconnect(p_dev_rec->hci_handle, HCI_ERR_AUTH_FAILURE, - "btm_io_capabilities_req Security failure"); + "btm_io_capabilities_req for bonded device"); } return; } @@ -2618,10 +2618,22 @@ void btm_io_capabilities_req(RawAddress p) { * ******************************************************************************/ void btm_io_capabilities_rsp(const tBTM_SP_IO_RSP evt_data) { - tBTM_SEC_DEV_REC* p_dev_rec; - /* Allocate a new device record or reuse the oldest one */ - p_dev_rec = btm_find_or_alloc_dev(evt_data.bd_addr); + tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(evt_data.bd_addr); + + /* 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()) { + log::warn("Incoming bond request, but {} is already bonded (notifying user)", evt_data.bd_addr); + bta_dm_remote_key_missing(evt_data.bd_addr); + + if (p_dev_rec != NULL) { + btm_sec_disconnect(p_dev_rec->hci_handle, HCI_ERR_AUTH_FAILURE, + "btm_io_capabilities_rsp for bonded device"); + } + return; + } /* If no security is in progress, this indicates incoming security */ if (btm_sec_cb.pairing_state == BTM_PAIR_STATE_IDLE) { @@ -3012,6 +3024,16 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) { tBTM_SEC_CB::btm_pair_state_descr(btm_sec_cb.pairing_state), handle, status, p_dev_rec->sec_rec.classic_link, p_dev_rec->bd_addr, reinterpret_cast(p_dev_rec->sec_bd_name)); + + if (status == HCI_ERR_KEY_MISSING && + com::android::bluetooth::flags::key_missing_classic_device()) { + 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); + btm_sec_disconnect(handle, HCI_ERR_AUTH_FAILURE, "auth_cmpl KEY_MISSING for bonded device"); + return; + } + } else { log::verbose("Security Manager: in state: {}, handle: {}, status: {}", tBTM_SEC_CB::btm_pair_state_descr(btm_sec_cb.pairing_state), handle, status); -- GitLab From 9c3ca59cc07ba1cd54587013f172b735322e0412 Mon Sep 17 00:00:00 2001 From: Jakub Tyszkowski Date: Thu, 7 Nov 2024 16:14:09 +0000 Subject: [PATCH 605/875] LeAudio: Fix buffer size type conversion for the SW encoder The LC3 software codec uses the value of -1 to indicate the invalid number of samples, while the codec interface uses 0 (and unsigned data type). With this fix we handle -1 gracefully. Bug: 377177980 Test: m -j Flag: Exempt; trivial fix - no functional changes Change-Id: Ibc970a240fbedba0e9c0cdb887a0a7495e25a946 --- system/bta/le_audio/codec_interface.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/system/bta/le_audio/codec_interface.cc b/system/bta/le_audio/codec_interface.cc index 637c77f5bf3..0342e45c74c 100644 --- a/system/bta/le_audio/codec_interface.cc +++ b/system/bta/le_audio/codec_interface.cc @@ -80,8 +80,14 @@ struct CodecInterface::Impl { (pcm_config_->bits_per_sample == 24) ? LC3_PCM_FORMAT_S24 : LC3_PCM_FORMAT_S16; // Prepare the decoded output buffer - output_channel_samples_ = + auto num_samples = lc3_frame_samples(bt_codec_config_.data_interval_us, pcm_config_->sample_rate); + if (num_samples == -1) { + log::error("Could not determine the sample count for data_interval: {}, sample_rate: {}", + bt_codec_config_.data_interval_us, pcm_config_->sample_rate); + return CodecInterface::Status::STATUS_ERR_CODEC_NOT_READY; + } + output_channel_samples_ = num_samples; adjustOutputBufferSizeIfNeeded(&output_channel_data_); // Prepare the decoder @@ -185,7 +191,14 @@ struct CodecInterface::Impl { } if (codec_id_.coding_format == types::kLeAudioCodingFormatLC3) { - return lc3_frame_samples(bt_codec_config_.data_interval_us, pcm_config_->sample_rate); + auto num_samples = + lc3_frame_samples(bt_codec_config_.data_interval_us, pcm_config_->sample_rate); + if (num_samples == -1) { + log::error("Could not determine the sample count for data_interval: {}, sample_rate: {}", + bt_codec_config_.data_interval_us, pcm_config_->sample_rate); + return 0; + } + return num_samples; } log::error("Invalid codec ID: [{}:{}:{}]", codec_id_.coding_format, codec_id_.vendor_company_id, @@ -206,6 +219,7 @@ struct CodecInterface::Impl { private: inline void adjustOutputBufferSizeIfNeeded(std::vector* out_buffer) { if (out_buffer->size() < output_channel_samples_) { + log::debug("Changing buffer size to {}", output_channel_samples_); out_buffer->resize(output_channel_samples_); } } -- GitLab From 62c77931a4643491866fffc12a8cb9cfeb50802c Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 6 Nov 2024 17:00:20 -0800 Subject: [PATCH 606/875] HAP: offer a way to disable leaudio on some device Bug: 345826775 Flag: com.android.bluetooth.flags.enable_hap_by_default Test: m . Change-Id: I62c8b466a9040d91cd7b5f9a18ebeb728852452d --- .../com/android/bluetooth/btservice/PhonePolicy.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java b/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java index 1dcef80a661..be7af84c0d6 100644 --- a/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +++ b/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java @@ -281,16 +281,23 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { return isLeAudioOnlyGroup(device); } + private static final String SYSPROP_HAP_ENABLED = "bluetooth.profile.hap.enabled_by_default"; + // return true if device support Hearing Access Service and it has not been manually disabled private boolean shouldEnableHapByDefault(BluetoothDevice device, ParcelUuid[] uuids) { if (!Flags.enableHapByDefault()) { - Log.i(TAG, "shouldDefaultToHap: Flag enableHapByDefault is disabled"); + Log.i(TAG, "shouldEnableHapByDefault: Flag is disabled"); return false; } HapClientService hap = mFactory.getHapClientService(); if (hap == null) { - Log.e(TAG, "shouldDefaultToHap: HapClient is null"); + Log.e(TAG, "shouldEnableHapByDefault: No HapClientService"); + return false; + } + + if (!SystemProperties.getBoolean(SYSPROP_HAP_ENABLED, true)) { + Log.i(TAG, "shouldEnableHapByDefault: SystemProperty is overridden to false"); return false; } -- GitLab From df850d2a664e71d27f88d545e41f5432cb96bf39 Mon Sep 17 00:00:00 2001 From: William Escande Date: Wed, 6 Nov 2024 19:48:43 -0800 Subject: [PATCH 607/875] cpplint: fix and enable whitespace/ending_newline Bug: 364967694 Test: m . Flag: Exempt refactor Change-Id: Ie7050f0c432d1d82f68cb1c6fdde0af8d72700a6 --- CPPLINT.cfg | 2 -- OWNERS | 2 +- system/audio_bluetooth_hw/device_port_proxy_hidl.h | 2 +- .../le_audio/broadcaster/broadcast_configuration_provider.cc | 2 +- system/bta/le_audio/le_audio_log_history.h | 2 +- system/bta/le_audio/storage_helper.h | 2 +- system/btif/include/btif_keystore.h | 2 +- system/btif/include/btif_metrics_logging.h | 2 +- system/common/address_obfuscator.h | 2 +- system/common/id_generator.h | 2 +- system/common/id_generator_unittest.cc | 2 +- system/device/include/device_iot_conf_defs.h | 2 +- system/device/include/interop_database.h | 2 +- system/embdrv/encoder_for_aptx/src/CBStruct.h | 2 +- system/gd/common/audit_log.h | 2 +- system/gd/common/byte_array.h | 2 +- system/gd/common/list_map.h | 2 +- system/gd/common/numbers.h | 2 +- system/gd/common/numbers_test.cc | 2 +- system/gd/common/type_helper.h | 2 +- system/gd/hci/enum_helper.h | 2 +- system/gd/hci/hci_metrics_logging.h | 2 +- system/gd/hci/link_key.cc | 2 +- system/gd/hci/link_key.h | 2 +- system/gd/hci/remote_name_request.h | 2 +- system/gd/metrics/chromeos/metrics_allowlist.cc | 2 +- system/gd/metrics/chromeos/metrics_allowlist.h | 2 +- system/gd/metrics/counter_metrics.h | 2 +- system/gd/os/android/parameter_provider.cc | 2 +- system/gd/os/bt_keystore.h | 2 +- system/gd/os/files.h | 2 +- system/gd/os/host/system_properties.cc | 2 +- system/gd/os/linux_generic/files_test.cc | 2 +- system/gd/os/parameter_provider.h | 2 +- system/gd/os/rand.h | 2 +- system/gd/os/system_properties_common_test.cc | 2 +- system/gd/packet/custom_field_fixed_size_interface.h | 2 +- system/gd/storage/classic_device.cc | 2 +- system/gd/storage/config_cache_helper_test.cc | 2 +- system/gd/storage/le_device.cc | 2 +- system/gd/storage/le_device.h | 2 +- system/gd/storage/legacy_config_file.h | 2 +- system/gd/storage/legacy_config_file_test.cc | 2 +- system/gd/storage/mutation.cc | 2 +- system/gd/storage/mutation.h | 2 +- system/gd/storage/mutation_entry.cc | 2 +- system/gd/storage/mutation_entry.h | 2 +- system/gd/storage/mutation_test.cc | 2 +- system/gd/storage/serializable.h | 2 +- system/osi/include/properties.h | 2 +- system/packet/avrcp/avrcp_reject_packet.cc | 2 +- system/packet/avrcp/avrcp_reject_packet.h | 2 +- system/packet/avrcp/capabilities_packet.h | 2 +- system/packet/avrcp/change_path.h | 2 +- .../packet/avrcp/get_current_player_application_setting_value.h | 2 +- system/packet/avrcp/get_folder_items.h | 2 +- system/packet/avrcp/get_play_status_packet.h | 2 +- system/packet/avrcp/get_total_number_of_items.h | 2 +- .../packet/avrcp/list_player_application_setting_attributes.h | 2 +- system/packet/avrcp/list_player_application_setting_values.h | 2 +- system/packet/avrcp/pass_through_packet.h | 2 +- system/packet/avrcp/play_item.h | 2 +- system/packet/avrcp/register_notification_packet.h | 2 +- system/packet/avrcp/set_absolute_volume.h | 2 +- system/packet/avrcp/set_addressed_player.h | 2 +- system/packet/avrcp/set_browsed_player.h | 2 +- system/packet/avrcp/set_player_application_setting_value.h | 2 +- system/packet/avrcp/vendor_packet.h | 2 +- system/packet/base/packet_builder.h | 2 +- system/packet/include/avrcp_packet.h | 2 +- system/packet/include/packet.h | 2 +- system/packet/tests/avrcp/avrcp_browse_packet_test.cc | 2 +- system/packet/tests/avrcp/avrcp_packet_test.cc | 2 +- system/packet/tests/avrcp/avrcp_reject_packet_test.cc | 2 +- system/packet/tests/avrcp/change_path_packet_test.cc | 2 +- system/packet/tests/avrcp/get_capabilities_packet_test.cc | 2 +- .../avrcp/get_current_player_application_setting_value_test.cc | 2 +- system/packet/tests/avrcp/get_folder_items_packet_test.cc | 2 +- system/packet/tests/avrcp/get_play_status_packet_test.cc | 2 +- .../packet/tests/avrcp/get_total_number_of_items_packet_test.cc | 2 +- .../avrcp/list_player_application_setting_attributes_test.cc | 2 +- .../tests/avrcp/list_player_application_setting_values_test.cc | 2 +- system/packet/tests/avrcp/pass_through_packet_test.cc | 2 +- system/packet/tests/avrcp/set_absolute_volume_packet_test.cc | 2 +- system/packet/tests/avrcp/set_browsed_player_packet_test.cc | 2 +- .../tests/avrcp/set_player_application_setting_value_test.cc | 2 +- system/packet/tests/avrcp/vendor_packet_test.cc | 2 +- system/packet/tests/base/packet_builder_test.cc | 2 +- system/packet/tests/base/packet_test.cc | 2 +- system/stack/acl/acl.h | 2 +- system/stack/include/btu_hcif.h | 2 +- system/stack/test/ad_parser_unittest.cc | 2 +- system/stack/test/common/mock_btif_storage.h | 2 +- system/test/mock/mock_common_os_utils.h | 2 +- system/test/mock/mock_osi_mutex.h | 2 +- system/types/remote_version_type.h | 2 +- 96 files changed, 95 insertions(+), 97 deletions(-) diff --git a/CPPLINT.cfg b/CPPLINT.cfg index cc062661c71..23248637ae7 100644 --- a/CPPLINT.cfg +++ b/CPPLINT.cfg @@ -9,8 +9,6 @@ filter=-whitespace/newline # TODO: b/364967694 re-enable the warning filter=-whitespace/blank_line # TODO: b/364967694 re-enable the warning -filter=-whitespace/ending_newline -# TODO: b/364967694 re-enable the warning filter=-readability/check # TODO: b/364967694 re-enable the warning filter=-runtime/int diff --git a/OWNERS b/OWNERS index 491c4d0a382..bb6f4b95794 100644 --- a/OWNERS +++ b/OWNERS @@ -9,7 +9,7 @@ okamil@google.com #{LAST_RESORT_SUGGESTION} # Per-file ownership # Build files / test_config / presubmit / preupload / linter file -per-file PREUPLOAD.cfg,TEST_MAPPING,*.bp,*.xml,.clang-tidy,pyrightconfig.json=file:/OWNERS_build +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 diff --git a/system/audio_bluetooth_hw/device_port_proxy_hidl.h b/system/audio_bluetooth_hw/device_port_proxy_hidl.h index 640ff95fb1d..edc3e2a3edd 100644 --- a/system/audio_bluetooth_hw/device_port_proxy_hidl.h +++ b/system/audio_bluetooth_hw/device_port_proxy_hidl.h @@ -115,4 +115,4 @@ public: } // namespace hidl } // namespace audio } // namespace bluetooth -} // namespace android \ No newline at end of file +} // namespace android diff --git a/system/bta/le_audio/broadcaster/broadcast_configuration_provider.cc b/system/bta/le_audio/broadcaster/broadcast_configuration_provider.cc index 3f6c2ae600f..03e0e4ad4ff 100644 --- a/system/bta/le_audio/broadcaster/broadcast_configuration_provider.cc +++ b/system/bta/le_audio/broadcaster/broadcast_configuration_provider.cc @@ -76,4 +76,4 @@ BroadcastConfiguration GetBroadcastConfig( return lc3_mono_16_2_2; } } // namespace broadcaster -} // namespace bluetooth::le_audio \ No newline at end of file +} // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/le_audio_log_history.h b/system/bta/le_audio/le_audio_log_history.h index 5fa17350e20..1e85affc0ac 100644 --- a/system/bta/le_audio/le_audio_log_history.h +++ b/system/bta/le_audio/le_audio_log_history.h @@ -75,4 +75,4 @@ public: const std::string& msg) = 0; virtual void AddLogHistory(const std::string& tag, int group_id, const RawAddress& addr, const std::string& msg, const std::string& extra) = 0; -}; \ No newline at end of file +}; diff --git a/system/bta/le_audio/storage_helper.h b/system/bta/le_audio/storage_helper.h index 0f196024f79..85418457c97 100644 --- a/system/bta/le_audio/storage_helper.h +++ b/system/bta/le_audio/storage_helper.h @@ -31,4 +31,4 @@ bool SerializeAses(const LeAudioDevice* leAudioDevice, std::vector& out bool DeserializeAses(LeAudioDevice* leAudioDevice, const std::vector& in); bool SerializeHandles(const LeAudioDevice* leAudioDevice, std::vector& out); bool DeserializeHandles(LeAudioDevice* leAudioDevice, const std::vector& in); -} // namespace bluetooth::le_audio \ No newline at end of file +} // namespace bluetooth::le_audio diff --git a/system/btif/include/btif_keystore.h b/system/btif/include/btif_keystore.h index 460f3b8a4a6..83133a6eb81 100644 --- a/system/btif/include/btif_keystore.h +++ b/system/btif/include/btif_keystore.h @@ -22,4 +22,4 @@ namespace bluetooth_keystore { BluetoothKeystoreInterface* getBluetoothKeystoreInterface(); } // namespace bluetooth_keystore -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/btif/include/btif_metrics_logging.h b/system/btif/include/btif_metrics_logging.h index 00e3a337721..d68eddce5e7 100644 --- a/system/btif/include/btif_metrics_logging.h +++ b/system/btif/include/btif_metrics_logging.h @@ -66,4 +66,4 @@ 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); \ No newline at end of file +bool is_valid_id_from_metric_id_allocator(const int id); diff --git a/system/common/address_obfuscator.h b/system/common/address_obfuscator.h index 3caff715cae..4f60b4c6b9f 100644 --- a/system/common/address_obfuscator.h +++ b/system/common/address_obfuscator.h @@ -73,4 +73,4 @@ private: }; } // namespace common -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/common/id_generator.h b/system/common/id_generator.h index e404ff4585a..7c6425aeef7 100644 --- a/system/common/id_generator.h +++ b/system/common/id_generator.h @@ -45,4 +45,4 @@ private: }; template -int IdGenerator::ALL_USED = -1; \ No newline at end of file +int IdGenerator::ALL_USED = -1; diff --git a/system/common/id_generator_unittest.cc b/system/common/id_generator_unittest.cc index d56ee1971f0..7b090cf3653 100644 --- a/system/common/id_generator_unittest.cc +++ b/system/common/id_generator_unittest.cc @@ -34,4 +34,4 @@ TEST(IdGeneratorTest, sanity_test) { generator.Release(2); ASSERT_EQ(0, generator.GetNext()); ASSERT_EQ(2, generator.GetNext()); -} \ No newline at end of file +} diff --git a/system/device/include/device_iot_conf_defs.h b/system/device/include/device_iot_conf_defs.h index 4132deab545..09c576d9ae1 100644 --- a/system/device/include/device_iot_conf_defs.h +++ b/system/device/include/device_iot_conf_defs.h @@ -104,4 +104,4 @@ #define IOT_CONF_BYTE_NUM_1 1 #define IOT_CONF_BYTE_NUM_2 2 #define IOT_CONF_BYTE_NUM_3 3 -#define IOT_CONF_BYTE_NUM_4 4 \ No newline at end of file +#define IOT_CONF_BYTE_NUM_4 4 diff --git a/system/device/include/interop_database.h b/system/device/include/interop_database.h index b6c0ae1994f..8e7196f0fc9 100644 --- a/system/device/include/interop_database.h +++ b/system/device/include/interop_database.h @@ -48,4 +48,4 @@ typedef struct { uint16_t vendor_id; uint16_t product_id; interop_feature_t feature; -} interop_hid_multitouch_t; \ No newline at end of file +} interop_hid_multitouch_t; diff --git a/system/embdrv/encoder_for_aptx/src/CBStruct.h b/system/embdrv/encoder_for_aptx/src/CBStruct.h index eb968d66501..7be89439797 100644 --- a/system/embdrv/encoder_for_aptx/src/CBStruct.h +++ b/system/embdrv/encoder_for_aptx/src/CBStruct.h @@ -37,4 +37,4 @@ typedef struct circularBuffer_t { #ifdef _GCC #pragma GCC visibility pop #endif -#endif // CBSTRUCT_H \ No newline at end of file +#endif // CBSTRUCT_H diff --git a/system/gd/common/audit_log.h b/system/gd/common/audit_log.h index 7ce403e9310..b129bc74116 100644 --- a/system/gd/common/audit_log.h +++ b/system/gd/common/audit_log.h @@ -25,4 +25,4 @@ void LogConnectionAdminAuditEvent(const char* action, const hci::Address& addres hci::ErrorCode status); } // namespace common -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/gd/common/byte_array.h b/system/gd/common/byte_array.h index 29c58d8d8d2..b7183c4d2d6 100644 --- a/system/gd/common/byte_array.h +++ b/system/gd/common/byte_array.h @@ -74,4 +74,4 @@ public: }; } // namespace common -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/gd/common/list_map.h b/system/gd/common/list_map.h index 802602bde73..1b633028060 100644 --- a/system/gd/common/list_map.h +++ b/system/gd/common/list_map.h @@ -200,4 +200,4 @@ private: }; } // namespace common -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/gd/common/numbers.h b/system/gd/common/numbers.h index 826615a71f2..e31bebbee3a 100644 --- a/system/gd/common/numbers.h +++ b/system/gd/common/numbers.h @@ -44,4 +44,4 @@ bool IsNumberInNumericLimits(InputType input) { } } // namespace common -} // namespace bluetooth \ No newline at end of file +} // namespace bluetooth diff --git a/system/gd/common/numbers_test.cc b/system/gd/common/numbers_test.cc index ee1b92a87be..bf4159f934f 100644 --- a/system/gd/common/numbers_test.cc +++ b/system/gd/common/numbers_test.cc @@ -34,4 +34,4 @@ TEST(NumbersTest, test_is_number_in_numeric_limits) { ASSERT_FALSE(IsNumberInNumericLimits(int32_t(-129))); } -} // namespace testing \ No newline at end of file +} // namespace testing diff --git a/system/gd/common/type_helper.h b/system/gd/common/type_helper.h index 74991fbade2..2f4a9d74fee 100644 --- a/system/gd/common/type_helper.h +++ b/system/gd/common/type_helper.h @@ -28,4 +28,4 @@ template